/* Inter variable 100–900 — the same UI face and subset split used by Untitled UI React.
   Self-hosted so production has no Google Fonts/runtime network dependency. */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./fonts/inter-vietnamese.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169,
    U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309,
    U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
    U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC,
    U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Mirrors the metric-adjusted fallback generated on the Untitled UI site. */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  ascent-override: 90.44%;
  descent-override: 22.52%;
  line-gap-override: 0%;
  size-adjust: 107.12%;
}

/* ==== Peram UI Library — tokens/colors.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Colors — surface / text / accent / semantic. Neutral scale = Tailwind Zinc,
   accent scale = Tailwind Blue. Verbatim from SSOT (SURFACE_LIGHT / SURFACE_DARK). */

:root {
  /* Backgrounds */
  --ptui-bg: #f6f7f9;
  --ptui-bg-elevated: #ffffff;
  --ptui-bg-subtle: #f1f2f4;
  --ptui-bg-muted: #ebecef;
  --ptui-surface: #ffffff;
  --ptui-surface-hover: #f6f7f9;

  /* Borders */
  --ptui-border: #e2e4e8;
  --ptui-border-strong: #cbcfd4;
  --ptui-border-focus: #2563eb;

  /* Text.
     LUAT DUNG --ptui-text-muted (do 2026-08-14, khoa bang tests/contrast.test.mjs):
     muted CHI dat WCAG AA tren --ptui-bg (4.51) va --ptui-surface (4.83).
     Tren nen DAM HON surface no TRUOT: bg-subtle 4.31 / bg-muted 4.09.
     => Nen dam hon surface (bg-subtle, bg-muted, *-soft, hang duoc chon) thi chu phu
     PHAI len bac --ptui-text-secondary (9.32 / 8.84). Giu muted o zinc-500 la co y:
     len zinc-600 se dat AA moi nen nhung khoang cach voi secondary tut con 1.35,
     hai bac chu gan nhu khong phan biet duoc — hong thang chu 4 bac. */
  --ptui-text: #09090b;
  --ptui-text-secondary: #3f3f46;
  --ptui-text-muted: #71717a;
  --ptui-text-subtle: #a1a1aa;
  --ptui-text-on-accent: #ffffff;

  /* Accent (Tailwind Blue) */
  --ptui-accent: #2563eb;
  --ptui-accent-hover: #1d4ed8;
  --ptui-accent-pressed: #1e40af;
  --ptui-accent-soft: #eff6ff;
  --ptui-accent-soft-hover: #dbeafe;
  --ptui-accent-ring: rgba(37, 99, 235, 0.18);

  /* Semantic — naming is "danger", not "error".
     Thang -700 (khong phai -600): 3 mau nay duoc dung lam CHU tren nen *-soft
     (.ptui-badge-*, .ptui-confirm-ico-*, .ptui-menu-item--danger, .ptui-field-req).
     O -600 badge light truot WCAG AA 4.5:1 — danger 4.41 / warning 3.07 / success 3.15.
     Len -700: 5.91 / 4.84 / 4.79 = dat AA. Doi xung voi dark (badge dung thang -400).
     Nut dac .ptui-btn-danger hardcode gradient rieng nen dien mao nut KHONG doi. */
  --ptui-danger: #b91c1c;
  --ptui-danger-soft: #fef2f2;
  --ptui-success: #15803d;
  --ptui-success-soft: #f0fdf4;
  --ptui-warning: #b45309;
  --ptui-warning-soft: #fffbeb;
}

[data-theme="dark"] {
  --ptui-bg: #09090b;
  --ptui-bg-elevated: #0f0f10;
  --ptui-bg-subtle: #131316;
  --ptui-bg-muted: #18181b;
  --ptui-surface: #101012;
  --ptui-surface-hover: #18181b;

  --ptui-border: #27272a;
  --ptui-border-strong: #3f3f46;
  --ptui-border-focus: #3b82f6;

  --ptui-text: #fafafa;
  --ptui-text-secondary: #d4d4d8;
  --ptui-text-muted: #a1a1aa;
  --ptui-text-subtle: #71717a;
  /* DAO sang chu TOI o dark (2026-08-14). Accent dark (#3b82f6) SANG HON accent light
     (#2563eb), nen chu trang tren nut primary chi dat 3.68 va o trang thai hover
     (#60a5fa) con 2.54 — nhan nut 14px/650 la chu thuong nen nguong la 4.5, khong
     phai 3. Chu toi: 5.41 / 7.83. Keo theo dung huong 2 noi khac cung dung token nay:
     .pill-tab.is-active .pill-tab-count (extras.css) va .ptui-kbc-av. */
  --ptui-text-on-accent: #09090b;

  --ptui-accent: #3b82f6;
  --ptui-accent-hover: #60a5fa;
  /* Trong theme TOI, "dang nhan" phai SANG len chu khong toi di. Gia tri cu #2563eb
     chep tu light: voi chu toi chi 3.85 (va lam vien nut chi 3.68 tren surface).
     Di tiep thang blue theo huong sang dan (600 -> 500 -> 400 -> 300) = #93c5fd:
     nen + chu toi 11.03, lam vien tren surface 10.54. */
  --ptui-accent-pressed: #93c5fd;
  --ptui-accent-soft: rgba(59, 130, 246, 0.10);
  --ptui-accent-soft-hover: rgba(59, 130, 246, 0.18);
  --ptui-accent-ring: rgba(59, 130, 246, 0.30);

  /* Semantic o DARK len thang -400 (2026-08-14). Truoc day khoi nay CHI override 3
     token *-soft, nen 3 mau foreground ke thua nguyen gia tri light (-700) va bi dat
     len nen gan den: danger 3.07 / success 3.97 / warning 3.96 tren --ptui-bg (tren
     --ptui-surface con thap hon: 2.94 / 3.79 / 3.78). Day la y dinh thiet ke da ghi
     trong khoi :root ("doi xung voi dark, badge dung thang -400") nhung chua bao gio
     duoc viet ra. Nay viet ra: 7.19 / 11.42 / 9.39.
     Gia tri trung khop san voi override badge dark trong components.css
     (.ptui-badge-success/-warning/-danger) — day la dua token ve dung quy uoc ma
     component da tu lam rieng le, KHONG phai them mau moi vao he. */
  --ptui-danger: #f87171;
  --ptui-success: #4ade80;
  --ptui-warning: #fbbf24;

  /* Semantic soft tints flip to translucent in dark (used by badges, action
     icons, confirm icons, etc.) so they read on the near-black surface. */
  --ptui-danger-soft: rgba(220, 38, 38, 0.16);
  --ptui-success-soft: rgba(22, 163, 74, 0.16);
  --ptui-warning-soft: rgba(217, 119, 6, 0.16);
}

/* ==== Peram UI Library — tokens/status.css (verbatim tu peram-ui-platform-ver6) ==== */
/* DIEU CHINH thu vien (Peram UI Library): nhom token 10 tone status --ptui-st-*
   port tu @peram-ui/design-tokens 0.4.0 (nguon ui-core da xoa) — sample ver6 KHONG co
   nhom nay. Dung cho .pill-tab--{tone} (extras.css) va moi UI to mau theo trang thai.
   Dark override chi doi -bg/-fg (mau goc giu nguyen lam dot/border). */
:root {
  --ptui-st-all: #6366f1;
  --ptui-st-all-fg: #4f46e5;
  --ptui-st-all-bg: #eef2ff;
  --ptui-st-gray: #64748b;
  --ptui-st-gray-fg: #475569;
  --ptui-st-gray-bg: #f1f5f9;
  --ptui-st-blue: #2563eb;
  --ptui-st-blue-fg: #1d4ed8;
  --ptui-st-blue-bg: #eff6ff;
  --ptui-st-amber: #f59e0b;
  --ptui-st-amber-fg: #b45309;
  --ptui-st-amber-bg: #fffbeb;
  --ptui-st-purple: #9333ea;
  --ptui-st-purple-fg: #7e22ce;
  --ptui-st-purple-bg: #faf5ff;
  --ptui-st-teal: #0d9488;
  --ptui-st-teal-fg: #0f766e;
  --ptui-st-teal-bg: #f0fdfa;
  --ptui-st-green: #16a34a;
  --ptui-st-green-fg: #15803d;
  --ptui-st-green-bg: #f0fdf4;
  --ptui-st-red: #dc2626;
  --ptui-st-red-fg: #b91c1c;
  --ptui-st-red-bg: #fef2f2;
  --ptui-st-orange: #ea580c;
  --ptui-st-orange-fg: #c2410c;
  --ptui-st-orange-bg: #fff7ed;
  --ptui-st-cyan: #0891b2;
  --ptui-st-cyan-fg: #0e7490;
  --ptui-st-cyan-bg: #ecfeff;
}

[data-theme="dark"] {
  --ptui-st-all-bg: rgba(99, 102, 241, 0.18);
  --ptui-st-all-fg: #c7d2fe;
  --ptui-st-gray-bg: rgba(100, 116, 139, 0.18);
  --ptui-st-gray-fg: #cbd5e1;
  --ptui-st-blue-bg: rgba(37, 99, 235, 0.18);
  --ptui-st-blue-fg: #bfdbfe;
  --ptui-st-amber-bg: rgba(245, 158, 11, 0.18);
  --ptui-st-amber-fg: #fde68a;
  --ptui-st-purple-bg: rgba(147, 51, 234, 0.18);
  --ptui-st-purple-fg: #e9d5ff;
  --ptui-st-teal-bg: rgba(13, 148, 136, 0.18);
  --ptui-st-teal-fg: #99f6e4;
  --ptui-st-green-bg: rgba(22, 163, 74, 0.18);
  --ptui-st-green-fg: #bbf7d0;
  --ptui-st-red-bg: rgba(220, 38, 38, 0.18);
  --ptui-st-red-fg: #fecaca;
  --ptui-st-orange-bg: rgba(234, 88, 12, 0.18);
  --ptui-st-orange-fg: #fed7aa;
  --ptui-st-cyan-bg: rgba(8, 145, 178, 0.18);
  --ptui-st-cyan-fg: #a5f3fc;
}

/* ==== Peram UI Library — tokens/typography.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Typography — exact Untitled UI React stacks. Inter for all product UI;
   monospace is reserved for source code. No separate display/data face. */

:root {
  --ptui-font-sans: "Inter", "Inter Fallback", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --ptui-font-mono: ui-monospace, "Roboto Mono", SFMono-Regular, Menlo, Monaco,
    Consolas, "Liberation Mono", "Courier New", monospace;
}

/* ==== Peram UI Library — tokens/typescale.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Thang chữ — thêm ở 0.15.0.
   ĐẶT Ở FILE RIÊNG, không sửa `tokens/typography.css`: file đó vẫn phải trùng md5
   với sample ver6 theo hợp đồng verbatim. `typography.css` chỉ khai báo hai họ
   font; nó KHÔNG hề có một token cỡ chữ nào — đó chính là lỗ hổng file này lấp.

   CĂN CỨ, đo được chứ không phải chọn cho đẹp:
   - Đo `getComputedStyle` trên 445 phần tử có chữ của library: **22 cỡ khác nhau**,
     kèm nửa-pixel 10.5 / 11.5 / 12.5 / 13.5 và giá trị lẻ 12.3 / 12.48 / 15.2 / 28.5.
     Đó không phải một thang, mà là chỉnh tay từng chỗ.
   - Đối chiếu: Fluent 2 ramp có **10** bậc (10/12/14/16/20/24/28/32/40/68);
     Material 3 dùng **11** cỡ cho 15 vai trò; Untitled UI có **9** bậc.
   - Bốn bậc 11/12/13/14 chiếm phần lớn lượt dùng thực tế (39 + 98 + 52 + 104 lần),
     nên thang giữ đủ cả bốn thay vì ép về 12/14 rồi làm vỡ mật độ bảng biểu.

   ĐỘ ĐẬM: đo được **8 giá trị** (400/500/600/620/650/700/750/800/900). Fluent 2
   chỉ dùng 400/600/700; Material 3 dùng 400/500/700. Các mốc 620/650/750/850 là số
   tự chế, không mốc nào của Inter cần tới chúng. Rút về **ba** bậc.

   Inter là font variable 100–900 nên mọi bậc đều là nét thật, không phải nét giả
   do trình duyệt bôi đậm. */

:root {
  /* Cỡ chữ — 8 bậc */
  --ptui-text-xs: 11px;    /* nhãn phụ, đơn vị, chú thích trong bảng */
  --ptui-text-sm: 12px;    /* badge, tag, chú thích, header bảng */
  --ptui-text-md: 13px;    /* nhãn điều khiển, nút, mô tả phụ */
  --ptui-text-base: 14px;  /* chữ thân bài mặc định */
  --ptui-text-lg: 16px;    /* nhấn mạnh, tiêu đề dialog/panel */
  --ptui-text-xl: 20px;    /* tiêu đề mục */
  --ptui-text-2xl: 24px;   /* tiêu đề trang */
  --ptui-text-3xl: 28px;   /* số liệu lớn, display */

  /* Độ đậm — 3 bậc, theo Fluent 2 */
  --ptui-weight-regular: 400;
  --ptui-weight-medium: 600;
  --ptui-weight-bold: 700;
}

/* ==== Peram UI Library — tokens/layout.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Layout constants + radius + z-index ladder. Verbatim from SSOT (SHARED). */

:root {
  /* Radius scale */
  --ptui-radius-sm: 6px;
  --ptui-radius: 10px;
  --ptui-radius-lg: 14px;
  --ptui-radius-xl: 20px;

  /* Layout dimensions */
  --ptui-rail-width: 64px;
  --ptui-sidebar-width: 260px;
  --ptui-sidebar-collapsed-width: 84px;
  --ptui-control-height: 44px;

  /* Z-index ladder (single source of truth) */
  --ptui-z-sidebar: 30; /* @kind other */
  --ptui-z-rail: 31; /* @kind other */
}

/* ==== Peram UI Library — tokens/zindex.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Z-index ladder — thang xep lop DAY DU cho moi overlay.

   DIEU CHINH thu vien (khong co trong sample ver6) — tach file rieng thay vi sua
   tokens/layout.css de layout.css giu md5 trung sample. Cung co che voi status.css.

   LY DO TON TAI (bug that, do duoc truoc 0.13.0):
   - components.css:1388 doc `var(--ptui-z-tip, 900)` va :1415 doc `var(--ptui-z-toast, 1100)`
     nhung KHONG file token nao khai hai bien nay => luon roi ve fallback.
   - Hau qua 1: tooltip (900) < modal-overlay (1000, hardcode) => tooltip dat trong Modal
     bi chinh Modal che khuat.
   - Hau qua 2: backdrop sidebar mobile (1001, components.css:256) > modal-overlay (1000)
     => mo Modal khi sidebar mobile dang mo thi Modal nam DUOI backdrop.
   Khai bao o day sua ca hai ma KHONG phai dung vao components.css (cac rule da doc var san).
   Rieng hai cho hardcode (.ptui-modal-overlay, .ptui-menu) duoc override trong extras.css.

   THANG (thap -> cao). Buoc nhay 10 de con cho chen tang moi ma khong danh so lai:
     sidebar 30 / rail 31            (layout.css — giu nguyen, khong dung toi)
     popover 1000                    menu, dropdown, date popover, select
     sticky-banner 1050              banner thong bao ghim dau trang
     modal 1100                      modal overlay + drawer/slideout + backdrop sidebar mobile
     toast 1200                      toast stack — luon tren modal (bao ket qua thao tac trong modal)
     tooltip 1300                    tooltip — luon tren cung (co the bat trong modal LAN trong toast)
     drag-ghost 1400                 anh keo-tha cua DataTable/Kanban — bay tren tat ca
   Quy tac: tooltip PHAI cao nhat sau drag-ghost; toast PHAI tren modal. Doi thu tu nay
   la tai lap dung bug da sua — tests/v013.test.mjs khoa lai bang assert so hoc. */

:root {
  --ptui-z-popover: 1000; /* @kind other */
  --ptui-z-sticky-banner: 1050; /* @kind other */
  --ptui-z-modal: 1100; /* @kind other */
  /* 0.21.2 (04/09/2026): lop noi PORTAL (`--fixed` cua menu/multiselect/date/dt-pop, tu 0.18.0)
     la anh em cua modal trong <body> nen phai DUNG TREN modal (1100) va DUOI toast (1200) —
     bug do duoc o ATS: MultiSelect trong Modal mo ra nhung nam sau overlay, khong chon duoc. */
  --ptui-z-popover-floating: 1150; /* @kind other */
  --ptui-z-toast: 1200; /* @kind other */
  --ptui-z-tip: 1300; /* @kind other */
  --ptui-z-drag-ghost: 1400; /* @kind other */
}

/* ==== Peram UI Library — tokens/effects.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Effects — shadow (slate-tinted, subtle) + motion (duration + easing).
   Verbatim from SSOT (SHARED). */

:root {
  /* Shadows */
  --ptui-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.06);
  --ptui-shadow-md: 0 4px 14px -3px rgba(15, 23, 42, 0.10), 0 2px 6px -2px rgba(15, 23, 42, 0.06);
  --ptui-shadow-lg: 0 24px 56px -14px rgba(15, 23, 42, 0.18), 0 10px 20px -10px rgba(15, 23, 42, 0.08);

  /* Motion */
  --ptui-duration-fast: 150ms; /* @kind other */
  --ptui-duration-normal: 200ms; /* @kind other */
  --ptui-duration-slow: 300ms; /* @kind other */
  --ptui-ease-standard: cubic-bezier(0.22, 0.61, 0.36, 1); /* @kind other */
  --ptui-ease-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1); /* @kind other */
  --ptui-ease-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15); /* @kind other */
}

/* ==== Peram UI Library — tokens/flat.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Ngon ngu thi giac 2D (0.14.0) — token cho be mat phang.

   DIEU CHINH thu vien (khong co trong sample ver6). Tach file rieng thay vi sua
   colors.css / effects.css de HAI FILE DO GIU MD5 TRUNG SAMPLE. Cung co che voi
   status.css va zindex.css. File nay dat SAU "effects" trong TOKEN_ORDER nen
   phan override shadow o duoi thang gia tri cu.

   ===========================================================================
   VI SAO DOI: nut cu trong "3D" — do duoc 4 tang chong len nhau:
     (1) 9 linear-gradient 180deg sang→toi tren nut (van khoi kinh dien)
     (2) shadow 2 lop CO GLOW MAU (nut primary do bong xanh rgba(37,99,235,.22))
     (3) translateY(1px) khi :active + filter: brightness() khi :hover
     (4) inset highlight trang o mep tren (kanban board, progress track)
   Radix Themes gom DUNG 4 thu phap nay vao mot variant va dat ten `classic`.
   Fluent 2 va Material 3 deu co grep gradient tren nut = 0.

   CHIEU SAU LAY TU DAU NEU BO BONG: tu PHAN TANG NEN.
   Fluent dung 6 bac neutralBackground (moi bac chenh ~5 don vi RGB);
   M3 dung 5 bac surface-container. He Peram da co san thang do:
   bg #f6f7f9 · bg-subtle #f1f2f4 · bg-muted #ebecef · surface #ffffff.
   =========================================================================== */

:root {
  /* --- Nut primary: TRUNG TINH, khong phai mau thuong hieu -----------------
     User chot huong Vercel/shadcn/Polaris: nut chinh mau trung tinh thay vi xanh.
     LY DO TACH TOKEN RIENG, khong sua --ptui-accent: token accent dang nuoi
     badge / alert / banner / featured-icon / pill-tab / focus ring. Doi no thanh
     den se bien TAT CA nhung thu do thanh den. Accent giu nguyen vai tro "mau
     trang thai + link + focus"; nut chinh co token rieng. Day dung cach shadcn
     tach --primary khoi --accent/--ring.

     Gia tri nam tren thang ZINC ma he DA dung (text #09090b, secondary #3f3f46,
     bg-muted dark #18181b) — KHONG phai hue moi.
     Contrast do duoc: #fafafa tren #18181b = 16.8:1 (AA can 4.5). */
  --ptui-btn-primary-bg: #18181b; /* zinc-900 */
  --ptui-btn-primary-bg-hover: #27272a; /* zinc-800 — SANG len, vi da gan den tuyet doi */
  --ptui-btn-primary-bg-active: #3f3f46; /* zinc-700 */
  --ptui-btn-primary-fg: #fafafa;

  /* Nut danger: truoc 0.14 components.css:307 HARDCODE
     `linear-gradient(180deg,#ef4444,#dc2626)` nen dot 0.5.0 nang semantic len
     thang -700 da khong cham toi no. Nay khai thanh token de con sua duoc. */
  --ptui-btn-danger-bg: var(--ptui-danger);
  --ptui-btn-danger-bg-hover: #991b1b; /* red-800 */
  --ptui-btn-danger-bg-active: #7f1d1d; /* red-900 */
  --ptui-btn-danger-fg: #ffffff;

  /* --- Vien nut ------------------------------------------------------------
     Fluent giu `1px solid transparent` o MOI variant => doi variant hay doi
     state thi box model khong doi, nut khong nhay 1px. Ta lam theo. */
  --ptui-btn-border: var(--ptui-border-strong);
  --ptui-btn-border-hover: var(--ptui-text-muted);

  /* --- Shadow PHANG --------------------------------------------------------
     Cong thuc Fluent: moi shadow la CAP "ambient toa deu (0 0 Npx, khong offset)"
     + "key do xuong (0 Ypx 2Ypx)". Alpha toi da 0.14 o light. Offset thuan truc Y
     — khong bao gio co offset X nen khong gia lap nguon sang xien.
     Gia tri cu: shadow-lg co Y=56px (qua noi). Nay Y toi da 16px.
     Ba token nay GHI DE effects.css (file nay dung sau trong TOKEN_ORDER). */
  --ptui-shadow-sm: 0 0 2px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.08);
  --ptui-shadow-md: 0 0 2px rgba(15, 23, 42, 0.06), 0 4px 8px rgba(15, 23, 42, 0.10);
  --ptui-shadow-lg: 0 0 2px rgba(15, 23, 42, 0.08), 0 8px 16px rgba(15, 23, 42, 0.12);

  /* Bong rieng cho control nen-trang: chi de tach no khoi nen trang cua trang.
     Nut solid/primary KHONG dung cai nay — Radix/Geist/shadcn deu 0 shadow. */
  --ptui-shadow-control: 0 1px 2px rgba(15, 23, 42, 0.05);

  /* --- Thang O CHUA ICON ---------------------------------------------------
     Truoc 0.14 he co 10 co che roi rac: 9 kich thuoc (20/24/28/32/36/40/44/52/54)
     va 6 radius (50% · 999px · 6px · 10px · 12px hardcode · 14px) cho CUNG mot
     khai niem. 52 va 54 chi cach nhau 2px — nhin nhu go nham.
     Nay con 3 bac, 1 quy tac radius. 44 la bac day nhat truoc day (featured /
     confirm / uploader / file-icon) nen giu lam bac "md". */
  --ptui-icon-box-sm: 32px;
  --ptui-icon-box-md: 44px;
  --ptui-icon-box-lg: 56px;

  /* --- State layer (co che Material 3) -------------------------------------
     M3 KHONG co bang mau hover/active rieng cho tung tone: no phu mot lop
     on-color ban trong suot len nen, dung 3 con so nay cho TOAN he. Nho vay
     them mot tone mau moi KHONG phai tu che hover/active cho no.
     He Peram dang co 6 tone .ptui-actionbtn, moi tone tu tinh color-mix rieng —
     day chinh la cho se duoc don. */
  --ptui-state-hover: 0.08;
  --ptui-state-focus: 0.12;
  --ptui-state-pressed: 0.12;
  /* Disabled: M3 chuan hoa 0.38 cho noi dung / 0.12 cho nen, thay vi mau xam rieng */
  --ptui-state-disabled-content: 0.38;
  --ptui-state-disabled-container: 0.12;

  /* --- Motion --------------------------------------------------------------
     Chi transition mau, KHONG transition transform (Fluent:
     transitionProperty = 'background, border, color'). Nut khong nhuc nhich. */
  --ptui-btn-transition: background-color 120ms var(--ptui-ease-standard),
    border-color 120ms var(--ptui-ease-standard), color 120ms var(--ptui-ease-standard);
}

[data-theme="dark"] {
  /* Nut primary DAO CHIEU o dark — dung nhu Vercel/shadcn: nen sang, chu toi.
     Neu giu nen den o nen gan den (#09090b) thi nut bien mat. */
  --ptui-btn-primary-bg: #fafafa;
  --ptui-btn-primary-bg-hover: #e4e4e7; /* zinc-200 */
  --ptui-btn-primary-bg-active: #d4d4d8; /* zinc-300 */
  --ptui-btn-primary-fg: #18181b;

  /* Dark: danger la #f87171 (SANG) => chu phai TOI, va hover/active sang dan
     thay vi toi dan — cung logic dao chieu nhu nut primary. */
  --ptui-btn-danger-bg: var(--ptui-danger);
  --ptui-btn-danger-bg-hover: #fca5a5; /* red-300 */
  --ptui-btn-danger-bg-active: #fecaca; /* red-200 */
  --ptui-btn-danger-fg: #18181b;

  --ptui-btn-border: var(--ptui-border-strong);
  --ptui-btn-border-hover: var(--ptui-text-muted);

  /* Bong slate-tinted gan nhu vo hinh tren nen gan den — o dark phai dam hon
     (Fluent: alpha key 0.14 → 0.28 khi sang dark). Truoc 0.14 he KHONG co ban
     dark cho shadow nen 3 token nay ke thua nguyen gia tri light. */
  --ptui-shadow-sm: 0 0 2px rgba(0, 0, 0, 0.24), 0 1px 2px rgba(0, 0, 0, 0.28);
  --ptui-shadow-md: 0 0 2px rgba(0, 0, 0, 0.24), 0 4px 8px rgba(0, 0, 0, 0.32);
  --ptui-shadow-lg: 0 0 2px rgba(0, 0, 0, 0.28), 0 8px 16px rgba(0, 0, 0, 0.40);
  --ptui-shadow-control: 0 1px 2px rgba(0, 0, 0, 0.28);
}

/* ==== Peram UI Library — tokens/intent.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Mau nut theo Y NGHIA (0.20.0) — DIEU CHINH thu vien, khong co trong sample ver6.

   File RIENG, dat SAU "flat" trong TOKEN_ORDER nen 4 token --ptui-btn-primary-*
   o duoi GHI DE flat.css (cung co che flat.css ghi de effects.css). Khong sua
   flat.css de no giu nguyen lich su 0.14.0 va md5.

   ===========================================================================
   VI SAO DOI (04/09/2026, chu du an dao quyet dinh 0.14.0):
   Nut primary den zinc-900 (kieu Vercel/shadcn) bi chu du an che xau tren
   Peram Talent ATS. Doi ve MAU THUONG HIEU (--ptui-accent, xanh Tailwind Blue)
   — dung chuan Material 3 (filled = primary/brand), Fluent 2 (primary =
   brand blue #0f6cbd), Carbon (Blue 60), Atlassian (#1868db).

   NGUYEN TAC MAU NUT (docs/DESIGN-PRINCIPLES.md ch.2 la SSOT chu, day la
   ban tom tat de nguoi doc token khong phai mo doc):
     primary  = xanh thuong hieu  -> tao moi / luu / gui / xac nhan tich cuc
     success  = xanh la           -> CHI cho DUYET / CHAP NHAN trong cap
                                     quyet dinh (dung canh nut danger "Tu choi")
     danger   = do                -> xoa / tu choi / huy-ban-ghi (pha huy)
     warning  = amber             -> hanh dong can can nhac (tam khoa, thu hoi,
                                     gui lai qua han). KHONG dung cho "Gui".
     outline  = vien xanh         -> sua / hanh dong phu co nhan manh nhe
     ghost    = khong vien        -> xem / chi tiet
     (tran)   = trang, vien mong  -> huy (dong form) / quay lai / phu
   Cam: primary den; submit mau cam (cam = canh bao o moi he); cancel-dong-form
   mau do (do la pha huy).

   CONTRAST (WCAG 2.1 AA text 4.5:1, chu nut 14px/600 = chu THUONG):
     light: #fff tren #2563eb 5.17 · #15803d 5.02 · #b45309 5.02 · #b91c1c 5.91
     dark : #09090b tren #3b82f6 5.41 · #4ade80 12.3 · #fbbf24 11.6
   Hover/active o light TOI dan (thang -800/-900), o dark SANG dan (thang
   -300/-200) — cung logic dao chieu nhu nut danger trong flat.css.
   tests/v0200.test.mjs tinh lai cac so nay tu dist, khong tin comment.
   =========================================================================== */

:root {
  --ptui-btn-primary-bg: var(--ptui-accent);
  --ptui-btn-primary-bg-hover: var(--ptui-accent-hover);
  --ptui-btn-primary-bg-active: var(--ptui-accent-pressed);
  --ptui-btn-primary-fg: var(--ptui-text-on-accent);

  --ptui-btn-success-bg: var(--ptui-success); /* green-700 */
  --ptui-btn-success-bg-hover: #166534; /* green-800 */
  --ptui-btn-success-bg-active: #14532d; /* green-900 */
  --ptui-btn-success-fg: #ffffff;

  --ptui-btn-warning-bg: var(--ptui-warning); /* amber-700 */
  --ptui-btn-warning-bg-hover: #92400e; /* amber-800 */
  --ptui-btn-warning-bg-active: #78350f; /* amber-900 */
  --ptui-btn-warning-fg: #ffffff;
}

[data-theme="dark"] {
  --ptui-btn-primary-bg: var(--ptui-accent);
  --ptui-btn-primary-bg-hover: var(--ptui-accent-hover);
  --ptui-btn-primary-bg-active: var(--ptui-accent-pressed);
  --ptui-btn-primary-fg: var(--ptui-text-on-accent);

  --ptui-btn-success-bg: var(--ptui-success); /* green-400 (sang) => chu toi */
  --ptui-btn-success-bg-hover: #86efac; /* green-300 */
  --ptui-btn-success-bg-active: #bbf7d0; /* green-200 */
  --ptui-btn-success-fg: #09090b;

  --ptui-btn-warning-bg: var(--ptui-warning); /* amber-400 (sang) => chu toi */
  --ptui-btn-warning-bg-hover: #fcd34d; /* amber-300 */
  --ptui-btn-warning-bg-active: #fde68a; /* amber-200 */
  --ptui-btn-warning-fg: #09090b;
}

/* ==== Peram UI Library — tokens/motion.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Motion tokens (0.14.0) — thang thoi luong + easing co TEN, de moi chuyen dong
   trong he deu tra ve cung mot bang, thay vi moi cho tu doan mot con so.

   DIEU CHINH thu vien (khong co trong sample ver6). File rieng de effects.css giu
   md5 trung sample. Dat sau "flat" trong TOKEN_ORDER.

   ===========================================================================
   CAN CU (source that):
   - Material 3 `md-sys-motion`: short1-4 = 50/100/150/200ms · medium1-4 =
     250/300/350/400ms · long1-4 = 450/500/550/600ms.
     easing emphasized `cubic-bezier(0.2,0,0,1)` · emphasized-decelerate
     `(0.05,0.7,0.1,1)` · emphasized-accelerate `(0.3,0,0.8,0.15)`.
   - Fluent 2: nut chi transition `background, border, color` — KHONG transition
     transform. Duration cua Fluent rat ngan (durationFaster ~100ms).
   - Luat vang (ca hai he): ENTER dung ease-OUT (vat dang dung lai),
     EXIT dung ease-IN va NHANH HON enter (vat bien mat thi dut khoat).
   ===========================================================================

   HE DA CO SAN o effects.css: --ptui-duration-fast/normal/slow (150/200/300ms)
   va 3 easing standard/decelerate/accelerate. File nay KHONG ghi de chung — chi
   BO SUNG cac bac con thieu va cac keyframe-driven duration. */

:root {
  /* Bac cuc ngan cho micro-interaction (hover nut, doi mau). Fluent dung muc nay
     cho nut; 150ms cua he hoi cham cho viec chi doi mau. */
  --ptui-duration-instant: 100ms; /* @kind other */
  /* Bac dai cho chuyen dong lon (drawer, bottom-sheet, page transition) */
  --ptui-duration-slower: 400ms; /* @kind other */

  /* --- Thoi luong CO NGU NGHIA (dung ten viec, khong dung ten do dai) --------
     Muc dich: doc code la biet dang noi ve cai gi. `--ptui-motion-toast-life`
     ro nghia hon `5000ms` nam tran trong JSX. */

  /* Toast tu tat sau bao lau. 5s la muc hoi tu cua nganh (Radix Toast default
     5000ms, Carbon toast 5s). Toast CO HANH DONG thi KHONG duoc tu tat — nguoi
     dung can thoi gian de bam. */
  --ptui-motion-toast-life: 5000ms; /* @kind other */

  /* Lac canh bao: tong thoi luong + bien do. Xem keyframes ptui-shake o extras.css.
     Bien do nho (4px) va CHI 3 nhip — du de bao "sai roi", khong den muc gay chong mat.
     WCAG 2.3.1 chi cam NHAY DO SANG (flash) >3 lan/giay — shake la dich chuyen vi
     tri nen khong cham. Nhung WCAG 2.3.3 (AAA) thi CO cham: lac khong essential
     => bat buoc co nhanh prefers-reduced-motion. */
  --ptui-motion-shake: 360ms; /* @kind other */
  /* Easing rieng cua shake — Animation Patterns "CSS Error Shake Feedback".
     Khong dung --ptui-ease-standard vi shake can vao/ra dut khoat hon. */
  --ptui-ease-shake: cubic-bezier(0.36, 0.07, 0.19, 0.97); /* @kind other */

  /* Nhip "dang suy nghi" cua agent AI. 3 cham lech pha nhau 160ms — con so nay
     la quy uoc typing-indicator pho bien (delay = duration/3 lam 3 cham doc thanh
     mot lan song chay). */
  --ptui-motion-think: 1400ms; /* @kind other */
  --ptui-motion-think-stagger: 160ms; /* SpinKit three-bounce: -0.32s/-0.16s/0s */ /* @kind other */

  /* Nhay bat chu y (badge dem tang, hang vua them). Mot lan, khong lap. */
  --ptui-motion-attention: 600ms; /* @kind other */
}

/* ==== Peram UI Library — tokens/sidebar.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Sidebar — the signature brand surface. Purple → pink gradient rail + panel.
   This is the main brand identity moment; the rest of the UI stays neutral
   zinc + blue. Verbatim from SSOT (ROOT / DARK sidebar block). */

:root {
  --ptui-sidebar-bg:
    radial-gradient(120% 60% at 0% 0%, rgba(168, 85, 247, 0.30) 0%, transparent 55%),
    radial-gradient(120% 70% at 100% 100%, rgba(236, 72, 153, 0.16) 0%, transparent 60%),
    linear-gradient(168deg, #3a1660 0%, #2a1046 46%, #190a2c 100%);
  --ptui-sidebar-border: rgba(255, 255, 255, 0.08);
  --ptui-sidebar-text: rgba(233, 226, 245, 0.62);
  --ptui-sidebar-text-strong: #ffffff;
  --ptui-sidebar-muted: rgba(233, 226, 245, 0.42);
  --ptui-sidebar-hover: rgba(255, 255, 255, 0.06);
  --ptui-sidebar-active-bg:
    linear-gradient(90deg, rgba(236, 72, 153, 0.26) 0%, rgba(139, 92, 246, 0.14) 60%, rgba(139, 92, 246, 0.04) 100%);
  --ptui-sidebar-active-text: #ffffff;
  --ptui-sidebar-active-border: rgba(255, 255, 255, 0.10);
  --ptui-sidebar-active-rail: #ec4899;
  --ptui-sidebar-accent-bar: linear-gradient(180deg, #6d8bff 0%, #a855f7 45%, #ec4899 100%); /* @kind color */
  --ptui-sidebar-active-glow: 0 8px 24px -12px rgba(236, 72, 153, 0.5);
  --ptui-sidebar-toggle-bg: #2a1046;
  --ptui-sidebar-toggle-color: rgba(255, 255, 255, 0.9);
  --ptui-sidebar-toggle-hover-bg: #3a1660;
}

[data-theme="dark"] {
  --ptui-sidebar-bg:
    radial-gradient(120% 60% at 0% 0%, rgba(168, 85, 247, 0.28) 0%, transparent 55%),
    radial-gradient(120% 70% at 100% 100%, rgba(236, 72, 153, 0.15) 0%, transparent 60%),
    linear-gradient(168deg, #341655 0%, #240f3e 46%, #150823 100%);
  --ptui-sidebar-border: rgba(255, 255, 255, 0.07);
  --ptui-sidebar-text: rgba(228, 220, 242, 0.60);
  --ptui-sidebar-muted: rgba(228, 220, 242, 0.40);
  --ptui-sidebar-toggle-bg: #240f3e;
  --ptui-sidebar-toggle-hover-bg: #341655;
}

/* ==== Peram UI Library — tokens/kanban.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Kanban — dotted-paper board surface, stacked-paper columns, lift-on-drag cards.
   Verbatim from SSOT (KANBAN_LIGHT / KANBAN_DARK). Cards inherit column tone via
   --ptui-kb-tone / -tone-bg / -tone-fg, set inline by the KanbanBoard component. */

:root {
  --ptui-kb-board-bg:
    radial-gradient(circle at 16px 16px, rgba(90, 106, 133, 0.13) 0 1px, transparent 1px),
    linear-gradient(180deg, #ecf0f7, #e3e9f3);
  --ptui-kb-board-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), inset 0 2px 10px rgba(13, 21, 38, 0.06);
  --ptui-kb-col-bg: linear-gradient(180deg, #f7f9fc, #f1f4fa);
  --ptui-kb-col-shadow: 0 1px 0 rgba(13, 21, 38, 0.06), 0 4px 8px rgba(13, 21, 38, 0.07), 0 12px 28px rgba(13, 21, 38, 0.06);
  --ptui-kb-col-head-bg: linear-gradient(180deg, #ffffff, #f4f6fa);
  --ptui-kb-card-border: #dce1ec;
  --ptui-kb-card-border-hover: #c9d2e4;
  --ptui-kb-card-bg: linear-gradient(180deg, #ffffff, #fbfcfe);
  --ptui-kb-card-shadow: 0 1px 2px rgba(13, 21, 38, 0.06), 0 6px 14px rgba(13, 21, 38, 0.07);
  --ptui-kb-card-shadow-hover: 0 2px 5px rgba(13, 21, 38, 0.09), 0 12px 26px rgba(13, 21, 38, 0.11);
  --ptui-kb-card-shadow-overlay: 0 18px 40px rgba(13, 21, 38, 0.25);
  --ptui-kb-drop-bg: rgba(37, 99, 235, 0.07);
}

[data-theme="dark"] {
  --ptui-kb-board-bg:
    radial-gradient(circle at 16px 16px, rgba(148, 163, 184, 0.10) 0 1px, transparent 1px),
    linear-gradient(180deg, #131316, #0f0f12);
  --ptui-kb-board-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), inset 0 2px 10px rgba(0, 0, 0, 0.35);
  --ptui-kb-col-bg: linear-gradient(180deg, #18181b, #131316);
  --ptui-kb-col-shadow: 0 1px 0 rgba(0, 0, 0, 0.4), 0 4px 8px rgba(0, 0, 0, 0.35), 0 12px 28px rgba(0, 0, 0, 0.3);
  --ptui-kb-col-head-bg: linear-gradient(180deg, #1c1c1f, #161619);
  --ptui-kb-card-border: #2e2e33;
  --ptui-kb-card-border-hover: #3f3f46;
  --ptui-kb-card-bg: linear-gradient(180deg, #1a1a1d, #161619);
  --ptui-kb-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 14px rgba(0, 0, 0, 0.35);
  --ptui-kb-card-shadow-hover: 0 2px 5px rgba(0, 0, 0, 0.5), 0 12px 26px rgba(0, 0, 0, 0.45);
  --ptui-kb-card-shadow-overlay: 0 18px 40px rgba(0, 0, 0, 0.6);
  --ptui-kb-drop-bg: rgba(59, 130, 246, 0.10);
}

/* ==== Peram UI Library — tokens/metric.css (verbatim tu peram-ui-platform-ver6) ==== */
/* Metric-card tone palette — accent + soft per tone, as real tokens so the dark
   values live under :root scopes instead of `[data-theme="dark"] .ptui-metric-*`
   component selectors. The MetricCard classes reference these; border/glow are
   derived via color-mix at the component level. */

:root {
  --ptui-metric-blue-accent: var(--ptui-accent);
  --ptui-metric-blue-soft: var(--ptui-accent-soft);
  --ptui-metric-green-accent: #16a34a;
  --ptui-metric-green-soft: #ecfdf3;
  --ptui-metric-amber-accent: #d97706;
  --ptui-metric-amber-soft: #fff7ed;
  --ptui-metric-rose-accent: #e11d48;
  --ptui-metric-rose-soft: #fff1f2;
  --ptui-metric-violet-accent: #7c3aed;
  --ptui-metric-violet-soft: #f5f3ff;
  --ptui-metric-slate-accent: #64748b;
  --ptui-metric-slate-soft: #f1f5f9;
}

[data-theme="dark"] {
  --ptui-metric-green-accent: #22c55e;
  --ptui-metric-green-soft: rgba(34, 197, 94, 0.12);
  --ptui-metric-amber-accent: #f59e0b;
  --ptui-metric-amber-soft: rgba(245, 158, 11, 0.13);
  --ptui-metric-rose-accent: #fb7185;
  --ptui-metric-rose-soft: rgba(251, 113, 133, 0.13);
  --ptui-metric-violet-accent: #a78bfa;
  --ptui-metric-violet-soft: rgba(167, 139, 250, 0.13);
  --ptui-metric-slate-accent: #94a3b8;
  --ptui-metric-slate-soft: rgba(148, 163, 184, 0.12);
}

/* ==== Peram UI Library — components.css (verbatim tu peram-ui-platform-ver6) ==== */
/* =========================================================================
   Peram UI Platform — component CSS (.ptui-*)
   Transcribed verbatim from @peram-ui/ui-kit src/styles.css (TwoTierSidebar,
   Button, IconButton, Panel, MetricCard, KanbanBoard). Only var(--ptui-*)
   references, no hardcoded palette. Table + Modal are NEW (designed to match
   this system — not in the original source, which had them unbuilt).
   ========================================================================= */

/* --------------------------- Shell / TwoTierSidebar --------------------------- */
.ptui-shell {
  display: grid;
  grid-template-columns: var(--ptui-rail-width) var(--ptui-sidebar-width) minmax(0, 1fr);
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.ptui-shell.ptui-collapsed {
  grid-template-columns: var(--ptui-rail-width) var(--ptui-sidebar-collapsed-width) minmax(0, 1fr);
}

/* Tier 1: icon rail */
.ptui-rail {
  position: relative;
  z-index: var(--ptui-z-rail, 31);
  width: var(--ptui-rail-width);
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 12px 0 14px;
  background: var(--ptui-sidebar-bg);
  border-right: 1px solid var(--ptui-sidebar-border);
  color: var(--ptui-sidebar-text);
}
.ptui-rail::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, transparent 32%),
    linear-gradient(315deg, rgba(236, 72, 153, 0.1) 0%, transparent 38%);
  opacity: 0.92;
}
.ptui-rail > * { position: relative; z-index: 1; }
.ptui-railBrand {
  margin-bottom: 10px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ptui-railBrand svg { width: 30px; height: 30px; }
.ptui-railItem {
  width: 100%;
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  color: var(--ptui-sidebar-muted);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 8px 2px;
  border-radius: 10px;
  transition: background var(--ptui-duration-normal, 200ms) ease, color var(--ptui-duration-normal, 200ms) ease;
}
.ptui-railItem:hover { color: var(--ptui-sidebar-text-strong); background: var(--ptui-sidebar-hover); }
.ptui-railItem.ptui-active { color: var(--ptui-sidebar-text-strong); }
.ptui-railItem.ptui-active svg { color: var(--ptui-sidebar-active-rail); }
.ptui-railLabel { font-size: 10.5px; line-height: 1.1; text-align: center; }
.ptui-railSpacer { flex: 1 1 auto; }

/* Tier 2: sidebar panel */
.ptui-sidebar {
  position: relative;
  width: var(--ptui-sidebar-width);
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: visible;
  background: var(--ptui-sidebar-bg);
  border-right: 1px solid var(--ptui-sidebar-border);
  color: var(--ptui-sidebar-text);
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.04), 18px 0 34px -32px rgba(15, 23, 42, 0.7);
}
.ptui-collapsed .ptui-sidebar { width: var(--ptui-sidebar-collapsed-width); }
.ptui-sidebar::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, transparent 32%),
    linear-gradient(315deg, rgba(236, 72, 153, 0.1) 0%, transparent 38%);
  opacity: 0.92;
}
.ptui-sidebar::after {
  content: "";
  position: absolute;
  inset: 60px auto 18px 0;
  width: 3px;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(99, 102, 241, 0), rgba(236, 72, 153, 0.62), rgba(99, 102, 241, 0));
}
.ptui-sidebarBrand { position: relative; z-index: 1; padding: 16px 16px 8px; flex: 0 0 auto; }
.ptui-sidebarBrand h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ptui-sidebar-text-strong);
}
.ptui-collapsed .ptui-sidebarText { display: none; }
.ptui-sidebarToggle {
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  z-index: 6;
  width: 28px;
  height: 28px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 50%;
  background: var(--ptui-sidebar-toggle-bg);
  color: var(--ptui-sidebar-toggle-color);
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.35);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.ptui-sidebarToggle svg { transition: transform var(--ptui-duration-normal, 200ms) ease; }
.ptui-collapsed .ptui-sidebarToggle svg { transform: rotate(180deg); }
.ptui-sidebarToggle:hover {
  background: var(--ptui-sidebar-toggle-hover-bg);
  color: var(--ptui-sidebar-active-text);
  border-color: rgba(255, 255, 255, 0.3);
  box-shadow: 0 3px 10px rgba(15, 23, 42, 0.45);
}
.ptui-sidebarToggle:active { transform: translateY(-50%) scale(0.94); }
.ptui-nav {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  padding: 6px 8px 16px;
}
.ptui-navGroupItems { display: flex; flex-direction: column; gap: 2px; }
.ptui-navItem {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 10px 12px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ptui-sidebar-text);
  font-size: 14px;
  font-weight: 650;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.22s var(--ptui-ease-standard, cubic-bezier(0.22, 0.61, 0.36, 1)), color 0.22s ease;
}
.ptui-navItem:hover {
  background: var(--ptui-sidebar-hover);
  color: var(--ptui-sidebar-text-strong);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: inset 3px 0 0 rgba(255, 255, 255, 0.18);
}
.ptui-navItem.ptui-active {
  background: var(--ptui-sidebar-active-bg);
  color: var(--ptui-sidebar-active-text);
  border-color: var(--ptui-sidebar-active-border);
  box-shadow: var(--ptui-sidebar-active-glow), 0 10px 22px -18px rgba(0, 0, 0, 0.78);
}
.ptui-navItem.ptui-active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 60%;
  border-radius: 0 6px 6px 0;
  background: var(--ptui-sidebar-accent-bar);
  box-shadow: 0 0 14px rgba(236, 72, 153, 0.7);
  pointer-events: none;
}
.ptui-navItem svg { flex: 0 0 auto; opacity: 0.94; }
.ptui-collapsed .ptui-navText { display: none; }
.ptui-collapsed .ptui-navItem { justify-content: center; padding: 10px 0; }
.ptui-sidebarFooter {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px 14px;
  border-top: 1px solid var(--ptui-sidebar-border);
}
.ptui-collapsed .ptui-sidebarFooter { padding: 10px 6px 14px; align-items: center; }
.ptui-content { position: relative; min-width: 0; min-height: 0; overflow: auto; }
.ptui-hamburger, .ptui-backdrop { display: none; }

@media (max-width: 860px) {
  .ptui-shell, .ptui-shell.ptui-collapsed { grid-template-columns: minmax(0, 1fr); }
  .ptui-content { grid-column: 1; }
  .ptui-rail, .ptui-sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    height: 100dvh;
    z-index: 1002;
    transition: transform 0.22s var(--ptui-ease-standard, ease);
  }
  .ptui-rail { left: 0; transform: translateX(-100%); }
  .ptui-sidebar {
    left: var(--ptui-rail-width);
    width: var(--ptui-sidebar-width);
    transform: translateX(calc(-100% - var(--ptui-rail-width)));
    box-shadow: 18px 0 40px -20px rgba(0, 0, 0, 0.6);
  }
  .ptui-shell.ptui-mobile-open .ptui-rail,
  .ptui-shell.ptui-mobile-open .ptui-sidebar { transform: translateX(0); }
  .ptui-shell.ptui-collapsed .ptui-sidebar { width: var(--ptui-sidebar-width); }
  .ptui-sidebarToggle { display: none; }
  .ptui-hamburger {
    display: grid;
    place-items: center;
    position: fixed;
    top: 10px;
    left: 10px;
    z-index: 1001;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    border: 1px solid var(--ptui-sidebar-border);
    background: var(--ptui-sidebar-toggle-bg);
    color: var(--ptui-sidebar-toggle-color);
    cursor: pointer;
  }
  .ptui-shell.ptui-mobile-open .ptui-hamburger { display: none; }
  .ptui-shell.ptui-mobile-open .ptui-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 1001;
    background: rgba(0, 0, 0, 0.45);
  }
}

/* ---------------------------- Button ---------------------------- */
/* All buttons are 2D — flat body with a soft fake drop shadow (no hard 3D
   bottom edge). Hover deepens the shadow slightly; active presses 1px. */
.ptui-btn {
  min-height: var(--ptui-control-height, 44px);
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--ptui-border-strong);
  border-radius: var(--ptui-radius, 10px);
  background: linear-gradient(180deg, var(--ptui-surface), var(--ptui-bg-subtle));
  color: var(--ptui-text);
  font: 650 14px/1 var(--ptui-font-sans);
  cursor: pointer;
  box-shadow: var(--ptui-btn-shadow, 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.10));
  transition: transform .08s ease, box-shadow .15s ease, filter .15s ease, border-color .15s ease;
}
.ptui-btn:hover { filter: brightness(1.02); box-shadow: var(--ptui-btn-shadow-hover, 0 2px 4px rgba(15, 23, 42, 0.08), 0 3px 8px rgba(15, 23, 42, 0.12)); }
.ptui-btn:active { transform: translateY(1px); filter: brightness(0.98); box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10); }
.ptui-btn:disabled { opacity: .5; cursor: not-allowed; transform: none; filter: none; box-shadow: none; }
.ptui-btn:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; }

.ptui-btn-primary {
  --ptui-btn-shadow: 0 1px 2px rgba(37, 99, 235, 0.24), 0 2px 8px rgba(37, 99, 235, 0.22);
  --ptui-btn-shadow-hover: 0 2px 5px rgba(37, 99, 235, 0.28), 0 6px 16px rgba(37, 99, 235, 0.28);
  border-color: var(--ptui-accent-pressed);
  background: linear-gradient(180deg, var(--ptui-accent), var(--ptui-accent-hover));
  color: var(--ptui-text-on-accent, #fff);
}

.ptui-btn-outline {
  border-color: color-mix(in srgb, var(--ptui-accent) 40%, var(--ptui-border));
  background: linear-gradient(180deg, var(--ptui-surface), var(--ptui-accent-soft));
  color: var(--ptui-accent);
}

.ptui-btn-danger {
  --ptui-btn-shadow: 0 1px 2px rgba(220, 38, 38, 0.24), 0 2px 8px rgba(220, 38, 38, 0.22);
  --ptui-btn-shadow-hover: 0 2px 5px rgba(220, 38, 38, 0.28), 0 6px 16px rgba(220, 38, 38, 0.28);
  border-color: #b91c1c;
  background: linear-gradient(180deg, #ef4444, #dc2626);
  color: #fff;
}

/* ---------------------------- IconButton ---------------------------- */
.ptui-iconbtn {
  width: 40px;
  height: 40px;
  border: 1px solid var(--ptui-border-strong);
  border-radius: 10px;
  background: linear-gradient(180deg, var(--ptui-surface), var(--ptui-bg-subtle));
  color: var(--ptui-text-secondary);
  display: inline-grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.10);
  transition: transform .08s ease, box-shadow .15s ease, color .15s ease, filter .15s ease;
}
.ptui-iconbtn:hover { color: var(--ptui-text); box-shadow: 0 2px 4px rgba(15, 23, 42, 0.08), 0 3px 8px rgba(15, 23, 42, 0.12); filter: brightness(1.02); }
.ptui-iconbtn:active { transform: translateY(1px); box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10); }

/* ---------------------------- ActionIcon (CRM row actions) ----------------------------
   Ghost icon buttons with standard CRM tones: view (neutral), edit (blue accent),
   delete (danger red) + success/warning. Transparent by default, tinted on hover. */
.ptui-actionbtn {
  --ptui-act: var(--ptui-text-muted);
  --ptui-act-strong: var(--ptui-text);
  --ptui-act-soft: var(--ptui-bg-muted);
  width: 34px;
  height: 34px;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  color: var(--ptui-act);
  display: inline-grid;
  place-items: center;
  cursor: pointer;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease, border-color var(--ptui-duration-fast, 150ms) ease, transform .08s ease;
}
.ptui-actionbtn:hover { background: var(--ptui-act-soft); color: var(--ptui-act-strong); border-color: color-mix(in srgb, var(--ptui-act) 24%, transparent); }
.ptui-actionbtn:active { transform: translateY(1px); }
.ptui-actionbtn:focus-visible { outline: 2px solid color-mix(in srgb, var(--ptui-act) 40%, transparent); outline-offset: 1px; }
.ptui-actionbtn:disabled { opacity: .4; cursor: not-allowed; }
.ptui-actionbtn-neutral { --ptui-act: var(--ptui-text-muted); --ptui-act-strong: var(--ptui-text); --ptui-act-soft: var(--ptui-bg-muted); }
.ptui-actionbtn-view    { --ptui-act: var(--ptui-text-secondary); --ptui-act-strong: var(--ptui-accent); --ptui-act-soft: var(--ptui-accent-soft); }
.ptui-actionbtn-accent  { --ptui-act: var(--ptui-accent); --ptui-act-strong: var(--ptui-accent-hover); --ptui-act-soft: var(--ptui-accent-soft); }
.ptui-actionbtn-success { --ptui-act: var(--ptui-success); --ptui-act-strong: var(--ptui-success); --ptui-act-soft: var(--ptui-success-soft); }
.ptui-actionbtn-warning { --ptui-act: var(--ptui-warning); --ptui-act-strong: var(--ptui-warning); --ptui-act-soft: var(--ptui-warning-soft); }
.ptui-actionbtn-danger  { --ptui-act: var(--ptui-danger); --ptui-act-strong: var(--ptui-danger); --ptui-act-soft: var(--ptui-danger-soft); }
/* group container to sit inside a table cell */
.ptui-actions { display: inline-flex; align-items: center; gap: 2px; }

/* ---------------------------- Panel ---------------------------- */
.ptui-panel {
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-lg, 14px);
  background: var(--ptui-surface);
  color: var(--ptui-text);
  box-shadow: var(--ptui-shadow-sm);
}

/* ---------------------------- MetricCard ---------------------------- */
.ptui-metric {
  --ptui-metric-accent: var(--ptui-accent);
  --ptui-metric-soft: var(--ptui-accent-soft);
  --ptui-metric-border: color-mix(in srgb, var(--ptui-accent) 24%, var(--ptui-border));
  --ptui-metric-glow: color-mix(in srgb, var(--ptui-accent) 12%, transparent);
  position: relative;
  min-height: 146px;
  display: grid;
  align-content: start;
  gap: 12px;
  padding: 18px;
  overflow: hidden;
  border: 1px solid var(--ptui-metric-border);
  border-radius: var(--ptui-radius-lg, 14px);
  background:
    radial-gradient(circle at 100% 0%, var(--ptui-metric-glow) 0%, transparent 42%),
    linear-gradient(180deg, var(--ptui-surface) 0%, var(--ptui-bg-elevated) 100%);
  color: var(--ptui-text);
  box-shadow: var(--ptui-shadow-sm);
}
.ptui-metric::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: var(--ptui-metric-accent);
  display: block;
}
.ptui-metric-blue   { --ptui-metric-accent: var(--ptui-metric-blue-accent); --ptui-metric-soft: var(--ptui-metric-blue-soft); --ptui-metric-border: color-mix(in srgb, var(--ptui-metric-blue-accent) 28%, var(--ptui-border)); --ptui-metric-glow: color-mix(in srgb, var(--ptui-metric-blue-accent) 12%, transparent); }
.ptui-metric-green  { --ptui-metric-accent: var(--ptui-metric-green-accent); --ptui-metric-soft: var(--ptui-metric-green-soft); --ptui-metric-border: color-mix(in srgb, var(--ptui-metric-green-accent) 30%, var(--ptui-border)); --ptui-metric-glow: color-mix(in srgb, var(--ptui-metric-green-accent) 12%, transparent); }
.ptui-metric-amber  { --ptui-metric-accent: var(--ptui-metric-amber-accent); --ptui-metric-soft: var(--ptui-metric-amber-soft); --ptui-metric-border: color-mix(in srgb, var(--ptui-metric-amber-accent) 30%, var(--ptui-border)); --ptui-metric-glow: color-mix(in srgb, var(--ptui-metric-amber-accent) 12%, transparent); }
.ptui-metric-rose   { --ptui-metric-accent: var(--ptui-metric-rose-accent); --ptui-metric-soft: var(--ptui-metric-rose-soft); --ptui-metric-border: color-mix(in srgb, var(--ptui-metric-rose-accent) 28%, var(--ptui-border)); --ptui-metric-glow: color-mix(in srgb, var(--ptui-metric-rose-accent) 11%, transparent); }
.ptui-metric-violet { --ptui-metric-accent: var(--ptui-metric-violet-accent); --ptui-metric-soft: var(--ptui-metric-violet-soft); --ptui-metric-border: color-mix(in srgb, var(--ptui-metric-violet-accent) 30%, var(--ptui-border)); --ptui-metric-glow: color-mix(in srgb, var(--ptui-metric-violet-accent) 12%, transparent); }
.ptui-metric-slate  { --ptui-metric-accent: var(--ptui-metric-slate-accent); --ptui-metric-soft: var(--ptui-metric-slate-soft); --ptui-metric-border: color-mix(in srgb, var(--ptui-metric-slate-accent) 26%, var(--ptui-border)); --ptui-metric-glow: color-mix(in srgb, var(--ptui-metric-slate-accent) 10%, transparent); }
.ptui-metric-icon {
  width: 40px;
  height: 40px;
  display: inline-grid;
  place-items: center;
  border: 1px solid color-mix(in srgb, var(--ptui-metric-accent) 24%, transparent);
  border-radius: 10px;
  background: var(--ptui-metric-soft);
  color: var(--ptui-metric-accent);
}
.ptui-metric-label { color: var(--ptui-text-muted); font-size: 13px; }
.ptui-metric-value { font-size: 28px; font-weight: 800; color: var(--ptui-text); }
.ptui-metric-rate { display: grid; gap: 8px; }
.ptui-metric-percent { font-size: 24px; font-weight: 800; color: var(--ptui-text); }
.ptui-metric-sub { color: var(--ptui-text-muted); font-size: 12px; }
.ptui-metric-track { height: 8px; border-radius: 999px; background: var(--ptui-bg-muted); overflow: hidden; }
.ptui-metric-track i { display: block; width: var(--ptui-rate, 0%); height: 100%; background: var(--ptui-metric-accent); border-radius: 999px; }

/* ---------------------------- KanbanBoard ---------------------------- */
.ptui-kb-board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, 320px);
  gap: 14px;
  overflow-x: auto;
  padding: 12px;
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-lg, 14px);
  min-height: var(--ptui-kb-minh, 520px);
  background: var(--ptui-kb-board-bg);
  background-size: 18px 18px, auto;
  box-shadow: var(--ptui-kb-board-shadow);
  cursor: grab;
}
.ptui-kb-board--grabbing { cursor: grabbing; user-select: none; }
.ptui-kb-col {
  display: grid;
  grid-template-rows: auto 1fr;
  border-radius: var(--ptui-radius-lg, 14px);
  min-height: calc(var(--ptui-kb-minh, 520px) - 24px);
  overflow: hidden;
  background: var(--ptui-kb-col-bg);
  box-shadow: var(--ptui-kb-col-shadow);
  transition: outline-color 0.15s ease;
}
.ptui-kb-col--over {
  outline: 2px solid color-mix(in oklab, var(--ptui-kb-tone, var(--ptui-accent)) 55%, transparent);
  outline-offset: -2px;
}
.ptui-kb-colHead {
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px;
  background: var(--ptui-kb-col-head-bg);
  border-bottom: 1px solid var(--ptui-border);
}
.ptui-kb-colTitle { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 850; color: var(--ptui-text); }
.ptui-kb-colDot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  background: var(--ptui-kb-tone, var(--ptui-text-muted));
  box-shadow: 0 0 0 3px var(--ptui-kb-tone-bg, var(--ptui-bg-subtle));
}
.ptui-kb-colCount {
  min-width: 28px;
  height: 22px;
  padding: 0 8px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: var(--ptui-kb-tone-bg, var(--ptui-bg-subtle));
  color: var(--ptui-kb-tone-fg, var(--ptui-text-secondary));
}
.ptui-kb-cards {
  display: grid;
  gap: 12px;
  padding: 14px 12px;
  overflow-y: auto;
  align-content: start;
  max-height: var(--ptui-kb-maxlist, 1316px);
}
.ptui-kb-card {
  position: relative;
  display: grid;
  gap: 9px;
  border: 1px solid var(--ptui-kb-card-border);
  border-radius: var(--ptui-radius, 10px);
  background: var(--ptui-kb-card-bg);
  padding: 14px 14px 13px;
  box-shadow: var(--ptui-kb-card-shadow);
  transition: box-shadow 0.18s ease, transform 0.16s ease, border-color 0.14s ease;
  cursor: grab;
}
.ptui-kb-card::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--ptui-kb-tone, var(--ptui-accent));
}
.ptui-kb-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--ptui-kb-card-shadow-hover);
  border-color: var(--ptui-kb-card-border-hover);
}
.ptui-kb-card--static { cursor: default; }
.ptui-kb-card--placeholder { opacity: 0.35; }
.ptui-kb-card--overlay {
  transform: scale(1.03) rotate(0.8deg);
  box-shadow: var(--ptui-kb-card-shadow-overlay);
  cursor: grabbing;
}
.ptui-kb-empty {
  min-height: 72px;
  display: grid;
  place-items: center;
  border: 1px dashed var(--ptui-border);
  border-radius: var(--ptui-radius, 10px);
  background: var(--ptui-kb-drop-bg);
  color: var(--ptui-text-muted);
  font-size: 12.5px;
  font-weight: 700;
}

/* ---- KanbanCard — rich card CONTENT (rendered inside .ptui-kb-card via renderCard) ---- */
.ptui-kbc { display: grid; gap: 9px; }
.ptui-kbc-bar { height: 4px; border-radius: 999px; background: var(--ptui-kbc-color, var(--ptui-accent)); margin: -2px 0 1px; }
.ptui-kbc-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ptui-kbc-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.ptui-kbc-tag {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border-radius: 6px; font-size: 11px; font-weight: 700; line-height: 1;
  background: var(--ptui-kbc-tag-bg, var(--ptui-bg-muted));
  color: var(--ptui-kbc-tag-fg, var(--ptui-text-secondary));
}
.ptui-kbc-grip {
  display: inline-flex; color: var(--ptui-text-subtle); cursor: grab; flex: 0 0 auto;
  opacity: 0; transition: opacity var(--ptui-duration-fast, 150ms) ease;
}
.ptui-kb-card:hover .ptui-kbc-grip { opacity: 1; }
.ptui-kbc-title { font-size: 14px; font-weight: 700; line-height: 1.35; color: var(--ptui-text); }
.ptui-kbc-desc {
  font-size: 12.5px; line-height: 1.45; color: var(--ptui-text-muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ptui-kbc-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ptui-kbc-due {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--ptui-text-muted);
}
.ptui-kbc-due--over { color: var(--ptui-danger); }
.ptui-kbc-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 2px; padding-top: 10px; border-top: 1px solid var(--ptui-border);
}
.ptui-kbc-people { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ptui-kbc-av {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 10.5px; font-weight: 700;
  color: var(--ptui-text-on-accent, #fff);
  background: var(--ptui-kbc-av, var(--ptui-accent));
  box-shadow: 0 0 0 2px var(--ptui-surface);
}
.ptui-kbc-creator { font-size: 11.5px; color: var(--ptui-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ptui-kbc-creator b { color: var(--ptui-text-secondary); font-weight: 650; }
.ptui-kbc-stats { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; color: var(--ptui-text-muted); font-size: 12px; }
.ptui-kbc-stat { display: inline-flex; align-items: center; gap: 4px; font-variant-numeric: tabular-nums; }
/* drag state (content dims slightly + grip locks visible; board handles the lift) */
.ptui-kbc--dragging { }
.ptui-kbc--dragging .ptui-kbc-grip { opacity: 1; cursor: grabbing; }

/* =========================================================================
   Table — NEW. Not in the original source (Table was unbuilt). Designed to
   match: zinc borders, blue accent, subtle slate shadows, 44px control rhythm.
   ========================================================================= */
.ptui-table-wrap {
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-lg, 14px);
  background: var(--ptui-surface);
  box-shadow: var(--ptui-shadow-sm);
  overflow: hidden;
}
.ptui-table { width: 100%; border-collapse: collapse; font: 400 14px/1.4 var(--ptui-font-sans); }
.ptui-table thead th {
  text-align: left;
  padding: 0 16px;
  height: 44px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ptui-text-muted);
  background: var(--ptui-bg-subtle);
  border-bottom: 1px solid var(--ptui-border);
  white-space: nowrap;
}
.ptui-table thead th.ptui-th-sortable { cursor: pointer; user-select: none; }
.ptui-table thead th.ptui-th-sortable:hover { color: var(--ptui-text-secondary); }
.ptui-table thead th .ptui-th-inner { display: inline-flex; align-items: center; gap: 6px; }
.ptui-table tbody td {
  padding: 0 16px;
  height: 52px;
  color: var(--ptui-text-secondary);
  border-bottom: 1px solid var(--ptui-border);
  vertical-align: middle;
}
.ptui-table tbody tr:last-child td { border-bottom: 0; }
.ptui-table tbody tr { transition: background var(--ptui-duration-fast, 150ms) ease; }
.ptui-table.ptui-table-hover tbody tr:hover { background: var(--ptui-surface-hover); }
.ptui-table tbody tr.ptui-row-selected { background: var(--ptui-accent-soft); }
.ptui-table td.ptui-td-strong { color: var(--ptui-text); font-weight: 600; }
.ptui-table td.ptui-td-num { text-align: right; font-variant-numeric: tabular-nums; }
.ptui-table .ptui-td-check, .ptui-table th.ptui-th-check { width: 44px; padding-right: 0; }
.ptui-table-align-end { text-align: right; }

/* ---- DataTable — draggable columns + per-column sort/filter (reuses .ptui-table) ---- */
.ptui-dt thead th { padding: 0 8px 0 16px; overflow: visible; }
.ptui-dt-th {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 44px;
  cursor: grab;
  transition: opacity var(--ptui-duration-fast, 150ms) ease;
}
.ptui-dt-th:active { cursor: grabbing; }
.ptui-dt-grip { display: inline-flex; color: var(--ptui-text-subtle); opacity: 0; transition: opacity var(--ptui-duration-fast, 150ms) ease; margin-left: -4px; }
.ptui-dt thead th:hover .ptui-dt-grip { opacity: 1; }
.ptui-dt-label { flex: 1 1 auto; }
.ptui-dt-th--dragging { opacity: 0.4; }
.ptui-dt-th-cell { position: relative; }
/* drop indicator bar where the column will land */
.ptui-dt-th-cell--over::before {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
  bottom: 6px;
  width: 3px;
  border-radius: 2px;
  background: var(--ptui-accent);
  box-shadow: 0 0 8px var(--ptui-accent-ring);
}
.ptui-dt-sort { display: inline-flex; color: var(--ptui-text-subtle); }
.ptui-dt-sort--active { color: var(--ptui-accent); }
.ptui-dt-menubtn {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ptui-text-muted);
  cursor: pointer;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-dt-menubtn:hover { background: var(--ptui-bg-muted); color: var(--ptui-text); }
.ptui-dt-menubtn--active { background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-dt-filtered { width: 6px; height: 6px; border-radius: 50%; background: var(--ptui-accent); flex: 0 0 auto; }
/* per-column popover: sort + filter */
.ptui-dt-pop {
  position: absolute;
  top: 40px;
  right: 4px;
  z-index: 900;
  min-width: 220px;
  padding: 8px;
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-lg, 14px);
  background: var(--ptui-surface);
  box-shadow: var(--ptui-shadow-lg);
  text-transform: none;
  letter-spacing: 0;
  animation: ptui-menu-pop var(--ptui-duration-fast, 150ms) var(--ptui-ease-decelerate, ease);
}
.ptui-dt-pop .ptui-dt-filterwrap { position: relative; margin-bottom: 6px; }
.ptui-dt-pop .ptui-dt-filterwrap svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--ptui-text-subtle); }
.ptui-dt-pop input {
  width: 100%;
  box-sizing: border-box;
  height: 38px;
  padding: 0 10px 0 32px;
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius, 10px);
  background: var(--ptui-bg-subtle);
  color: var(--ptui-text);
  font: 400 13.5px var(--ptui-font-sans);
}
.ptui-dt-pop input:focus { outline: none; border-color: var(--ptui-border-focus); box-shadow: 0 0 0 3px var(--ptui-accent-ring); background: var(--ptui-surface); }
.ptui-dt-drag-ghost {
  position: fixed;
  z-index: 1200;
  pointer-events: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  border-radius: 10px;
  background: var(--ptui-surface);
  border: 1px solid var(--ptui-accent);
  box-shadow: var(--ptui-shadow-lg);
  font: 700 13px var(--ptui-font-sans);
  color: var(--ptui-accent);
  transform: rotate(-3deg) scale(1.02);
  transform-origin: top left;
}
.ptui-dt-drag-ghost svg { color: var(--ptui-accent); opacity: 0.8; }

/* Badge / status pill used inside tables + cards */
.ptui-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 650;
  line-height: 1;
  border: 1px solid transparent;
  white-space: nowrap;
}
.ptui-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: 0.9; }
.ptui-badge-neutral { background: var(--ptui-bg-muted); color: var(--ptui-text-secondary); }
.ptui-badge-accent  { background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-badge-success { background: var(--ptui-success-soft); color: var(--ptui-success); }
.ptui-badge-warning { background: var(--ptui-warning-soft); color: var(--ptui-warning); }
.ptui-badge-danger  { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
[data-theme="dark"] .ptui-badge-success { background: rgba(22,163,74,.14); color: #4ade80; }
[data-theme="dark"] .ptui-badge-warning { background: rgba(217,119,6,.16); color: #fbbf24; }
[data-theme="dark"] .ptui-badge-danger  { background: rgba(220,38,38,.16); color: #f87171; }
.ptui-badge-plain::before { display: none; }

/* =========================================================================
   Modal — NEW. Overlay + centered dialog. Matches Panel surface + lg shadow.
   ========================================================================= */
.ptui-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(15, 23, 42, 0.42);
  backdrop-filter: blur(2px);
  animation: ptui-modal-fade var(--ptui-duration-normal, 200ms) var(--ptui-ease-standard, ease);
}
@keyframes ptui-modal-fade { from { opacity: 0; } to { opacity: 1; } }
.ptui-modal {
  width: 100%;
  max-width: var(--ptui-modal-w, 480px);
  max-height: calc(100dvh - 48px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-xl, 20px);
  background: var(--ptui-surface);
  color: var(--ptui-text);
  box-shadow: var(--ptui-shadow-lg);
  overflow: hidden;
  animation: ptui-modal-pop var(--ptui-duration-normal, 200ms) var(--ptui-ease-decelerate, ease);
}
@keyframes ptui-modal-pop { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
.ptui-modal-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 20px 20px 14px;
}
.ptui-modal-titles { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }
.ptui-modal-title { margin: 0; font-size: 17px; font-weight: 750; color: var(--ptui-text); }
.ptui-modal-sub { margin: 0; font-size: 13px; color: var(--ptui-text-muted); }
.ptui-modal-close {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ptui-text-muted);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.ptui-modal-close:hover { background: var(--ptui-bg-muted); color: var(--ptui-text); }
.ptui-modal-body { padding: 0 20px 4px; overflow-y: auto; overflow-x: hidden; color: var(--ptui-text-secondary); font-size: 14px; line-height: 1.55; }
.ptui-modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 20px 20px;
  margin-top: 8px;
}

/* ConfirmDialog — confirm/cancel popup built on Modal (icon + copy row). */
.ptui-confirm-body { display: flex; gap: 14px; padding: 6px 0 10px; }
.ptui-confirm-ico { width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center; flex: 0 0 auto; }
.ptui-confirm-ico-danger { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
.ptui-confirm-ico-primary { background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-confirm-ico-success { background: var(--ptui-success-soft); color: var(--ptui-success); }
[data-theme="dark"] .ptui-confirm-ico-danger { background: rgba(220, 38, 38, 0.16); }
[data-theme="dark"] .ptui-confirm-ico-success { background: rgba(22, 163, 74, 0.16); }
.ptui-confirm-copy { min-width: 0; }
.ptui-confirm-title { margin: 2px 0 4px; font-size: 17px; font-weight: 750; color: var(--ptui-text); }
.ptui-confirm-msg { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ptui-text-secondary); }

/* =========================================================================
   AIButton — NEW. The signature AI-trigger button. Brand accent-bar gradient
   (blue→violet→pink, echoing the sidebar), a sparkle glyph, a sweeping shimmer
   sheen and a soft glow. Same 3D press model as .ptui-btn. Use ONLY for "run
   AI / ask the agent" actions so it stays special.
   ========================================================================= */
.ptui-ai-btn {
  position: relative;
  overflow: hidden;
  min-height: var(--ptui-control-height, 44px);
  padding: 0 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--ptui-radius, 10px);
  background: linear-gradient(135deg, #6d8bff 0%, #a855f7 48%, #ec4899 100%);
  color: #fff;
  font: 700 14px/1 var(--ptui-font-sans);
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(168, 85, 247, 0.28), 0 4px 14px rgba(168, 85, 247, 0.3);
  transition: transform .08s ease, box-shadow .15s ease, filter .15s ease;
}
.ptui-ai-btn > * { position: relative; z-index: 1; }
/* sweeping shimmer band */
.ptui-ai-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.42) 46%, rgba(255, 255, 255, 0) 60%);
  background-size: 220% 100%;
  background-position: 180% 0;
  animation: ptui-ai-shimmer 3.2s var(--ptui-ease-standard, ease) infinite;
  pointer-events: none;
}
@keyframes ptui-ai-shimmer { 0% { background-position: 180% 0; } 55%, 100% { background-position: -60% 0; } }
.ptui-ai-btn:hover { filter: brightness(1.05) saturate(1.05); box-shadow: 0 2px 6px rgba(168, 85, 247, 0.34), 0 8px 22px rgba(168, 85, 247, 0.4); }
.ptui-ai-btn:active { transform: translateY(1px); box-shadow: 0 1px 4px rgba(168, 85, 247, 0.3); }
.ptui-ai-btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }
.ptui-ai-btn:disabled::after { animation: none; }
.ptui-ai-btn:focus-visible { outline: 2px solid rgba(168, 85, 247, 0.5); outline-offset: 2px; }
.ptui-ai-btn .ptui-ai-spark { animation: ptui-ai-spark 2.4s ease-in-out infinite; }
@keyframes ptui-ai-spark { 0%, 100% { opacity: .85; transform: scale(1); } 50% { opacity: 1; transform: scale(1.14); } }
/* soft variant — tinted, for secondary AI actions on light surfaces */
.ptui-ai-btn-soft {
  background: linear-gradient(135deg, rgba(109, 139, 255, 0.14), rgba(168, 85, 247, 0.14) 55%, rgba(236, 72, 153, 0.14));
  color: #7c3aed;
  border-color: color-mix(in srgb, #a855f7 32%, var(--ptui-border));
  box-shadow: 0 1px 2px rgba(168, 85, 247, 0.14), 0 2px 8px rgba(168, 85, 247, 0.16);
}
.ptui-ai-btn-soft::after { background: linear-gradient(100deg, transparent 30%, rgba(168, 85, 247, 0.18) 48%, transparent 62%); background-size: 220% 100%; }
[data-theme="dark"] .ptui-ai-btn-soft { color: #c4b5fd; }
@media (prefers-reduced-motion: reduce) {
  .ptui-ai-btn::after, .ptui-ai-btn .ptui-ai-spark { animation: none; }
}

/* =========================================================================
   Icon — NEW. A thin wrapper for the system's Lucide-style 24-grid stroke
   glyphs, adding motion/emphasis effects: spin, pulse, bounce, glow, plus a
   "ping" activity dot. Effects respect prefers-reduced-motion.
   ========================================================================= */
.ptui-ico { display: inline-flex; line-height: 0; color: currentColor; vertical-align: middle; }
.ptui-ico svg { display: block; }
.ptui-ico-spin svg  { animation: ptui-ico-spin 1s linear infinite; }
.ptui-ico-pulse svg { animation: ptui-ico-pulse 1.6s var(--ptui-ease-standard, ease) infinite; }
.ptui-ico-bounce svg{ animation: ptui-ico-bounce 1.1s var(--ptui-ease-standard, ease) infinite; }
.ptui-ico-glow svg  { filter: drop-shadow(0 0 5px currentColor); }
.ptui-ico-action svg { animation: ptui-ico-action 2s var(--ptui-ease-standard, ease) infinite; transform-origin: 50% 65%; }
@keyframes ptui-ico-action {
  0%   { transform: translateY(0) rotate(0deg); }
  12%  { transform: translateY(-5px) rotate(0deg); }
  24%  { transform: translateY(0) rotate(0deg); }
  36%  { transform: translateY(-5px) rotate(0deg); }
  48%  { transform: translateY(0) rotate(0deg); }
  85%  { transform: translateY(0) rotate(360deg); }
  100% { transform: translateY(0) rotate(360deg); }
}
@keyframes ptui-ico-spin  { to { transform: rotate(360deg); } }
@keyframes ptui-ico-pulse { 0%, 100% { opacity: .55; transform: scale(0.94); } 50% { opacity: 1; transform: scale(1.06); } }
@keyframes ptui-ico-bounce{ 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
/* activity dot with a ping ring */
.ptui-ico-ping { position: relative; }
.ptui-ico-ping::before, .ptui-ico-ping::after {
  content: "";
  position: absolute;
  top: -2px;
  right: -2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ptui-ico-dot, var(--ptui-danger));
}
.ptui-ico-ping::before { animation: ptui-ico-ping 1.4s var(--ptui-ease-decelerate, ease) infinite; }
@keyframes ptui-ico-ping { 0% { transform: scale(1); opacity: .6; } 80%, 100% { transform: scale(2.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ptui-ico-spin svg, .ptui-ico-pulse svg, .ptui-ico-bounce svg, .ptui-ico-action svg, .ptui-ico-ping::before { animation: none; }
}

/* =========================================================================
   Dropdown / Menu — NEW. A trigger button (reuses .ptui-btn 3D model) that
   opens a floating panel of selectable items: icons, selected check, section
   labels, separators, danger + disabled items. Panel = surface + lg shadow.
   ========================================================================= */
.ptui-dropdown { position: relative; display: inline-block; }
.ptui-dropdown-trigger { gap: 8px; }
.ptui-dropdown-caret { transition: transform var(--ptui-duration-fast, 150ms) ease; opacity: 0.7; }
.ptui-dropdown[data-open="true"] .ptui-dropdown-caret { transform: rotate(180deg); }

.ptui-menu {
  position: absolute;
  z-index: 900;
  top: calc(100% + 6px);
  left: 0;
  min-width: 220px;
  max-height: 320px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-lg, 14px);
  background: var(--ptui-surface);
  box-shadow: var(--ptui-shadow-lg);
  animation: ptui-menu-pop var(--ptui-duration-fast, 150ms) var(--ptui-ease-decelerate, ease);
}
.ptui-menu--end { left: auto; right: 0; }
@keyframes ptui-menu-pop { from { opacity: 0; transform: translateY(-4px) scale(0.985); } to { opacity: 1; transform: none; } }

.ptui-menu-label {
  padding: 8px 10px 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ptui-text-muted);
}
.ptui-menu-sep { height: 1px; margin: 6px 4px; background: var(--ptui-border); }

.ptui-menu-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ptui-radius, 10px);
  background: transparent;
  color: var(--ptui-text-secondary);
  font: 600 14px/1.2 var(--ptui-font-sans);
  text-align: left;
  cursor: pointer;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-menu-item:hover { background: var(--ptui-surface-hover); color: var(--ptui-text); }
.ptui-menu-item:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: -2px; }
.ptui-menu-item .ptui-menu-ico { display: inline-flex; flex: 0 0 auto; color: var(--ptui-text-muted); }
.ptui-menu-item:hover .ptui-menu-ico { color: var(--ptui-text-secondary); }
.ptui-menu-item .ptui-menu-text { flex: 1 1 auto; min-width: 0; }
.ptui-menu-item .ptui-menu-check { flex: 0 0 auto; color: var(--ptui-accent); opacity: 0; }
.ptui-menu-item--selected { background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-menu-item--selected .ptui-menu-ico { color: var(--ptui-accent); }
.ptui-menu-item--selected .ptui-menu-check { opacity: 1; }
.ptui-menu-item--danger { color: var(--ptui-danger); }
.ptui-menu-item--danger .ptui-menu-ico { color: var(--ptui-danger); }
.ptui-menu-item--danger:hover { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
[data-theme="dark"] .ptui-menu-item--danger:hover { background: rgba(220, 38, 38, 0.16); }
.ptui-menu-item:disabled, .ptui-menu-item--disabled { opacity: 0.45; cursor: not-allowed; }
.ptui-menu-item:disabled:hover, .ptui-menu-item--disabled:hover { background: transparent; color: var(--ptui-text-secondary); }

/* =========================================================================
   Progress — NEW. Linear % load bar matching the system: zinc track, blue
   accent fill (semantic tones), tabular value, soft top sheen. Sizes sm/base/lg
   and an indeterminate (unknown-duration) variant. Tone drives fill via
   --ptui-prog-tone; value via --ptui-prog (0–100%).
   ========================================================================= */
.ptui-progress { display: grid; gap: 8px; --ptui-prog-tone: var(--ptui-accent); }
.ptui-progress-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.ptui-progress-label { font-size: 13px; font-weight: 600; color: var(--ptui-text-secondary); }
.ptui-progress-value {
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-family: var(--ptui-font-sans);
  color: var(--ptui-text);
  letter-spacing: -0.01em;
}
.ptui-progress-track {
  position: relative;
  height: var(--ptui-prog-h, 8px);
  border-radius: 999px;
  background: var(--ptui-bg-muted);
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.06);
}
.ptui-progress-sm { --ptui-prog-h: 6px; }
.ptui-progress-lg { --ptui-prog-h: 12px; }
.ptui-progress-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--ptui-prog, 0%);
  border-radius: 999px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0) 55%),
    linear-gradient(90deg, color-mix(in srgb, var(--ptui-prog-tone) 82%, #fff 0%), var(--ptui-prog-tone));
  box-shadow: 0 1px 3px color-mix(in srgb, var(--ptui-prog-tone) 40%, transparent);
  transition: width var(--ptui-duration-slow, 300ms) var(--ptui-ease-decelerate, ease);
}
.ptui-progress-accent  { --ptui-prog-tone: var(--ptui-accent); }
.ptui-progress-success { --ptui-prog-tone: var(--ptui-success); }
.ptui-progress-warning { --ptui-prog-tone: var(--ptui-warning); }
.ptui-progress-danger  { --ptui-prog-tone: var(--ptui-danger); }
.ptui-progress-violet  { --ptui-prog-tone: var(--ptui-metric-violet-accent); }
.ptui-progress-slate   { --ptui-prog-tone: var(--ptui-metric-slate-accent); }

/* Indeterminate — unknown-duration work: a shuttle sweeps the track. */
.ptui-progress-track--indet .ptui-progress-fill {
  width: 38%;
  transition: none;
  animation: ptui-prog-indet 1.25s var(--ptui-ease-standard, ease) infinite;
}
@keyframes ptui-prog-indet {
  0%   { left: -42%; right: auto; }
  100% { left: 100%; right: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .ptui-progress-track--indet .ptui-progress-fill { animation-duration: 2.4s; }
}

/* Input — used by Modal forms and UI kits. Matches 44px control + focus ring. */
.ptui-field { display: grid; gap: 7px; min-width: 0; }
.ptui-field-req { color: var(--ptui-danger); }
.ptui-field-hint { font-size: 11.5px; color: var(--ptui-text-muted); }
.ptui-field--full { grid-column: 1 / -1; }
/* FormDialog — responsive form grid inside the Modal body */
.ptui-form-grid { display: grid; gap: 16px 18px; padding: 10px 0 8px; }
@media (max-width: 520px) { .ptui-form-grid { grid-template-columns: 1fr !important; } }
select.ptui-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 34px;
  cursor: pointer;
}
.ptui-label { font-size: 13px; font-weight: 600; color: var(--ptui-text-secondary); letter-spacing: -0.005em; }
.ptui-input {
  height: var(--ptui-control-height, 44px);
  padding: 0 12px;
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius, 10px);
  background: var(--ptui-surface);
  color: var(--ptui-text);
  font: 400 14px/1 var(--ptui-font-sans);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: border-color .15s ease, box-shadow .15s ease;
  width: 100%;
}
.ptui-input::placeholder { color: var(--ptui-text-subtle); }
.ptui-input:hover { border-color: var(--ptui-border-strong); }
.ptui-input:focus { outline: none; border-color: var(--ptui-border-focus); box-shadow: 0 0 0 3px var(--ptui-accent-ring), 0 1px 2px rgba(15, 23, 42, 0.04); }
textarea.ptui-input { height: auto; padding: 10px 12px; resize: vertical; line-height: 1.5; }

/* =========================================================================
   Workflow builder — node cards + animated connectors (NEW).
   A WorkflowCanvas holds absolutely-positioned WorkflowNode cards over a
   dotted-paper background; edges are drawn as flowing bezier SVG paths.
   Node type sets an accent color via --ptui-wf (blue/violet/green/amber/…).
   ========================================================================= */
.ptui-wf-canvas {
  position: relative;
  width: 100%;
  border-radius: var(--ptui-radius-lg, 14px);
  border: 1px solid var(--ptui-border);
  background-color: var(--ptui-bg);
  background-image: radial-gradient(var(--ptui-border-strong) 1px, transparent 1px);
  background-size: 22px 22px;
  background-position: -1px -1px;
  overflow: hidden;
}
[data-theme="dark"] .ptui-wf-canvas { background-image: radial-gradient(#2a2a30 1px, transparent 1px); }
.ptui-wf-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }
.ptui-wf-edge { fill: none; stroke: var(--ptui-border-strong); stroke-width: 2; }
.ptui-wf-edge-flow {
  fill: none;
  stroke: var(--ptui-wf-edge, var(--ptui-accent));
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 7 9;
  animation: ptui-wf-flow 0.9s linear infinite;
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ptui-wf-edge, var(--ptui-accent)) 45%, transparent));
}
@keyframes ptui-wf-flow { to { stroke-dashoffset: -32; } }
.ptui-wf-edge-dot { fill: var(--ptui-wf-edge, var(--ptui-accent)); }
.ptui-wf-edge-hit { stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: grab; }
.ptui-wf-edge-pending { pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .ptui-wf-edge-flow { animation: none; } }

.ptui-wf-node {
  --ptui-wf: var(--ptui-accent);
  position: absolute;
  z-index: 2;
  width: var(--ptui-wf-w, 236px);
  border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-lg, 14px);
  background: var(--ptui-surface);
  box-shadow: var(--ptui-shadow-md);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.ptui-wf-node:hover { border-color: color-mix(in srgb, var(--ptui-wf) 45%, var(--ptui-border)); box-shadow: var(--ptui-shadow-lg); transform: translateY(-1px); }
.ptui-wf-node--selected { border-color: var(--ptui-wf); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ptui-wf) 20%, transparent), var(--ptui-shadow-lg); }
.ptui-wf-node--running { border-color: var(--ptui-wf); }
.ptui-wf-node--running::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--ptui-wf) 40%, transparent);
  animation: ptui-wf-pulse 1.6s var(--ptui-ease-standard, ease) infinite;
}
@keyframes ptui-wf-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ptui-wf) 42%, transparent); } 70% { box-shadow: 0 0 0 10px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }

.ptui-wf-head {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 13px;
  border-bottom: 1px solid var(--ptui-border);
  border-top-left-radius: inherit; border-top-right-radius: inherit;
  background: linear-gradient(180deg, color-mix(in srgb, var(--ptui-wf) 9%, var(--ptui-surface)), var(--ptui-surface));
}
.ptui-wf-ico {
  width: 30px; height: 30px; border-radius: 9px; flex: 0 0 auto;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--ptui-wf) 15%, var(--ptui-surface));
  color: var(--ptui-wf);
}
.ptui-wf-htext { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 1px; }
.ptui-wf-kind { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ptui-wf); line-height: 1.2; }
.ptui-wf-title { display: block; font-size: 13.5px; font-weight: 700; color: var(--ptui-text); line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ptui-wf-badge {
  font-size: 10px; font-weight: 700; padding: 3px 7px; border-radius: 999px; flex: 0 0 auto;
  background: color-mix(in srgb, var(--ptui-wf) 14%, transparent); color: var(--ptui-wf);
}
.ptui-wf-body { padding: 11px 13px; display: grid; gap: 9px; }
.ptui-wf-prompt {
  font-size: 12.5px; line-height: 1.5; color: var(--ptui-text-secondary);
  background: var(--ptui-bg-subtle); border: 1px solid var(--ptui-border); border-radius: 9px; padding: 8px 10px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.ptui-wf-prompt b { color: var(--ptui-wf); font-weight: 650; }
.ptui-wf-file {
  display: flex; align-items: center; gap: 9px; font-size: 12.5px;
  border: 1px dashed var(--ptui-border-strong); border-radius: 9px; padding: 8px 10px; color: var(--ptui-text-secondary);
}
.ptui-wf-file .ptui-wf-file-ico { color: var(--ptui-wf); flex: 0 0 auto; }
.ptui-wf-file b { font-weight: 650; color: var(--ptui-text); }
.ptui-wf-file small { color: var(--ptui-text-muted); }
/* image thumbnail slot (upload/output image) */
.ptui-wf-image {
  display: flex; align-items: center; gap: 10px; font-size: 12.5px;
  border: 1px solid var(--ptui-border); border-radius: 9px; padding: 8px 10px; color: var(--ptui-text-secondary);
  background: color-mix(in srgb, var(--ptui-wf) 6%, var(--ptui-bg-subtle));
}
.ptui-wf-image-ico {
  width: 40px; height: 40px; flex: 0 0 auto; border-radius: 7px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--ptui-wf) 14%, var(--ptui-surface)); color: var(--ptui-wf);
}
.ptui-wf-image b { font-weight: 650; color: var(--ptui-text); }
.ptui-wf-image small { color: var(--ptui-text-muted); }
.ptui-wf-steps { display: grid; gap: 5px; margin: 0; padding: 0; list-style: none; }
.ptui-wf-step { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ptui-text-secondary); }
.ptui-wf-step-n { width: 17px; height: 17px; border-radius: 50%; flex: 0 0 auto; display: grid; place-items: center; font-size: 9.5px; font-weight: 700; background: color-mix(in srgb, var(--ptui-wf) 15%, transparent); color: var(--ptui-wf); }
.ptui-wf-fields { display: grid; gap: 6px; }
.ptui-wf-field { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12px; }
.ptui-wf-field span { color: var(--ptui-text-muted); }
.ptui-wf-field b { font-weight: 650; color: var(--ptui-text); }
.ptui-wf-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 13px; border-top: 1px solid var(--ptui-border); font-size: 11.5px; color: var(--ptui-text-muted);
}
.ptui-wf-model { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.ptui-wf-model-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ptui-wf); }
.ptui-wf-port {
  position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%;
  background: var(--ptui-surface); border: 2px solid var(--ptui-wf); transform: translateY(-50%); z-index: 3;
}
.ptui-wf-port--in { left: -7px; }
.ptui-wf-port--out { right: -7px; }
.ptui-wf-port--out::after {
  content: ""; position: absolute; inset: 2px; border-radius: 50%; background: var(--ptui-wf); opacity: 0;
  transition: opacity .15s ease;
}
.ptui-wf-node:hover .ptui-wf-port--out::after { opacity: 1; }
/* node wrapper (holds card + ports + resize handle) */
.ptui-wf-nodewrap { z-index: 2; }
.ptui-wf-nodewrap:hover { z-index: 4; }
.ptui-wf-nodewrap .ptui-wf-port { position: absolute; top: 50%; }
.ptui-wf-nodewrap .ptui-wf-port--out { pointer-events: all; }
.ptui-wf-nodewrap .ptui-wf-port--in { pointer-events: all; }
.ptui-wf-nodewrap .ptui-wf-port:hover { transform: translateY(-50%) scale(1.25); }
/* free-resize handle, bottom-right; shows on hover */
.ptui-wf-resize {
  position: absolute; right: -3px; bottom: -3px; width: 22px; height: 22px;
  display: grid; place-items: center; border-radius: 7px;
  background: var(--ptui-surface); border: 1px solid var(--ptui-border);
  color: var(--ptui-text-muted); cursor: nwse-resize; box-shadow: var(--ptui-shadow-sm);
  opacity: 0; transform: scale(.8); transition: opacity .15s ease, transform .15s ease; z-index: 5;
}
.ptui-wf-nodewrap:hover .ptui-wf-resize { opacity: 1; transform: scale(1); }
.ptui-wf-resize:hover { color: var(--ptui-accent); border-color: var(--ptui-accent); }
/* pan cursor + zoom controls */
.ptui-wf-canvas--panning { cursor: grabbing; }
.ptui-wf-canvas--panning .ptui-wf-node { pointer-events: none; }
.ptui-wf-zoom {
  position: absolute; right: 12px; bottom: 12px; z-index: 5;
  display: flex; align-items: center; gap: 2px;
  padding: 4px; border-radius: 12px;
  background: color-mix(in srgb, var(--ptui-surface) 88%, transparent);
  border: 1px solid var(--ptui-border);
  box-shadow: var(--ptui-shadow-md);
  backdrop-filter: blur(8px);
}
.ptui-wf-zoom button {
  width: 30px; height: 30px; border: 0; border-radius: 8px; background: transparent;
  color: var(--ptui-text-secondary); cursor: pointer; display: grid; place-items: center;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-wf-zoom button:hover { background: var(--ptui-bg-muted); color: var(--ptui-text); }
.ptui-wf-zoom-val { min-width: 42px; text-align: center; font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ptui-text-secondary); }

/* =========================================================================
   v0.8.0 — 8 nhom component moi. Cong them, KHONG doi mot gia tri token nao.
   Nhip theo he hien hanh: control 44px (--ptui-control-height), radius 10px,
   duration/ease tu effects.css. Khong hex moi o tang nay.
   ========================================================================= */

/* ---------------------------- Checkbox / Radio ---------------------------- */
/* Input that bi an nhung VAN nhan ban phim (khong dung display:none). */
.ptui-check { display: inline-flex; align-items: flex-start; gap: 10px; position: relative; cursor: pointer; color: var(--ptui-text); line-height: 1.5; }
.ptui-check-input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none; }
.ptui-check-box {
  flex: none; position: relative; display: inline-block; margin-top: 1px;
  width: 16px; height: 16px; border-radius: var(--ptui-radius-sm, 6px);
  border: 1px solid var(--ptui-border-strong); background: var(--ptui-surface);
  transition: background var(--ptui-duration-fast, 150ms) ease, border-color var(--ptui-duration-fast, 150ms) ease, box-shadow var(--ptui-duration-fast, 150ms) ease;
}
.ptui-check-lg .ptui-check-box { width: 20px; height: 20px; margin-top: 0; }
.ptui-check-box--round { border-radius: 999px; }
.ptui-check:hover .ptui-check-input:not(:disabled) + .ptui-check-box { border-color: var(--ptui-accent); background: var(--ptui-accent-soft); }
.ptui-check-input:checked + .ptui-check-box,
.ptui-check-input:indeterminate + .ptui-check-box { background: var(--ptui-accent); border-color: var(--ptui-accent); color: var(--ptui-text-on-accent); }
.ptui-check-input:focus-visible + .ptui-check-box { box-shadow: 0 0 0 3px var(--ptui-accent-ring); border-color: var(--ptui-border-focus); }
.ptui-check-input:disabled + .ptui-check-box { background: var(--ptui-bg-subtle); border-color: var(--ptui-border); }
.ptui-check-input:disabled ~ .ptui-check-text { opacity: .55; }
.ptui-check-box > svg, .ptui-check-box .ptui-ico { display: none; }
/* Dau tich va gach ngang ve bang CSS — khong phu thuoc glyph nao. */
.ptui-check-box::after { content: ""; position: absolute; opacity: 0; transition: opacity var(--ptui-duration-fast, 150ms) ease; }
.ptui-check-box:not(.ptui-check-box--round)::after {
  left: 50%; top: 47%; width: 4px; height: 8px; margin: -5px 0 0 -2px;
  border: 0 solid currentColor; border-right-width: 2px; border-bottom-width: 2px; transform: rotate(45deg);
}
.ptui-check-lg .ptui-check-box:not(.ptui-check-box--round)::after { width: 5px; height: 10px; margin: -6px 0 0 -3px; }
.ptui-check-box--round::after { left: 50%; top: 50%; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 999px; background: currentColor; }
.ptui-check-lg .ptui-check-box--round::after { width: 8px; height: 8px; margin: -4px 0 0 -4px; }
.ptui-check-input:checked + .ptui-check-box::after { opacity: 1; }
.ptui-check-input:indeterminate + .ptui-check-box::after {
  opacity: 1; border: 0; transform: none; background: currentColor; border-radius: 999px;
  left: 50%; top: 50%; width: 8px; height: 2px; margin: -1px 0 0 -4px;
}
.ptui-check-text { display: block; }
.ptui-check-title { display: block; font-size: 14px; font-weight: 500; color: var(--ptui-text); }
.ptui-check-lg .ptui-check-title { font-size: 15px; }
.ptui-check-desc { display: block; margin-top: 2px; font-size: 13px; color: var(--ptui-text-secondary); line-height: 1.55; }
.ptui-check-card {
  padding: 14px 16px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius, 10px);
  background: var(--ptui-surface); box-shadow: var(--ptui-shadow-sm);
  transition: background var(--ptui-duration-fast, 150ms) ease, border-color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-check-card:hover { background: var(--ptui-surface-hover); border-color: var(--ptui-border-strong); }
.ptui-check-card:has(.ptui-check-input:checked) { border-color: var(--ptui-accent); background: var(--ptui-accent-soft); }
.ptui-check-card .ptui-check-box { order: 2; margin-left: auto; }
.ptui-check-card .ptui-check-text { order: 1; flex: 1 1 auto; }

/* ---------------------------- Avatar ---------------------------- */
.ptui-avatar {
  --ptui-avatar-size: 40px; --ptui-avatar-dot: 10px; --ptui-avatar-fs: 15px;
  position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: var(--ptui-avatar-size); height: var(--ptui-avatar-size); border-radius: 999px; overflow: visible;
  background: var(--ptui-accent-soft); color: var(--ptui-accent);
  font: 650 var(--ptui-avatar-fs)/1 var(--ptui-font-sans); user-select: none;
}
.ptui-avatar-xs { --ptui-avatar-size: 24px; --ptui-avatar-dot: 6px; --ptui-avatar-fs: 10px; }
.ptui-avatar-sm { --ptui-avatar-size: 32px; --ptui-avatar-dot: 8px; --ptui-avatar-fs: 12px; }
.ptui-avatar-md { --ptui-avatar-size: 40px; --ptui-avatar-dot: 10px; --ptui-avatar-fs: 15px; }
.ptui-avatar-lg { --ptui-avatar-size: 48px; --ptui-avatar-dot: 12px; --ptui-avatar-fs: 17px; }
.ptui-avatar-xl { --ptui-avatar-size: 56px; --ptui-avatar-dot: 14px; --ptui-avatar-fs: 20px; }
.ptui-avatar-img { width: 100%; height: 100%; border-radius: 999px; object-fit: cover; display: block; }
.ptui-avatar-ring { box-shadow: 0 0 0 2px var(--ptui-surface), 0 0 0 4px var(--ptui-accent-soft-hover); }
.ptui-avatar-more { background: var(--ptui-bg-muted); color: var(--ptui-text-secondary); font-size: calc(var(--ptui-avatar-fs) * .82); }
.ptui-avatar-dot { position: absolute; right: 0; bottom: 0; width: var(--ptui-avatar-dot); height: var(--ptui-avatar-dot); border-radius: 999px; box-shadow: 0 0 0 2px var(--ptui-surface); }
.ptui-avatar-dot-online { background: var(--ptui-success); }
.ptui-avatar-dot-offline { background: var(--ptui-border-strong); }
.ptui-avatar-dot-busy { background: var(--ptui-danger); }
.ptui-avatar-group { display: inline-flex; align-items: center; }
.ptui-avatar-group .ptui-avatar { margin-left: calc(var(--ptui-avatar-size) * -.3); box-shadow: 0 0 0 2px var(--ptui-surface); }
.ptui-avatar-group .ptui-avatar:first-child { margin-left: 0; }

/* ---------------------------- Skeleton ---------------------------- */
.ptui-skeleton { position: relative; overflow: hidden; display: block; background: var(--ptui-bg-muted); border-radius: var(--ptui-radius-sm, 6px); }
.ptui-skeleton::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--ptui-surface-hover), transparent);
  animation: ptui-skeleton-sheen 1.5s var(--ptui-ease-standard, ease) infinite;
}
.ptui-skeleton-line { height: 12px; }
.ptui-skeleton-circle { width: 44px; height: 44px; border-radius: 999px; }
.ptui-skeleton-block { height: 132px; border-radius: var(--ptui-radius, 10px); }
.ptui-skeleton-stack { display: flex; flex-direction: column; gap: 8px; }
@keyframes ptui-skeleton-sheen { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .ptui-skeleton::after { animation: none; } }

/* ---------------------------- ButtonGroup (segmented) ---------------------------- */
.ptui-btngroup { display: inline-flex; align-items: stretch; isolation: isolate; }
.ptui-btngroup-item {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  margin-left: -1px; padding: 0 15px; min-height: var(--ptui-control-height, 44px);
  border: 1px solid var(--ptui-border-strong); background: var(--ptui-surface);
  color: var(--ptui-text-secondary); font: 650 14px/1 var(--ptui-font-sans); cursor: pointer;
  box-shadow: var(--ptui-shadow-sm);
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-btngroup-item:first-child { margin-left: 0; border-top-left-radius: var(--ptui-radius, 10px); border-bottom-left-radius: var(--ptui-radius, 10px); }
.ptui-btngroup-item:last-child { border-top-right-radius: var(--ptui-radius, 10px); border-bottom-right-radius: var(--ptui-radius, 10px); }
.ptui-btngroup-item:hover { background: var(--ptui-surface-hover); color: var(--ptui-text); }
.ptui-btngroup-item[aria-pressed="true"] { background: var(--ptui-accent-soft); color: var(--ptui-accent); border-color: var(--ptui-accent); z-index: 1; }
.ptui-btngroup-item:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; z-index: 2; }
.ptui-btngroup-item:disabled { background: var(--ptui-bg-subtle); color: var(--ptui-text-subtle); cursor: not-allowed; }
.ptui-btngroup-item--icon { padding: 0; width: var(--ptui-control-height, 44px); }
.ptui-btngroup-count {
  display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px; background: var(--ptui-bg-muted); color: var(--ptui-text-secondary);
  font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums;
}
.ptui-btngroup-item[aria-pressed="true"] .ptui-btngroup-count { background: var(--ptui-surface); color: var(--ptui-accent); }
.ptui-btngroup-sm .ptui-btngroup-item { min-height: 34px; padding: 0 13px; font-size: 13px; }
.ptui-btngroup-sm .ptui-btngroup-item--icon { padding: 0; width: 34px; }

/* ---------------------------- Breadcrumb ---------------------------- */
.ptui-crumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; font-size: 14px; }
.ptui-crumb {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px;
  border-radius: var(--ptui-radius-sm, 6px); color: var(--ptui-text-secondary); text-decoration: none;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-crumb:hover { background: var(--ptui-surface-hover); color: var(--ptui-text); }
.ptui-crumb:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 1px; }
.ptui-crumb.ptui-active { color: var(--ptui-text); font-weight: 650; background: var(--ptui-bg-subtle); }
.ptui-crumb-sep { display: inline-flex; color: var(--ptui-text-subtle); }

/* ---------------------------- Tooltip ---------------------------- */
/* Nen dao: dung --ptui-text lam NEN va --ptui-bg lam CHU. O light thanh muc tren
   giay, o dark tu dao lai thanh giay tren muc — dung mot cap token cho ca hai che do. */
.ptui-tip { position: relative; display: inline-flex; }
.ptui-tip-pop {
  position: absolute; z-index: var(--ptui-z-tip, 900); width: max-content; max-width: 230px;
  padding: 8px 10px; border-radius: var(--ptui-radius-sm, 6px);
  background: var(--ptui-text); color: var(--ptui-bg);
  font-size: 12px; line-height: 1.55; box-shadow: var(--ptui-shadow-lg);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--ptui-duration-fast, 150ms) var(--ptui-ease-decelerate, ease), transform var(--ptui-duration-fast, 150ms) var(--ptui-ease-decelerate, ease), visibility var(--ptui-duration-fast, 150ms);
}
.ptui-tip--rich .ptui-tip-pop { max-width: 264px; padding: 10px 12px; }
.ptui-tip-title { display: block; font-size: 12px; font-weight: 700; margin-bottom: 3px; }
.ptui-tip-desc { display: block; opacity: .82; }
.ptui-tip-arrow { position: absolute; width: 8px; height: 8px; background: var(--ptui-text); transform: rotate(45deg); }
.ptui-tip--top .ptui-tip-pop { bottom: calc(100% + 10px); left: 50%; transform: translate(-50%, 4px); }
.ptui-tip--bottom .ptui-tip-pop { top: calc(100% + 10px); left: 50%; transform: translate(-50%, -4px); }
.ptui-tip--left .ptui-tip-pop { right: calc(100% + 10px); top: 50%; transform: translate(4px, -50%); }
.ptui-tip--right .ptui-tip-pop { left: calc(100% + 10px); top: 50%; transform: translate(-4px, -50%); }
.ptui-tip--top .ptui-tip-arrow { bottom: -4px; left: 50%; margin-left: -4px; }
.ptui-tip--bottom .ptui-tip-arrow { top: -4px; left: 50%; margin-left: -4px; }
.ptui-tip--left .ptui-tip-arrow { right: -4px; top: 50%; margin-top: -4px; }
.ptui-tip--right .ptui-tip-arrow { left: -4px; top: 50%; margin-top: -4px; }
.ptui-tip:hover .ptui-tip-pop, .ptui-tip:focus-within .ptui-tip-pop { opacity: 1; visibility: visible; }
.ptui-tip--top:hover .ptui-tip-pop, .ptui-tip--top:focus-within .ptui-tip-pop,
.ptui-tip--bottom:hover .ptui-tip-pop, .ptui-tip--bottom:focus-within .ptui-tip-pop { transform: translate(-50%, 0); }
.ptui-tip--left:hover .ptui-tip-pop, .ptui-tip--left:focus-within .ptui-tip-pop,
.ptui-tip--right:hover .ptui-tip-pop, .ptui-tip--right:focus-within .ptui-tip-pop { transform: translate(0, -50%); }

/* ---------------------------- Toast ---------------------------- */
.ptui-toast-stack {
  position: fixed; z-index: var(--ptui-z-toast, 1100); display: flex; flex-direction: column; gap: 12px;
  width: min(384px, calc(100vw - 48px)); pointer-events: none;
}
.ptui-toast-stack--bottom-right { right: 24px; bottom: 24px; }
.ptui-toast-stack--bottom-left { left: 24px; bottom: 24px; }
.ptui-toast-stack--top-right { right: 24px; top: 24px; }
.ptui-toast-stack--top-left { left: 24px; top: 24px; }
.ptui-toast-stack > * { pointer-events: auto; }
.ptui-toast {
  display: flex; gap: 12px; padding: 14px; background: var(--ptui-surface);
  border: 1px solid var(--ptui-border); border-left-width: 3px;
  border-radius: var(--ptui-radius, 10px); box-shadow: var(--ptui-shadow-lg);
  animation: ptui-toast-in var(--ptui-duration-normal, 200ms) var(--ptui-ease-decelerate, ease) both;
}
@keyframes ptui-toast-in { from { opacity: 0; transform: translateX(16px) scale(.98); } to { opacity: 1; transform: none; } }
.ptui-toast-ico { flex: none; width: 32px; height: 32px; border-radius: 999px; display: inline-grid; place-items: center; }
.ptui-toast-body { flex: 1 1 auto; min-width: 0; }
.ptui-toast-title { font-size: 14px; font-weight: 650; color: var(--ptui-text); }
.ptui-toast-msg { margin-top: 2px; font-size: 13px; line-height: 1.55; color: var(--ptui-text-secondary); }
.ptui-toast-acts { display: flex; gap: 16px; margin-top: 10px; }
.ptui-toast-act { padding: 0; border: 0; background: transparent; font: 650 13px/1 var(--ptui-font-sans); color: var(--ptui-accent); cursor: pointer; border-radius: var(--ptui-radius-sm, 6px); }
.ptui-toast-act:hover { color: var(--ptui-accent-hover); }
.ptui-toast-act--quiet { color: var(--ptui-text-secondary); }
.ptui-toast-act:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; }
.ptui-toast-close {
  flex: none; width: 24px; height: 24px; padding: 0; border: 0; background: transparent;
  color: var(--ptui-text-muted); border-radius: var(--ptui-radius-sm, 6px); cursor: pointer;
  display: inline-grid; place-items: center;
}
.ptui-toast-close:hover { background: var(--ptui-surface-hover); color: var(--ptui-text); }
.ptui-toast-close:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 1px; }
.ptui-toast-info { border-left-color: var(--ptui-accent); }
.ptui-toast-info .ptui-toast-ico { background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-toast-success { border-left-color: var(--ptui-success); }
.ptui-toast-success .ptui-toast-ico { background: var(--ptui-success-soft); color: var(--ptui-success); }
.ptui-toast-warning { border-left-color: var(--ptui-warning); }
.ptui-toast-warning .ptui-toast-ico { background: var(--ptui-warning-soft); color: var(--ptui-warning); }
.ptui-toast-danger { border-left-color: var(--ptui-danger); }
.ptui-toast-danger .ptui-toast-ico { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
@media (prefers-reduced-motion: reduce) { .ptui-toast { animation: none; } }

/* ---------------------------- TreeView ---------------------------- */
.ptui-tree { --ptui-tree-indent: 20px; --ptui-tree-row: 36px; --ptui-tree-pad: 8px; --ptui-tree-fs: 14px;
  padding: 6px; font-family: var(--ptui-font-sans); overflow-x: auto; }
.ptui-tree-md { --ptui-tree-indent: 24px; --ptui-tree-row: 44px; --ptui-tree-fs: 15px; }
.ptui-tree-item { display: block; outline: none; }
.ptui-tree-row {
  position: relative; display: flex; align-items: center; gap: 6px; min-height: var(--ptui-tree-row);
  padding: 2px 10px 2px calc(var(--ptui-tree-pad) + var(--ptui-tree-depth, 0) * var(--ptui-tree-indent));
  border-radius: var(--ptui-radius-sm, 6px); color: var(--ptui-text-secondary); cursor: pointer; user-select: none;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-tree-row:hover { background: var(--ptui-surface-hover); }
.ptui-tree-item.ptui-active > .ptui-tree-row { background: var(--ptui-accent-soft); color: var(--ptui-text); }
.ptui-tree-item.ptui-active > .ptui-tree-row .ptui-tree-label { font-weight: 650; color: var(--ptui-text); }
.ptui-tree-item:focus-visible > .ptui-tree-row { box-shadow: 0 0 0 2px var(--ptui-accent-ring); background: var(--ptui-surface-hover); }
/* Duong ke doc thut le — ve o hang, khong can phan tu bao ngoai. */
.ptui-tree-guides .ptui-tree-row::before {
  content: ""; position: absolute; top: 0; bottom: 0;
  left: calc(var(--ptui-tree-pad) + (var(--ptui-tree-depth, 0) - 1) * var(--ptui-tree-indent) + 10px);
  width: 1px; background: var(--ptui-border); pointer-events: none;
}
.ptui-tree-guides .ptui-tree-item[aria-level="1"] > .ptui-tree-row::before { display: none; }
.ptui-tree-toggle {
  flex: none; width: 20px; height: 20px; display: inline-grid; place-items: center; padding: 0; margin: 0;
  border: 0; background: transparent; color: var(--ptui-text-muted); border-radius: var(--ptui-radius-sm, 6px); cursor: pointer;
  transition: background var(--ptui-duration-fast, 150ms) ease, color var(--ptui-duration-fast, 150ms) ease, transform var(--ptui-duration-normal, 200ms) var(--ptui-ease-standard, ease);
}
.ptui-tree-toggle:hover { background: var(--ptui-bg-subtle); color: var(--ptui-text); }
.ptui-tree-item[aria-expanded="true"] > .ptui-tree-row > .ptui-tree-toggle { transform: rotate(90deg); }
.ptui-tree-toggle--leaf { cursor: default; }
.ptui-tree-toggle--leaf:hover { background: transparent; }
.ptui-tree-grip { flex: none; display: inline-grid; place-items: center; width: 16px; color: var(--ptui-text-subtle); opacity: 0; cursor: grab; transition: opacity var(--ptui-duration-fast, 150ms) ease; }
.ptui-tree-row:hover .ptui-tree-grip, .ptui-tree-item:focus-visible .ptui-tree-grip { opacity: 1; }
.ptui-tree-check {
  flex: none; position: relative; width: 16px; height: 16px; display: inline-grid; place-items: center;
  border: 1px solid var(--ptui-border-strong); border-radius: var(--ptui-radius-sm, 6px);
  background: var(--ptui-surface); color: var(--ptui-text-on-accent);
  transition: background var(--ptui-duration-fast, 150ms) ease, border-color var(--ptui-duration-fast, 150ms) ease;
}
.ptui-tree-check > * { opacity: 0; }
.ptui-tree-check[data-state="checked"], .ptui-tree-check[data-state="indeterminate"] { background: var(--ptui-accent); border-color: var(--ptui-accent); }
.ptui-tree-check[data-state="checked"] > *, .ptui-tree-check[data-state="indeterminate"] > * { opacity: 1; }
.ptui-tree-check[data-state="indeterminate"] > * { transform: scale(.72); }
.ptui-tree-ico { flex: none; display: inline-grid; place-items: center; color: var(--ptui-text-muted); }
.ptui-tree-item[aria-expanded] > .ptui-tree-row > .ptui-tree-ico { color: var(--ptui-accent); }
.ptui-tree-label { font-size: var(--ptui-tree-fs); line-height: 1.45; color: var(--ptui-text); white-space: nowrap; }
.ptui-tree-meta { font-size: 12px; color: var(--ptui-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ptui-tree-meta::before { content: "\00b7"; margin-right: 6px; color: var(--ptui-border-strong); }
.ptui-tree-ext {
  margin-left: auto; font: 600 10px/1 var(--ptui-font-sans); letter-spacing: .04em; text-transform: uppercase;
  color: var(--ptui-text-secondary); background: var(--ptui-bg-subtle);
  border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm, 6px); padding: 3px 5px;
}
.ptui-tree-empty { margin: 0; padding: 24px 12px; text-align: center; font-size: 13px; color: var(--ptui-text-muted); }

/* ==== Peram UI Library — extras.css ====
   DIEU CHINH thu vien (Peram UI Library): pattern chuan cua he Peram KHONG co trong
   sample ver6, tach RIENG khoi components.css de components.css giu verbatim
   (SHA256 trung sample). Hien co: .pill-tabs (segmented status tab — convention
   ATS/Leads/Identity console, chuan hoa ve token --ptui-* thuan; tone qua
   --ptui-st-* o tokens/status.css, token tu flip dark → KHONG can block .dark). */

.pill-tabs { display: flex; flex-wrap: wrap; gap: 10px; }
.pill-tab {
  --pill-tone: var(--ptui-accent);
  --pill-tone-fg: var(--ptui-accent);
  --pill-tone-bg: var(--ptui-accent-soft);
  display: inline-flex; align-items: center; gap: 9px;
  padding: 9px 16px; border-radius: 999px;
  border: 1px solid var(--ptui-border); background: var(--ptui-surface);
  color: var(--ptui-text-secondary);
  font: var(--ptui-weight-medium) var(--ptui-text-md)/1 var(--ptui-font-sans, inherit);
  cursor: pointer; user-select: none;
  transition: background .16s ease, color .16s ease, border-color .16s ease, box-shadow .16s ease;
}
.pill-tab:hover { background: var(--ptui-surface-hover); border-color: var(--ptui-border-strong); color: var(--ptui-text); }
.pill-tab:focus-visible { outline: 2px solid var(--pill-tone); outline-offset: 2px; }
.pill-tab:disabled { opacity: .55; cursor: not-allowed; }
.pill-tab-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--pill-tone); box-shadow: 0 0 0 3px var(--pill-tone-bg);
}
.pill-tab-count {
  min-width: 22px; height: 19px; padding: 0 7px; border-radius: var(--ptui-radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--ptui-text-xs); font-weight: var(--ptui-weight-bold); font-variant-numeric: tabular-nums;
  background: var(--ptui-bg-subtle); color: var(--ptui-text-muted);
}
.pill-tab.is-active {
  background: var(--pill-tone-bg); border-color: var(--pill-tone); color: var(--pill-tone-fg);
  box-shadow: 0 2px 7px -3px rgba(15, 23, 42, .18);
}
.pill-tab.is-active .pill-tab-dot { box-shadow: 0 0 0 3px rgba(255, 255, 255, .6); }
/* Count active: nen tone-FG + chu on-accent. Theo ban Peram Leads.
   O LIGHT tone-FG la mau DAM (thang -700/-800) nen chu on-accent = trang: 5.02-7.58.
   O DARK tone-FG la mau SANG (thang -200/-300) nen chu on-accent PHAI la mau toi —
   day chinh la ly do --ptui-text-on-accent duoc dao sang #09090b o dark (2026-08-14).
   Truoc ban vao do, chu van la trang tren nen sang => 10/10 tone truot, te nhat
   green 1.21:1 (gan nhu vo hinh). Sau: 15.98-16.42. Khoa bang tests/contrast.test.mjs.
   Luu y: KHONG dat nen bang tone base (--pill-tone) — amber chi ~2.07:1 o light. */
.pill-tab.is-active .pill-tab-count { background: var(--pill-tone-fg); color: var(--ptui-text-on-accent); }

/* Tone variants — map --pill-tone sang nhom token --ptui-st-* (tokens/status.css). */
.pill-tab--all    { --pill-tone: var(--ptui-st-all);    --pill-tone-fg: var(--ptui-st-all-fg);    --pill-tone-bg: var(--ptui-st-all-bg); }
.pill-tab--gray   { --pill-tone: var(--ptui-st-gray);   --pill-tone-fg: var(--ptui-st-gray-fg);   --pill-tone-bg: var(--ptui-st-gray-bg); }
.pill-tab--blue   { --pill-tone: var(--ptui-st-blue);   --pill-tone-fg: var(--ptui-st-blue-fg);   --pill-tone-bg: var(--ptui-st-blue-bg); }
.pill-tab--amber  { --pill-tone: var(--ptui-st-amber);  --pill-tone-fg: var(--ptui-st-amber-fg);  --pill-tone-bg: var(--ptui-st-amber-bg); }
.pill-tab--purple { --pill-tone: var(--ptui-st-purple); --pill-tone-fg: var(--ptui-st-purple-fg); --pill-tone-bg: var(--ptui-st-purple-bg); }
.pill-tab--teal   { --pill-tone: var(--ptui-st-teal);   --pill-tone-fg: var(--ptui-st-teal-fg);   --pill-tone-bg: var(--ptui-st-teal-bg); }
.pill-tab--green  { --pill-tone: var(--ptui-st-green);  --pill-tone-fg: var(--ptui-st-green-fg);  --pill-tone-bg: var(--ptui-st-green-bg); }
.pill-tab--red    { --pill-tone: var(--ptui-st-red);    --pill-tone-fg: var(--ptui-st-red-fg);    --pill-tone-bg: var(--ptui-st-red-bg); }
.pill-tab--orange { --pill-tone: var(--ptui-st-orange); --pill-tone-fg: var(--ptui-st-orange-fg); --pill-tone-bg: var(--ptui-st-orange-bg); }
.pill-tab--cyan   { --pill-tone: var(--ptui-st-cyan);   --pill-tone-fg: var(--ptui-st-cyan-fg);   --pill-tone-bg: var(--ptui-st-cyan-bg); }

/* ==== Chart tooltip (DIEU CHINH thu vien 0.3.0) ====
   Tooltip hover cho 4 chart SVG (Bar/Donut/Grouped/Line). Wrapper .ptui-chart
   phai la goc dinh vi; tooltip theo con tro, khong bat su kien chuot. */
.ptui-chart { position: relative; }
.ptui-chart-tip {
  position: absolute; z-index: 30; pointer-events: none;
  transform: translate(12px, -50%);
  max-width: 260px; padding: 8px 11px;
  background: var(--ptui-surface); border: 1px solid var(--ptui-border);
  border-radius: var(--ptui-radius-sm); box-shadow: var(--ptui-shadow-md);
  font: var(--ptui-weight-medium) var(--ptui-text-sm)/1.5 var(--ptui-font-sans, inherit); color: var(--ptui-text);
  animation: ptui-chart-tip-in .12s ease;
}
@keyframes ptui-chart-tip-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .ptui-chart-tip { animation: none; }
}

/* v0.12 — public Untitled UI MIT reference families, expressed in Peram tokens. */
.ptui-qr { position: relative; display: inline-grid; place-content: center; padding: 8px; overflow: hidden; color: var(--ptui-text); }
.ptui-qr--lg { padding: 12px; }
.ptui-qr-code { display: grid; place-content: center; color: var(--ptui-text); }
.ptui-qr-code svg { display: block; max-width: 100%; height: auto; }
.ptui-qr-corner { position: absolute; width: 12px; height: 12px; border-color: var(--ptui-accent); border-style: solid; }
.ptui-qr-corner--tl { top: 0; left: 0; border-width: 2px 0 0 2px; border-radius: var(--ptui-radius-sm) 0 0; }
.ptui-qr-corner--tr { top: 0; right: 0; border-width: 2px 2px 0 0; border-radius: 0 var(--ptui-radius-sm) 0 0; }
.ptui-qr-corner--br { right: 0; bottom: 0; border-width: 0 2px 2px 0; border-radius: 0 0 var(--ptui-radius-sm); }
.ptui-qr-corner--bl { bottom: 0; left: 0; border-width: 0 0 2px 2px; border-radius: 0 0 0 var(--ptui-radius-sm); }
.ptui-qr-scan { position: absolute; inset: 50% 0 0; border-top: 1px solid var(--ptui-accent); background: var(--ptui-accent-soft); opacity: .68; animation: ptui-qr-scan 1.8s var(--ptui-ease-standard) infinite alternate; pointer-events: none; }
@keyframes ptui-qr-scan { from { transform: translateY(-92%); } to { transform: translateY(92%); } }

.ptui-textarea-field { display: grid; gap: 6px; }
.ptui-textarea { min-height: 112px; padding-top: 10px; padding-bottom: 10px; resize: vertical; line-height: 1.5; }
.ptui-file-trigger { display: inline-flex; }
.ptui-file-trigger > input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }

.ptui-progress-circle { position: relative; display: inline-grid; place-content: center; color: var(--ptui-text); }
.ptui-progress-circle svg { grid-area: 1 / 1; transform: rotate(-90deg); }
.ptui-progress-circle circle { fill: none; }
.ptui-progress-circle-track { stroke: var(--ptui-border); }
.ptui-progress-circle-fill { stroke: var(--ptui-accent); stroke-linecap: round; transition: stroke-dashoffset var(--ptui-duration-slow) var(--ptui-ease-decelerate); }
.ptui-progress-circle strong { grid-area: 1 / 1; place-self: center; font-size: var(--ptui-text-md); font-variant-numeric: tabular-nums; }
.ptui-progress-circle--sm strong { font-size: var(--ptui-text-xs); }
.ptui-progress-circle--lg strong { font-size: var(--ptui-text-lg); }

.ptui-rating-stars { display: inline-flex; align-items: center; gap: 2px; color: var(--ptui-warning); }
.ptui-rating-star { width: 20px; height: 20px; }
.ptui-rating-star svg { display: block; width: 100%; height: 100%; stroke: currentColor; stroke-width: 1.5; }
.ptui-rating-stars--sm .ptui-rating-star { width: 16px; height: 16px; }
.ptui-rating-stars--lg .ptui-rating-star { width: 24px; height: 24px; }
.ptui-rating-badge { display: inline-flex; align-items: center; gap: 5px; min-height: 32px; padding: 0 9px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text-muted); font-size: var(--ptui-text-sm); }
.ptui-rating-badge strong { color: var(--ptui-text); font-size: var(--ptui-text-md); }

.ptui-featured-icon { width: 44px; height: 44px; display: inline-grid; place-content: center; border-radius: var(--ptui-radius); background: var(--ptui-accent-soft); color: var(--ptui-accent); box-shadow: 0 0 0 6px var(--ptui-bg-subtle); }
.ptui-featured-icon--sm { width: 36px; height: 36px; }
.ptui-featured-icon--lg { width: 52px; height: 52px; border-radius: var(--ptui-radius-lg); }
.ptui-featured-icon--accent { background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-featured-icon--success { background: var(--ptui-success-soft); color: var(--ptui-success); }
.ptui-featured-icon--warning { background: var(--ptui-warning-soft); color: var(--ptui-warning); }
.ptui-featured-icon--danger { background: var(--ptui-danger-soft); color: var(--ptui-danger); }

.ptui-section-divider { display: flex; align-items: center; gap: 12px; color: var(--ptui-text-muted); font-size: var(--ptui-text-sm); }
.ptui-section-divider::before, .ptui-section-divider::after { content: ""; flex: 1; height: 1px; background: var(--ptui-border); }
.ptui-section-divider:not(:has(span))::before { display: none; }
.ptui-social-button { min-height: var(--ptui-control-height); display: inline-flex; align-items: center; justify-content: center; gap: 9px; padding: 0 14px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); font: var(--ptui-weight-medium) var(--ptui-text-base)/1 var(--ptui-font-sans); box-shadow: var(--ptui-shadow-sm); cursor: pointer; }
.ptui-social-button:hover { background: var(--ptui-bg-subtle); }
.ptui-store-button { min-width: 168px; min-height: 52px; display: inline-flex; align-items: center; gap: 10px; padding: 7px 12px; border-radius: var(--ptui-radius); background: var(--ptui-text); color: var(--ptui-bg); text-decoration: none; }
.ptui-store-mark { width: 28px; display: grid; place-content: center; font-size: var(--ptui-text-xl); }
.ptui-store-button span:last-child { display: grid; gap: 1px; }
.ptui-store-button small { font-size: var(--ptui-text-xs); letter-spacing: .02em; }
.ptui-store-button strong { font-size: var(--ptui-text-lg); }

.ptui-tabs { display: grid; gap: 16px; }
.ptui-tabs-list { display: flex; align-items: center; gap: 4px; border-bottom: 1px solid var(--ptui-border); }
.ptui-tabs-list button { position: relative; min-height: 44px; display: inline-flex; align-items: center; gap: 7px; padding: 0 12px; border: 0; background: transparent; color: var(--ptui-text-muted); font: var(--ptui-weight-medium) var(--ptui-text-md)/1 var(--ptui-font-sans); cursor: pointer; }
.ptui-tabs-list button::after { content: ""; position: absolute; right: 10px; bottom: -1px; left: 10px; height: 2px; border-radius: 2px 2px 0 0; background: transparent; }
.ptui-tabs-list button[aria-selected="true"] { color: var(--ptui-accent); }
.ptui-tabs-list button[aria-selected="true"]::after { background: var(--ptui-accent); }
.ptui-tabs-list button > span { min-width: 22px; padding: 4px 6px; border-radius: 999px; background: var(--ptui-bg-muted); font-size: var(--ptui-text-xs); font-variant-numeric: tabular-nums; }
.ptui-tabs-panel { min-width: 0; }

.ptui-carousel { overflow: hidden; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-lg); background: var(--ptui-surface); box-shadow: var(--ptui-shadow-sm); }
.ptui-carousel-stage { min-height: 180px; display: grid; place-content: center; padding: 24px; }
.ptui-carousel-stage > [role="group"] { width: 100%; }
.ptui-carousel-controls { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 10px 14px; border-top: 1px solid var(--ptui-border); background: var(--ptui-bg-subtle); }
.ptui-carousel-controls button { width: 36px; height: 36px; display: grid; place-content: center; border: 1px solid var(--ptui-border); border-radius: 50%; background: var(--ptui-surface); color: var(--ptui-text); cursor: pointer; }
.ptui-carousel-controls span { min-width: 54px; color: var(--ptui-text-muted); font-size: var(--ptui-text-sm); text-align: center; font-variant-numeric: tabular-nums; }

.ptui-slideout-overlay { position: fixed; z-index: 1000; inset: 0; display: flex; background: var(--ptui-accent-ring); backdrop-filter: blur(2px); }
.ptui-slideout { width: min(var(--ptui-slideout-w, 420px), calc(100vw - 24px)); height: 100%; display: grid; grid-template-rows: auto 1fr auto; margin-left: auto; background: var(--ptui-surface); color: var(--ptui-text); box-shadow: var(--ptui-shadow-lg); animation: ptui-slideout-in var(--ptui-duration-normal) var(--ptui-ease-decelerate); }
.ptui-slideout--left { margin-right: auto; margin-left: 0; }
.ptui-slideout > header, .ptui-slideout > footer { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 18px; border-bottom: 1px solid var(--ptui-border); }
.ptui-slideout > footer { border-top: 1px solid var(--ptui-border); border-bottom: 0; }
.ptui-slideout h2, .ptui-slideout p { margin: 0; }
.ptui-slideout h2 { font-size: var(--ptui-text-lg); }
.ptui-slideout p { margin-top: 4px; color: var(--ptui-text-muted); font-size: var(--ptui-text-md); }
.ptui-slideout header > button { width: 36px; height: 36px; border: 0; border-radius: var(--ptui-radius-sm); background: transparent; color: var(--ptui-text-muted); font-size: var(--ptui-text-xl); cursor: pointer; }
.ptui-slideout-body { overflow: auto; padding: 18px; }
@keyframes ptui-slideout-in { from { transform: translateX(18px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.ptui-slideout--left { animation-name: ptui-slideout-in-left; }
@keyframes ptui-slideout-in-left { from { transform: translateX(-18px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }

.ptui-credit-card { width: min(100%, 360px); aspect-ratio: 1.586; display: grid; align-content: space-between; padding: 22px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-xl); background: var(--ptui-text); color: var(--ptui-bg); box-shadow: var(--ptui-shadow-md); }
.ptui-credit-card--light { background: var(--ptui-surface); color: var(--ptui-text); }
.ptui-credit-card-top, .ptui-credit-card-bottom { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.ptui-credit-card-chip { width: 38px; height: 28px; border: 1px solid currentColor; border-radius: var(--ptui-radius-sm); opacity: .62; }
.ptui-credit-card-number { font-size: clamp(var(--ptui-text-lg), 4vw, var(--ptui-text-2xl)); font-weight: var(--ptui-weight-medium); letter-spacing: .08em; font-variant-numeric: tabular-nums; }
.ptui-credit-card-bottom span { display: grid; gap: 4px; }
.ptui-credit-card-bottom small { opacity: .68; font-size: var(--ptui-text-xs); letter-spacing: .08em; text-transform: uppercase; }
.ptui-credit-card-bottom strong { font-size: var(--ptui-text-sm); letter-spacing: .04em; }

@media (max-width: 560px) {
  .ptui-tabs-list { overflow-x: auto; }
  .ptui-tabs-list button { flex: none; }
  .ptui-carousel-stage { min-height: 150px; padding: 16px; }
  .ptui-credit-card { padding: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .ptui-qr-scan, .ptui-slideout, .ptui-progress-circle-fill { animation: none; transition: none; }
}
.ptui-chart-tip-title {
  font-weight: var(--ptui-weight-bold); color: var(--ptui-text); margin-bottom: 3px; white-space: nowrap;
}
.ptui-chart-tip-row { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.ptui-chart-tip-swatch { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.ptui-chart-tip-label { color: var(--ptui-text-secondary); }
.ptui-chart-tip-value {
  margin-left: auto; padding-left: 12px; font-weight: var(--ptui-weight-bold);
  font-variant-numeric: tabular-nums; color: var(--ptui-text);
}

/* ==== Application primitives (DIEU CHINH thu vien 0.9.0) ====
   Original implementation informed by public Untitled UI behavior, adapted to
   Peram tokens, 44px controls, Vietnamese date format and UTC+7 time display. */
.ptui-calendar { overflow: hidden; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-lg); background: var(--ptui-surface); color: var(--ptui-text); box-shadow: var(--ptui-shadow-sm); }
.ptui-calendar button, .ptui-calendar select { font: inherit; }
.ptui-calendar-head { display: flex; align-items: center; gap: 12px; padding: 16px 18px; border-bottom: 1px solid var(--ptui-border); }
.ptui-calendar-date-tile { width: 62px; height: 62px; flex: none; display: grid; place-content: center; text-align: center; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius); background: var(--ptui-bg-subtle); }
.ptui-calendar-date-tile span { font-size: var(--ptui-text-xs); font-weight: var(--ptui-weight-bold); color: var(--ptui-text-muted); }
.ptui-calendar-date-tile strong { font: var(--ptui-weight-bold) var(--ptui-text-xl)/1 var(--ptui-font-sans); color: var(--ptui-accent); }
.ptui-calendar-title { display: grid; gap: 4px; min-width: 150px; }
.ptui-calendar-title strong { text-transform: capitalize; }
.ptui-calendar-title span { font-size: var(--ptui-text-sm); color: var(--ptui-text-muted); font-variant-numeric: tabular-nums; }
.ptui-calendar-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.ptui-calendar-icon, .ptui-calendar-today, .ptui-calendar-view, .ptui-calendar-add { min-height: var(--ptui-control-height); border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); cursor: pointer; }
.ptui-calendar-icon { width: var(--ptui-control-height); font-size: var(--ptui-text-xl); }
.ptui-calendar-today, .ptui-calendar-view, .ptui-calendar-add { padding: 0 14px; font-weight: var(--ptui-weight-medium); }
.ptui-calendar-add { border-color: var(--ptui-accent); background: var(--ptui-accent); color: var(--ptui-text-on-accent); }
.ptui-calendar-icon:hover, .ptui-calendar-today:hover, .ptui-calendar-view:hover { background: var(--ptui-surface-hover); }
.ptui-calendar button:focus-visible, .ptui-calendar select:focus-visible, .ptui-date-picker button:focus-visible { outline: 2px solid var(--ptui-accent); outline-offset: 2px; }
.ptui-calendar-weekdays, .ptui-calendar-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.ptui-calendar-weekdays { border-bottom: 1px solid var(--ptui-border); }
.ptui-calendar-weekdays span { padding: 10px; text-align: center; font-size: var(--ptui-text-sm); font-weight: var(--ptui-weight-medium); color: var(--ptui-text-muted); }
.ptui-calendar-day { min-height: 126px; padding: 8px; border-right: 1px solid var(--ptui-border); border-bottom: 1px solid var(--ptui-border); background: var(--ptui-surface); }
.ptui-calendar-day:nth-child(7n) { border-right: 0; }
.ptui-calendar-day.is-outside { background: var(--ptui-bg-subtle); color: var(--ptui-text-muted); }
.ptui-calendar-day.is-selected { box-shadow: inset 0 0 0 2px var(--ptui-accent); }
.ptui-calendar-day-number { width: 30px; height: 30px; border: 0; border-radius: 999px; background: transparent; color: inherit; cursor: pointer; }
.ptui-calendar-day.is-selected .ptui-calendar-day-number { background: var(--ptui-accent); color: var(--ptui-text-on-accent); }
.ptui-calendar-events { display: grid; gap: 4px; margin-top: 4px; }
.ptui-calendar-event { width: 100%; min-width: 0; display: flex; justify-content: space-between; gap: 6px; padding: 5px 7px; border: 0; border-radius: var(--ptui-radius-sm); background: var(--ptui-accent-soft); color: var(--ptui-accent); font-size: var(--ptui-text-xs) !important; text-align: left; cursor: pointer; }
.ptui-calendar-event span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--ptui-weight-medium); }
.ptui-calendar-event time { flex: none; font-variant-numeric: tabular-nums; }
.ptui-calendar-event--success { background: var(--ptui-success-soft); color: var(--ptui-success); }
.ptui-calendar-event--warning { background: var(--ptui-warning-soft); color: var(--ptui-warning); }
.ptui-calendar-event--danger { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
.ptui-calendar-event--neutral { background: var(--ptui-bg-muted); color: var(--ptui-text-secondary); }
.ptui-calendar-more { font-size: var(--ptui-text-xs); color: var(--ptui-text-muted); }
.ptui-calendar-time-head { margin-left: 60px; display: flex; border-bottom: 1px solid var(--ptui-border); }
.ptui-calendar-time-head button { flex: 1; min-height: 58px; border: 0; border-right: 1px solid var(--ptui-border); background: var(--ptui-surface); color: var(--ptui-text-secondary); cursor: pointer; }
.ptui-calendar-time-head button span, .ptui-calendar-time-head button strong { display: block; }
.ptui-calendar-time-head button.is-selected { color: var(--ptui-accent); background: var(--ptui-accent-soft); }
.ptui-calendar-timeline--day .ptui-calendar-time-head button:not(.is-selected) { display: none; }
.ptui-calendar-time-body { max-height: 620px; overflow: auto; }
.ptui-calendar-hour { min-height: 62px; display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid var(--ptui-border); }
.ptui-calendar-timeline--week .ptui-calendar-hour { grid-template-columns: 60px repeat(7, minmax(0, 1fr)); }
.ptui-calendar-hour > time { padding: 8px; font: var(--ptui-weight-medium) var(--ptui-text-xs)/1 var(--ptui-font-sans); color: var(--ptui-text-muted); text-align: right; font-variant-numeric: tabular-nums; }
.ptui-calendar-hour > div { padding: 5px 8px; border-left: 1px solid var(--ptui-border); }

.ptui-date-picker { position: relative; display: inline-block; max-width: 100%; }
.ptui-date-picker-control { display: flex; align-items: end; }
.ptui-date-field { display: grid; gap: 6px; color: var(--ptui-text-secondary); font-size: var(--ptui-text-md); font-weight: var(--ptui-weight-medium); letter-spacing: -.005em; }
.ptui-date-field input { width: 168px; height: var(--ptui-control-height); padding: 0 12px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); font: var(--ptui-weight-regular) var(--ptui-text-base)/1 var(--ptui-font-sans); font-variant-numeric: tabular-nums; }
.ptui-date-picker-control > button { width: var(--ptui-control-height); height: var(--ptui-control-height); margin-left: -1px; border: 1px solid var(--ptui-border); border-radius: 0 var(--ptui-radius-sm) var(--ptui-radius-sm) 0; background: var(--ptui-bg-subtle); color: var(--ptui-text); cursor: pointer; }
.ptui-date-picker-control .ptui-date-field input { border-radius: var(--ptui-radius-sm) 0 0 var(--ptui-radius-sm); }
.ptui-date-popover { position: absolute; z-index: 40; top: calc(100% + 8px); left: 0; width: min(760px, 90vw); box-shadow: var(--ptui-shadow-lg); }
.ptui-date-popover .ptui-calendar-actions .ptui-calendar-view, .ptui-date-popover .ptui-calendar-add { display: none; }
.ptui-date-range { display: flex; align-items: end; gap: 10px; margin: 0; padding: 0; border: 0; }
.ptui-date-range legend { width: 100%; margin-bottom: 8px; color: var(--ptui-text); font-size: var(--ptui-text-md); font-weight: var(--ptui-weight-bold); }

.ptui-uploader { display: grid; gap: 14px; color: var(--ptui-text); }
.ptui-uploader-drop { min-height: 172px; display: grid; place-content: center; justify-items: center; gap: 7px; padding: 22px; text-align: center; border: 1px dashed var(--ptui-border-strong); border-radius: var(--ptui-radius-lg); background: var(--ptui-bg-subtle); transition: border-color var(--ptui-duration-fast), background var(--ptui-duration-fast), transform var(--ptui-duration-fast); }
.ptui-uploader-drop.is-dragging { border-color: var(--ptui-accent); background: var(--ptui-accent-soft); transform: scale(.995); }
.ptui-uploader-drop.is-disabled { opacity: .55; }
.ptui-uploader-icon { width: 44px; height: 44px; display: grid; place-content: center; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius); background: var(--ptui-surface); color: var(--ptui-text-secondary); box-shadow: var(--ptui-shadow-sm); }
.ptui-uploader-icon svg { width: 22px; height: 22px; }
.ptui-uploader-drop p { margin: 3px 0 0; font-size: var(--ptui-text-base); color: var(--ptui-text-secondary); }
.ptui-uploader-drop p button { padding: 0; border: 0; background: transparent; color: var(--ptui-accent); font: inherit; font-weight: var(--ptui-weight-bold); cursor: pointer; }
.ptui-uploader-drop > span:last-child { font-size: var(--ptui-text-sm); color: var(--ptui-text-muted); }
.ptui-uploader-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.ptui-uploader-item { display: flex; align-items: center; gap: 12px; min-height: 76px; padding: 12px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius); background: var(--ptui-surface); }
.ptui-uploader-item--error { border-color: var(--ptui-danger); }
.ptui-file-type-icon { display: inline-grid; place-items: center; flex: none; vertical-align: middle; }
.ptui-file-icon-theme { display: grid; grid-area: 1 / 1; place-items: center; }
.ptui-file-icon-theme--dark { display: none; }
[data-theme="dark"] .ptui-file-icon-theme--light { display: none; }
[data-theme="dark"] .ptui-file-icon-theme--dark { display: grid; }
.ptui-uploader-file-icon { width: 44px; min-width: 44px; }
.ptui-uploader-meta { min-width: 0; flex: 1; display: grid; gap: 5px; }
.ptui-uploader-meta strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--ptui-text-md); }
.ptui-uploader-meta > span { font-size: var(--ptui-text-sm); color: var(--ptui-text-muted); }
.ptui-uploader-status { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; }
.ptui-uploader-status svg { width: 15px; height: 15px; flex: none; }
.ptui-uploader-status--complete { color: var(--ptui-success) !important; }
.ptui-uploader-status--error { color: var(--ptui-danger) !important; }
.ptui-uploader-progress { height: 7px; overflow: hidden; border-radius: 999px; background: var(--ptui-bg-muted); }
.ptui-uploader-progress span { display: block; height: 100%; border-radius: inherit; background: var(--ptui-accent); transition: width var(--ptui-duration-normal) var(--ptui-ease-standard); }
.ptui-uploader-item-actions { display: flex; gap: 4px; }
.ptui-uploader-item-actions button { min-width: 36px; height: 36px; border: 0; border-radius: var(--ptui-radius-sm); background: transparent; color: var(--ptui-text-secondary); font: var(--ptui-weight-medium) var(--ptui-text-md)/1 var(--ptui-font-sans); cursor: pointer; }
.ptui-uploader-item-actions button:hover { background: var(--ptui-bg-muted); }
.ptui-uploader-item-actions button:focus-visible { outline: 3px solid var(--ptui-accent-ring); outline-offset: 1px; }
.ptui-uploader-item-actions button svg { width: 17px; height: 17px; }

.ptui-select, .ptui-slider { display: grid; gap: 6px; color: var(--ptui-text); font-size: var(--ptui-text-md); font-weight: var(--ptui-weight-medium); }
.ptui-select select { width: 100%; min-width: 180px; height: var(--ptui-control-height); padding: 0 38px 0 12px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); font: var(--ptui-weight-medium) var(--ptui-text-base)/1 var(--ptui-font-sans); }
.ptui-field-error { color: var(--ptui-danger); }
.ptui-field-label { display: block; margin-bottom: 6px; font-size: var(--ptui-text-md); font-weight: var(--ptui-weight-medium); color: var(--ptui-text); }
.ptui-multiselect { position: relative; min-width: 230px; }
.ptui-multiselect > button { width: 100%; min-height: var(--ptui-control-height); display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 12px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); font: var(--ptui-weight-medium) var(--ptui-text-base)/1 var(--ptui-font-sans); cursor: pointer; }
.ptui-multiselect-values { display: flex; flex-wrap: wrap; gap: 4px; }
.ptui-multiselect-values span, .ptui-multiselect-values b { padding: 5px 8px; border-radius: var(--ptui-radius-sm); background: var(--ptui-accent-soft); color: var(--ptui-accent); font-size: var(--ptui-text-xs); }
.ptui-placeholder { color: var(--ptui-text-muted); }
.ptui-multiselect-menu { position: absolute; z-index: 35; top: calc(100% + 6px); left: 0; right: 0; display: grid; gap: 2px; padding: 6px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius); background: var(--ptui-surface); box-shadow: var(--ptui-shadow-md); }
.ptui-multiselect-menu button { min-height: 38px; display: flex; align-items: center; gap: 9px; padding: 0 8px; border: 0; border-radius: var(--ptui-radius-sm); background: transparent; color: var(--ptui-text); text-align: left; cursor: pointer; }
.ptui-multiselect-menu button:hover { background: var(--ptui-bg-muted); }
.ptui-multiselect-check { width: 20px; height: 20px; display: grid; place-content: center; border: 1px solid var(--ptui-border-strong); border-radius: var(--ptui-radius-sm); color: var(--ptui-accent); }
.ptui-toggle-row { display: inline-flex; align-items: flex-start; gap: 10px; padding: 0; border: 0; background: transparent; color: var(--ptui-text); text-align: left; cursor: pointer; }
.ptui-toggle { width: 44px; height: 24px; flex: none; padding: 2px; border-radius: 999px; background: var(--ptui-bg-muted); transition: background var(--ptui-duration-fast); }
.ptui-toggle span { display: block; width: 20px; height: 20px; border-radius: 50%; background: var(--ptui-surface); box-shadow: var(--ptui-shadow-sm); transition: transform var(--ptui-duration-fast) var(--ptui-ease-standard); }
.ptui-toggle-row[aria-checked="true"] .ptui-toggle { background: var(--ptui-accent); }
.ptui-toggle-row[aria-checked="true"] .ptui-toggle span { transform: translateX(20px); }
.ptui-toggle-copy { display: grid; gap: 3px; }
.ptui-toggle-copy strong { font-size: var(--ptui-text-base); }
.ptui-toggle-copy small { color: var(--ptui-text-muted); font-size: var(--ptui-text-sm); }
.ptui-toggle-row--sm .ptui-toggle { width: 36px; height: 20px; }
.ptui-toggle-row--sm .ptui-toggle span { width: 16px; height: 16px; }
.ptui-toggle-row--sm[aria-checked="true"] .ptui-toggle span { transform: translateX(16px); }
.ptui-slider > span { display: flex; justify-content: space-between; }
.ptui-slider output { color: var(--ptui-text-muted); font-variant-numeric: tabular-nums; }
.ptui-slider input { width: 100%; height: 24px; margin: 0; accent-color: var(--ptui-accent); cursor: pointer; }
.ptui-tag { display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 9px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-bg-subtle); color: var(--ptui-text-secondary); font: var(--ptui-weight-medium) var(--ptui-text-sm)/1 var(--ptui-font-sans); }
button.ptui-tag { cursor: pointer; }
.ptui-tag--accent, .ptui-tag.is-selected { border-color: var(--ptui-accent); background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-tag--success { background: var(--ptui-success-soft); color: var(--ptui-success); }
.ptui-tag--warning { background: var(--ptui-warning-soft); color: var(--ptui-warning); }
.ptui-tag--danger { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
.ptui-tag > button { width: 22px; height: 22px; padding: 0; border: 0; background: transparent; color: currentColor; cursor: pointer; }
.ptui-pin { display: flex; gap: 8px; }
.ptui-pin input { width: var(--ptui-control-height); height: 52px; padding: 0; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); font: var(--ptui-weight-bold) var(--ptui-text-xl)/1 var(--ptui-font-sans); text-align: center; font-variant-numeric: tabular-nums; }

.ptui-alert { display: grid; grid-template-columns: auto 1fr auto; align-items: start; gap: 11px; padding: 14px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius); background: var(--ptui-bg-subtle); color: var(--ptui-text); }
.ptui-alert-icon { width: 24px; height: 24px; display: grid; place-content: center; border-radius: 50%; background: var(--ptui-accent-soft); color: var(--ptui-accent); font-weight: var(--ptui-weight-bold); }
.ptui-alert strong { font-size: var(--ptui-text-base); }
.ptui-alert p { margin: 4px 0 0; color: var(--ptui-text-secondary); font-size: var(--ptui-text-md); }
.ptui-alert--success .ptui-alert-icon { background: var(--ptui-success-soft); color: var(--ptui-success); }
.ptui-alert--warning .ptui-alert-icon { background: var(--ptui-warning-soft); color: var(--ptui-warning); }
.ptui-alert--danger .ptui-alert-icon { background: var(--ptui-danger-soft); color: var(--ptui-danger); }
.ptui-alert-actions { display: flex; gap: 4px; }
.ptui-alert-actions button { min-height: 32px; padding: 0 8px; border: 0; border-radius: var(--ptui-radius-sm); background: transparent; color: var(--ptui-accent); font-weight: var(--ptui-weight-bold); cursor: pointer; }
.ptui-empty { display: grid; justify-items: center; gap: 8px; padding: 32px 20px; text-align: center; color: var(--ptui-text); }
.ptui-empty-icon { width: 54px; height: 54px; display: grid; place-content: center; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-lg); background: var(--ptui-bg-subtle); color: var(--ptui-accent); font-size: var(--ptui-text-2xl); box-shadow: var(--ptui-shadow-sm); }
.ptui-empty h3, .ptui-empty p { margin: 0; }
.ptui-empty p { max-width: 440px; color: var(--ptui-text-muted); font-size: var(--ptui-text-md); }
.ptui-empty-actions { display: flex; gap: 8px; margin-top: 8px; }
/* 0.14.0 — them :not(.ptui-btn). Selector descendant nay co specificity (0,1,1),
   CAO HON .ptui-btn-primary (0,1,0), nen no de mat nut that khi EmptyState emit
   .ptui-btn. Gio chi con ap cho nut tu do consumer truyen qua children. */
.ptui-empty-actions button:not(.ptui-btn) { min-height: var(--ptui-control-height); padding: 0 14px; border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-sm); background: var(--ptui-surface); color: var(--ptui-text); font-weight: var(--ptui-weight-medium); cursor: pointer; }
.ptui-empty-actions .ptui-empty-primary:not(.ptui-btn) { border-color: var(--ptui-accent); background: var(--ptui-accent); color: var(--ptui-text-on-accent); }
.ptui-pagination { display: flex; align-items: center; justify-content: center; gap: 4px; }
.ptui-pagination button { min-width: var(--ptui-control-height); height: var(--ptui-control-height); padding: 0 11px; border: 1px solid transparent; border-radius: var(--ptui-radius-sm); background: transparent; color: var(--ptui-text-secondary); font-weight: var(--ptui-weight-medium); cursor: pointer; }
.ptui-pagination button:hover { background: var(--ptui-bg-muted); color: var(--ptui-text); }
.ptui-pagination button[aria-current="page"] { border-color: var(--ptui-accent); background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-pagination button:disabled { opacity: .45; cursor: not-allowed; }
.ptui-pagination button span { margin: 0 5px; }
.ptui-pagination-ellipsis { padding: 0 5px; color: var(--ptui-text-muted); }
.ptui-pagination--compact > span { color: var(--ptui-text-muted); font-size: var(--ptui-text-md); }
.ptui-steps { display: flex; margin: 0; padding: 0; list-style: none; }
.ptui-step { position: relative; flex: 1; }
.ptui-step:not(:last-child)::after { content: ""; position: absolute; top: 17px; left: calc(50% + 24px); right: calc(-50% + 24px); height: 2px; background: var(--ptui-border); }
.ptui-step.is-complete:not(:last-child)::after { background: var(--ptui-accent); }
.ptui-step > button, .ptui-step > div { width: 100%; display: grid; justify-items: center; gap: 7px; padding: 0 8px; border: 0; background: transparent; color: var(--ptui-text-muted); text-align: center; }
.ptui-step > button { cursor: pointer; }
.ptui-step-index { position: relative; z-index: 1; width: 36px; height: 36px; display: grid; place-content: center; border: 1px solid var(--ptui-border-strong); border-radius: 50%; background: var(--ptui-surface); color: var(--ptui-text-muted); font-weight: var(--ptui-weight-bold); }
.ptui-step.is-current .ptui-step-index, .ptui-step.is-complete .ptui-step-index { border-color: var(--ptui-accent); background: var(--ptui-accent); color: var(--ptui-text-on-accent); }
.ptui-step strong, .ptui-step small { display: block; }
.ptui-step strong { color: var(--ptui-text); font-size: var(--ptui-text-md); }
.ptui-step small { margin-top: 3px; font-size: var(--ptui-text-xs); }
.ptui-steps--vertical { display: grid; }
.ptui-steps--vertical .ptui-step > button, .ptui-steps--vertical .ptui-step > div { grid-template-columns: 36px 1fr; justify-items: start; text-align: left; padding: 0 0 20px; }
.ptui-steps--vertical .ptui-step:not(:last-child)::after { top: 36px; bottom: 0; left: 17px; right: auto; width: 2px; height: auto; }
.ptui-loading { width: 44px; height: 44px; display: inline-grid; place-content: center; }
.ptui-loading-spinner { width: 26px; height: 26px; border: 3px solid var(--ptui-border); border-top-color: var(--ptui-accent); border-radius: 50%; animation: ptui-spin .8s linear infinite; }
.ptui-loading--sm .ptui-loading-spinner { width: 18px; height: 18px; border-width: 2px; }
.ptui-loading--lg .ptui-loading-spinner { width: 36px; height: 36px; }
.ptui-loading.is-inline { width: 24px; height: 24px; }
.ptui-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
@keyframes ptui-spin { to { transform: rotate(360deg); } }

@media (max-width: 760px) {
  .ptui-calendar-head { align-items: flex-start; flex-wrap: wrap; padding: 12px; }
  .ptui-calendar-actions { width: 100%; margin-left: 0; flex-wrap: wrap; }
  .ptui-calendar-add { margin-left: auto; }
  .ptui-calendar-day { min-height: 84px; padding: 4px; }
  .ptui-calendar-event { display: block; width: 7px; height: 7px; margin: 2px; padding: 0; border-radius: 50%; }
  .ptui-calendar-event span, .ptui-calendar-event time, .ptui-calendar-more { display: none; }
  .ptui-date-range { align-items: stretch; flex-direction: column; }
  .ptui-date-range > span { display: none; }
  .ptui-pin { gap: 5px; }
  .ptui-pin input { width: 38px; height: 46px; }
  .ptui-pagination:not(.ptui-pagination--compact) button span { display: none; }
  .ptui-pagination:not(.ptui-pagination--compact) { max-width: 100%; justify-content: flex-start; overflow-x: auto; padding-bottom: 4px; }
  .ptui-step small { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .ptui-uploader-drop, .ptui-uploader-progress span, .ptui-toggle, .ptui-toggle span { transition: none; }
  .ptui-loading-spinner { animation-duration: 1.6s; }
}

/* ==== v0.13 — Overlay + announcement families (DIEU CHINH thu vien) ====
   Bon nhom duoc nang cap: popup/modal · dialog · warning alert · announcement.
   Nguon doi chieu: Untitled UI (featured icon, backdrop blur, bottom-sheet responsive),
   Atlassian (thang width 400/600/800/968), Carbon (chi body cuon, nut mobile full-width),
   GitHub Primer (danger dialog focus vao nut AN TOAN), WAI-ARIA APG (dialog + alert).
   MOI thu o day chi tieu thu var(--ptui-*) — 0 hex moi, 0 hue thu hai.
   Dat trong extras.css de components.css giu md5 trung sample ver6. */

/* --- (1) SUA BUG THANG Z-INDEX --------------------------------------------
   components.css hardcode 4 cho, gay 2 loi that (chi tiet o tokens/zindex.css).
   Override tai day vi extras.css nam SAU components.css trong dist/styles.css
   => cung specificity, rule sau thang. Khong can !important. */
.ptui-modal-overlay { z-index: var(--ptui-z-modal); }
.ptui-menu { z-index: var(--ptui-z-popover); }
.ptui-dt-pop { z-index: var(--ptui-z-popover); }
.ptui-dt-drag-ghost { z-index: var(--ptui-z-drag-ghost); }
.ptui-slideout-overlay { z-index: var(--ptui-z-modal); }
.ptui-date-popover { z-index: var(--ptui-z-popover); }

/* --- (2) MODAL: thang size co ten -----------------------------------------
   .ptui-modal da doc `max-width: var(--ptui-modal-w, 480px)` san => chi can set bien.
   So lay tu Atlassian (400/600/800/968) + shadcn (512). */
.ptui-modal[data-size="xs"] { --ptui-modal-w: 400px; }
.ptui-modal[data-size="sm"] { --ptui-modal-w: 512px; }
.ptui-modal[data-size="md"] { --ptui-modal-w: 600px; }
.ptui-modal[data-size="lg"] { --ptui-modal-w: 800px; }
.ptui-modal[data-size="xl"] { --ptui-modal-w: 968px; }
.ptui-modal[data-size="full"] { --ptui-modal-w: none; width: 100%; height: calc(100dvh - 48px); }

/* --- (3) MODAL: backdrop blur + 3 placement -------------------------------
   Untitled UI dung overlay 70% + blur 6px; components.css dang blur 2px. */
.ptui-modal-overlay { backdrop-filter: blur(6px); }
.ptui-modal-overlay[data-placement="bottom"] { place-items: end center; padding: 0; }
.ptui-modal-overlay[data-placement="bottom"] .ptui-modal {
  max-width: none; width: 100%; border-bottom: 0; max-height: 88dvh;
  border-radius: var(--ptui-radius-xl) var(--ptui-radius-xl) 0 0;
  animation: ptui-sheet-up var(--ptui-duration-slow) var(--ptui-ease-decelerate);
}
/* Tay nam keo cua bottom-sheet — 100x5px bo tron, chuan vaul/shadcn Drawer */
.ptui-modal-overlay[data-placement="bottom"] .ptui-modal::before {
  content: ""; width: 100px; height: 5px; margin: 10px auto 0; flex: 0 0 auto;
  border-radius: 999px; background: var(--ptui-border-strong);
}
@keyframes ptui-sheet-up { from { transform: translateY(24px); opacity: 0; } }
.ptui-modal-overlay[data-placement="drawer-right"],
.ptui-modal-overlay[data-placement="drawer-left"] { padding: 0; }
.ptui-modal-overlay[data-placement="drawer-right"] { place-items: stretch end; }
.ptui-modal-overlay[data-placement="drawer-left"] { place-items: stretch start; }
.ptui-modal-overlay[data-placement="drawer-right"] .ptui-modal,
.ptui-modal-overlay[data-placement="drawer-left"] .ptui-modal {
  height: 100dvh; max-height: 100dvh; border-radius: 0;
  animation: ptui-drawer-in var(--ptui-duration-slow) var(--ptui-ease-decelerate);
}
.ptui-modal-overlay[data-placement="drawer-right"] .ptui-modal { border-right: 0; }
.ptui-modal-overlay[data-placement="drawer-left"] .ptui-modal { border-left: 0; animation-name: ptui-drawer-in-left; }
@keyframes ptui-drawer-in { from { transform: translateX(16px); opacity: 0; } }
@keyframes ptui-drawer-in-left { from { transform: translateX(-16px); opacity: 0; } }

/* --- (4) MODAL: exit animation (data-state) -------------------------------
   usePresence giu node song them dung --ptui-duration-normal roi thao.
   Luat motion: EXIT nhanh hon ENTER (200 vs 300) va dung ease-accelerate. */
.ptui-modal-overlay[data-state="closed"] { animation: ptui-modal-fade var(--ptui-duration-normal) var(--ptui-ease-accelerate) reverse forwards; }
.ptui-modal-overlay[data-state="closed"] .ptui-modal { animation: ptui-modal-pop var(--ptui-duration-normal) var(--ptui-ease-accelerate) reverse forwards; }

/* --- (5) MODAL: bong bao "con noi dung de cuon" ---------------------------
   Ky thuat gradient local/scroll: lop `local` cuon THEO noi dung nen che bong
   khi da cuon het; lop `scroll` dung yen nen chi lo ra khi CON cuon duoc
   => tu an khi khong tran, khong can JS, khong can do chieu cao.
   Mau bong lay tu color-mix cua --ptui-text: o dark thanh vet SANG, dung luat
   "dark: elevation the hien bang be mat sang hon", khong phai bong den. */
.ptui-modal-body {
  background:
    linear-gradient(var(--ptui-surface) 30%, transparent) top / 100% 20px no-repeat local,
    linear-gradient(transparent, var(--ptui-surface) 70%) bottom / 100% 20px no-repeat local,
    radial-gradient(farthest-side at 50% 0, color-mix(in srgb, var(--ptui-text) 12%, transparent), transparent) top / 100% 8px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, color-mix(in srgb, var(--ptui-text) 12%, transparent), transparent) bottom / 100% 8px no-repeat scroll;
}

/* --- (6) MODAL: header co featured icon -----------------------------------
   Tai dung .ptui-featured-icon da co tu 0.12 — khong ve khoi icon moi. */
.ptui-modal-head[data-lead="icon"] { align-items: flex-start; }
.ptui-modal-head > .ptui-featured-icon { flex: 0 0 auto; margin-top: 2px; }

/* --- (7) DIALOG: spinner tren nut xac nhan + o go-de-xac-nhan -------------- */
.ptui-btn-spinner {
  width: 15px; height: 15px; flex: 0 0 auto; border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 35%, transparent);
  border-top-color: currentColor; animation: ptui-spin .7s linear infinite;
}
.ptui-confirm-type { display: grid; gap: 7px; margin-top: 14px; }
.ptui-confirm-type-label { font-size: var(--ptui-text-md); color: var(--ptui-text-secondary); }
.ptui-confirm-type-label code {
  padding: 1px 6px; border-radius: var(--ptui-radius-sm);
  background: var(--ptui-bg-muted); color: var(--ptui-text);
  font-family: var(--ptui-font-sans); font-weight: var(--ptui-weight-bold);
}

/* --- (8) WARNING ALERT: 6 tone x 3 bien the nen x 2 bo cuc ----------------
   Bien --alert-tone/-soft la diem re DUY NHAT => them tone chi ton 1 dong.
   `info` KHONG co token rieng trong he (colors.css ghi ro) => tai dung accent. */
.ptui-alert {
  --alert-tone: var(--ptui-accent);
  --alert-soft: var(--ptui-accent-soft);
  gap: 12px; align-items: start;
}
.ptui-alert--info { --alert-tone: var(--ptui-accent); --alert-soft: var(--ptui-accent-soft); }
.ptui-alert--neutral { --alert-tone: var(--ptui-text-secondary); --alert-soft: var(--ptui-bg-muted); }
.ptui-alert--success { --alert-tone: var(--ptui-success); --alert-soft: var(--ptui-success-soft); }
.ptui-alert--warning { --alert-tone: var(--ptui-warning); --alert-soft: var(--ptui-warning-soft); }
.ptui-alert--danger { --alert-tone: var(--ptui-danger); --alert-soft: var(--ptui-danger-soft); }
.ptui-alert-icon { background: var(--alert-soft); color: var(--alert-tone); }
.ptui-alert-title { margin: 0; font-size: var(--ptui-text-base); font-weight: var(--ptui-weight-medium); color: var(--ptui-text); }
/* Chu phu dung text-secondary (KHONG text-muted): nen bg-subtle/-soft dam hon surface
   nen muted truot AA — luat khoa trong tokens/colors.css + contrast.test.mjs. */
.ptui-alert-text { margin: 4px 0 0; font-size: var(--ptui-text-md); line-height: 1.55; color: var(--ptui-text-secondary); }
.ptui-alert-links { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; }
.ptui-alert-link {
  min-height: 24px; padding: 0; border: 0; background: none;
  color: var(--alert-tone); font: var(--ptui-weight-medium) var(--ptui-text-md)/1.4 var(--ptui-font-sans); cursor: pointer;
}
.ptui-alert-link:hover { text-decoration: underline; }
.ptui-alert-link:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; border-radius: var(--ptui-radius-sm); }
.ptui-alert-close {
  width: 28px; height: 28px; display: grid; place-content: center; flex: 0 0 auto;
  border: 0; border-radius: var(--ptui-radius-sm); background: none;
  color: var(--ptui-text-secondary); cursor: pointer;
  transition: background var(--ptui-duration-fast) var(--ptui-ease-standard);
}
.ptui-alert-close:hover { background: var(--ptui-bg-muted); color: var(--ptui-text); }
.ptui-alert-close:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 1px; }
/* Bien the nen: accent-border-left (Carbon) va solid (nen mau nhat toan khoi) */
.ptui-alert--accent { border-left: 3px solid var(--alert-tone); border-radius: 0 var(--ptui-radius) var(--ptui-radius) 0; }
.ptui-alert--solid { background: var(--alert-soft); border-color: color-mix(in srgb, var(--alert-tone) 28%, transparent); }
.ptui-alert--solid .ptui-alert-icon { background: transparent; }
/* Bo cuc featured: o icon lon 40px thay vong tron 24px */
.ptui-alert--featured { gap: 14px; padding: 16px; }
.ptui-alert--featured .ptui-alert-icon { width: 40px; height: 40px; border-radius: var(--ptui-radius); }
/* Cap TRANG => vuong goc (luat Fluent: square = page-level, rounded = component-level) */
.ptui-alert--square { border-radius: 0; border-left-width: 0; border-right-width: 0; }

/* --- (9) ANNOUNCEMENT / BANNER -------------------------------------------
   Khac Alert o CHO DUNG: Banner la thong bao CAP TRANG / CAP SAN PHAM, song lau,
   co CTA, dismiss duoc, co the ghim dau trang. Alert nam TRONG luong tac vu.
   Dung chung bien --alert-tone/-soft nen hai ho khong bao gio lech mau nhau. */
.ptui-banner {
  --alert-tone: var(--ptui-accent);
  --alert-soft: var(--ptui-accent-soft);
  position: relative; width: 100%;
  border-bottom: 1px solid var(--ptui-border);
  background: var(--alert-soft); color: var(--ptui-text);
}
/* Khai TUONG MINH du tri so trung base: tone mac dinh van sinh class `--info`, de trong
   thi do la class mo coi (Consistency Gate muc 6). Khai ro cung lam y do doc duoc. */
.ptui-banner--info { --alert-tone: var(--ptui-accent); --alert-soft: var(--ptui-accent-soft); }
.ptui-banner--neutral { --alert-tone: var(--ptui-text-secondary); --alert-soft: var(--ptui-bg-subtle); }
.ptui-banner--success { --alert-tone: var(--ptui-success); --alert-soft: var(--ptui-success-soft); }
.ptui-banner--warning { --alert-tone: var(--ptui-warning); --alert-soft: var(--ptui-warning-soft); }
.ptui-banner--danger { --alert-tone: var(--ptui-danger); --alert-soft: var(--ptui-danger-soft); }
.ptui-banner-inner {
  display: flex; align-items: flex-start; gap: 12px;
  max-width: 1280px; margin: 0 auto; padding: 14px 16px;
}
.ptui-banner-icon {
  width: 32px; height: 32px; flex: 0 0 auto; display: grid; place-content: center;
  border-radius: var(--ptui-radius-sm);
  background: color-mix(in srgb, var(--alert-tone) 14%, transparent);
  color: var(--alert-tone);
}
.ptui-banner-content { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }
.ptui-banner-title { margin: 0; font-size: var(--ptui-text-base); font-weight: var(--ptui-weight-medium); }
.ptui-banner-text { margin: 0; font-size: var(--ptui-text-md); line-height: 1.55; color: var(--ptui-text-secondary); }
.ptui-banner-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.ptui-banner-close {
  width: 32px; height: 32px; display: grid; place-content: center; flex: 0 0 auto;
  border: 0; border-radius: var(--ptui-radius-sm); background: none;
  color: var(--ptui-text-secondary); cursor: pointer;
  transition: background var(--ptui-duration-fast) var(--ptui-ease-standard);
}
.ptui-banner-close:hover { background: color-mix(in srgb, var(--alert-tone) 12%, transparent); color: var(--ptui-text); }
.ptui-banner-close:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 1px; }
/* slim: mot dong, icon tran, cho thong bao ngan */
.ptui-banner--slim .ptui-banner-inner { align-items: center; padding: 9px 16px; }
.ptui-banner--slim .ptui-banner-icon { width: 20px; height: 20px; background: none; }
.ptui-banner--slim .ptui-banner-content { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* ghim dau trang: sticky DAY layout xuong, khong de len header */
.ptui-banner--sticky { position: sticky; top: 0; z-index: var(--ptui-z-sticky-banner); }
/* the noi goc man hinh — "what's new", toi da 400px theo thang Untitled UI */
.ptui-banner--floating {
  position: fixed; right: 24px; bottom: 24px; left: auto;
  width: min(400px, calc(100vw - 48px));
  z-index: var(--ptui-z-sticky-banner);
  border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius-lg);
  background: var(--ptui-surface); box-shadow: var(--ptui-shadow-lg);
  animation: ptui-banner-in var(--ptui-duration-slow) var(--ptui-ease-decelerate);
}
.ptui-banner--floating .ptui-banner-inner { flex-direction: column; padding: 16px; }
.ptui-banner--floating .ptui-banner-actions { width: 100%; }
.ptui-banner--floating .ptui-banner-close { position: absolute; top: 8px; right: 8px; }
.ptui-banner-media { width: 100%; border-radius: var(--ptui-radius); margin-bottom: 4px; }
@keyframes ptui-banner-in { from { opacity: 0; transform: translateY(12px); } }
.ptui-banner[data-state="closed"] { animation: ptui-banner-in var(--ptui-duration-normal) var(--ptui-ease-accelerate) reverse forwards; }

@media (max-width: 600px) {
  /* Footer dialog: mobile xep DOC, nut full-width, nut chinh NAM TREN
     (column-reverse => con cuoi cua DOM len dau). Chuan shadcn/Carbon. */
  .ptui-modal-foot { flex-direction: column-reverse; align-items: stretch; }
  .ptui-modal-foot > * { width: 100%; }
  .ptui-banner-inner { flex-wrap: wrap; }
  .ptui-banner-actions { width: 100%; }
  .ptui-banner-actions > * { flex: 1 1 auto; }
  .ptui-banner--floating { right: 12px; left: 12px; bottom: 12px; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  /* Truoc 0.13 CHI .ptui-toast duoc tat animation — modal/menu/tooltip/banner van chay.
     Cac rule nay nam SAU components.css nen thang ma khong can !important. */
  .ptui-modal-overlay, .ptui-modal, .ptui-menu, .ptui-banner,
  .ptui-slideout, .ptui-modal-overlay[data-state="closed"],
  .ptui-modal-overlay[data-state="closed"] .ptui-modal,
  .ptui-banner[data-state="closed"] { animation: none; }
  .ptui-tip-pop { transition-duration: 1ms; }
  .ptui-btn-spinner { animation-duration: 1.6s; }
}

/* --- (10) MODAL placement="responsive" -----------------------------------
   Desktop giu nguyen modal giua man; mobile bien thanh bottom-sheet. Mot
   component lo ca hai truong hop, dung pattern Primer position={{narrow:'bottom',
   regular:'center'}} — thay vi bat consumer tu doi sang Drawer o breakpoint. */
@media (max-width: 600px) {
  .ptui-modal-overlay[data-placement="responsive"] { place-items: end center; padding: 0; }
  .ptui-modal-overlay[data-placement="responsive"] .ptui-modal {
    max-width: none; width: 100%; border-bottom: 0; max-height: 88dvh;
    border-radius: var(--ptui-radius-xl) var(--ptui-radius-xl) 0 0;
    animation: ptui-sheet-up var(--ptui-duration-slow) var(--ptui-ease-decelerate);
  }
  .ptui-modal-overlay[data-placement="responsive"] .ptui-modal::before {
    content: ""; width: 100px; height: 5px; margin: 10px auto 0; flex: 0 0 auto;
    border-radius: 999px; background: var(--ptui-border-strong);
  }
  /* drawer tren mobile: chiem gan het be ngang, chua 24px de thay trang nen */
  .ptui-modal-overlay[data-placement="drawer-right"] .ptui-modal,
  .ptui-modal-overlay[data-placement="drawer-left"] .ptui-modal { width: calc(100vw - 24px); }
}

/* ==== v0.14 — NGON NGU 2D (DIEU CHINH thu vien) ===========================
   User chot: nut phang 2D kieu Microsoft 365 / Google, nut primary trung tinh.

   Khoi nay GHI DE components.css. Dat duoc vi extras.css nam SAU components.css
   trong dist/styles.css => cung specificity, rule sau thang. KHONG dung !important,
   KHONG sua components.css (giu md5 trung sample ver6).

   CAN CU (source that, khong phai cam tinh):
   - Fluent 2: grep gradient tren button/card/dialog = 0/0/0. Nut KHONG co shadow
     o rest/hover/pressed. transitionProperty chi 'background, border, color'.
   - Material 3: filled/tonal/outlined/text deu elevation level0 o rest. 0 gradient.
   - Radix Themes: gom DUNG 4 thu phap 3D (gradient 2 diem dung, inset highlight
     mep tren, bong inset mep duoi, dich chuyen khi nhan) vao mot variant va dat
     ten `classic` — tuc chinh Radix goi do la "kieu cu".
   - 7/7 he khao sat: KHONG he nao dung translateY tren nut.
   ========================================================================== */

/* --- (1) NUT NEN-TRANG: bo gradient, bo shadow noi khoi, bo translateY ---- */
.ptui-btn {
  background: var(--ptui-surface);
  border-color: var(--ptui-btn-border);
  box-shadow: var(--ptui-shadow-control);
  transition: var(--ptui-btn-transition);
}
.ptui-btn:hover {
  background: var(--ptui-surface-hover);
  border-color: var(--ptui-btn-border-hover);
  box-shadow: var(--ptui-shadow-control);
  filter: none; /* bo brightness — gia lap anh sang chieu vao khoi */
}
.ptui-btn:active {
  background: var(--ptui-bg-muted);
  transform: none; /* bo translateY(1px) — nut khong lun xuong nua */
  filter: none;
  box-shadow: var(--ptui-shadow-control);
}
.ptui-btn:disabled {
  opacity: var(--ptui-state-disabled-content);
  box-shadow: none;
}

/* --- (2) NUT PRIMARY: trung tinh, 1 mau dac, 0 shadow --------------------
   Radix/Geist/shadcn deu cho nut solid 0 shadow — bong chi danh cho nut nen-trang
   de tach no khoi nen trang cua trang. Nut dac da tu tach bang chinh mau cua no. */
.ptui-btn-primary {
  background: var(--ptui-btn-primary-bg);
  border-color: transparent; /* GIU 1px transparent: doi variant khong nhay layout */
  color: var(--ptui-btn-primary-fg);
  box-shadow: none;
}
.ptui-btn-primary:hover {
  background: var(--ptui-btn-primary-bg-hover);
  border-color: transparent;
  box-shadow: none;
}
.ptui-btn-primary:active {
  background: var(--ptui-btn-primary-bg-active);
  border-color: transparent;
  box-shadow: none;
}

/* --- (3) NUT DANGER: bo gradient hardcode, ve token ----------------------
   components.css:307 hardcode `linear-gradient(180deg,#ef4444,#dc2626)` nen dot
   0.5.0 nang semantic len thang -700 da khong cham toi no. Nay di qua token. */
.ptui-btn-danger {
  background: var(--ptui-btn-danger-bg);
  border-color: transparent;
  color: var(--ptui-btn-danger-fg);
  box-shadow: none;
}
.ptui-btn-danger:hover { background: var(--ptui-btn-danger-bg-hover); border-color: transparent; box-shadow: none; }
.ptui-btn-danger:active { background: var(--ptui-btn-danger-bg-active); border-color: transparent; box-shadow: none; }

/* --- (4) NUT OUTLINE: bo gradient, nen trong suot ------------------------
   Radix `outline` = vien mau cung tone + nen trong suot; hover moi len nen nhat. */
.ptui-btn-outline {
  background: transparent;
  border-color: color-mix(in srgb, var(--ptui-accent) 42%, var(--ptui-border));
  color: var(--ptui-accent);
  box-shadow: none;
}
.ptui-btn-outline:hover {
  background: var(--ptui-accent-soft);
  border-color: var(--ptui-accent);
  box-shadow: none;
}
.ptui-btn-outline:active {
  background: var(--ptui-accent-soft-hover);
  box-shadow: none;
}

/* --- (5) ICONBTN: dong bo voi .ptui-btn + bo sung 2 state con thieu ------ */
.ptui-iconbtn {
  background: var(--ptui-surface);
  border-color: var(--ptui-btn-border);
  border-radius: var(--ptui-radius);
  box-shadow: var(--ptui-shadow-control);
  transition: var(--ptui-btn-transition);
}
.ptui-iconbtn:hover {
  background: var(--ptui-surface-hover);
  border-color: var(--ptui-btn-border-hover);
  box-shadow: var(--ptui-shadow-control);
  filter: none;
}
.ptui-iconbtn:active { background: var(--ptui-bg-muted); transform: none; box-shadow: var(--ptui-shadow-control); }
/* Truoc 0.14 iconbtn KHONG co focus-visible va disabled — loi a11y that. */
.ptui-iconbtn:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; }
.ptui-iconbtn:disabled { opacity: var(--ptui-state-disabled-content); cursor: not-allowed; box-shadow: none; }

/* --- (6) ACTIONBTN: bo translateY (phan con lai da 2D san) --------------- */
.ptui-actionbtn:active { transform: none; background: var(--ptui-act-soft); }

/* --- (7) AI BUTTON: giu chu ky gradient thuong hieu, bo phan 3D ----------
   Gradient 135deg NHIEU HUE la chu ky nhan dien (luat he: nut chay AI dung
   .ptui-ai-btn), KHONG phai bevel — bevel la sang→toi CUNG mot hue gia lap nguon
   sang. Nen giu gradient, chi bo: glow tim offset Y=22px, translateY, brightness. */
.ptui-ai-btn {
  border-color: transparent;
  box-shadow: none;
  transition: var(--ptui-btn-transition), opacity 120ms var(--ptui-ease-standard);
}
.ptui-ai-btn:hover { filter: none; box-shadow: none; opacity: 0.92; }
.ptui-ai-btn:active { transform: none; box-shadow: none; opacity: 0.86; }
.ptui-ai-btn-soft { box-shadow: none; }

/* --- (8) PROGRESS: bo ranh lom + bo highlight bong kinh ------------------ */
.ptui-progress-track { box-shadow: none; background: var(--ptui-bg-muted); }
.ptui-progress-fill { background: var(--ptui-prog-tone); box-shadow: none; }

/* --- (9) KANBAN: bo bevel (highlight trang mep tren + lom mep duoi) ------
   Khong the sua tokens/kanban.css (dang trung md5 sample) nen ghi de o day. */
.ptui-kb-board { background: var(--ptui-bg-subtle); box-shadow: none; }
.ptui-kb-col { background: var(--ptui-surface); box-shadow: none; }
.ptui-kb-colHead { background: transparent; }
.ptui-kb-card { background: var(--ptui-surface); box-shadow: var(--ptui-shadow-control); }
.ptui-kb-card:hover { transform: none; box-shadow: var(--ptui-shadow-sm); border-color: var(--ptui-border-strong); }

/* --- (10) METRIC CARD: bo glow goc + gradient nen ------------------------ */
.ptui-metric { background: var(--ptui-surface); box-shadow: var(--ptui-shadow-control); }

/* --- (11) WORKFLOW NODE: bo nhac len khi hover -------------------------- */
.ptui-wf-node:hover { transform: none; box-shadow: var(--ptui-shadow-sm); }

/* --- (12) THANG O CHUA ICON — gom 10 co che ve 3 bac --------------------
   Truoc: 9 kich thuoc x 6 radius cho cung mot khai niem (52 va 54 cach nhau 2px).
   Nay: 1 quy tac hinh — bo goc theo --ptui-radius, nen la mau tone o alpha thap,
   KHONG vien, KHONG shadow. Ba bac sm/md/lg. */
.ptui-icon-box,
.ptui-featured-icon,
.ptui-empty-icon,
.ptui-uploader-icon,
.ptui-confirm-ico,
.ptui-banner-icon,
.ptui-toast-ico,
.ptui-alert-icon {
  border-radius: var(--ptui-radius);
  border: 0;
  box-shadow: none;
}
.ptui-featured-icon { width: var(--ptui-icon-box-md); height: var(--ptui-icon-box-md); }
.ptui-featured-icon--sm { width: var(--ptui-icon-box-sm); height: var(--ptui-icon-box-sm); }
.ptui-featured-icon--lg { width: var(--ptui-icon-box-lg); height: var(--ptui-icon-box-lg); border-radius: var(--ptui-radius-lg); }
.ptui-confirm-ico { width: var(--ptui-icon-box-md); height: var(--ptui-icon-box-md); }
.ptui-uploader-icon { width: var(--ptui-icon-box-md); height: var(--ptui-icon-box-md); background: var(--ptui-accent-soft); color: var(--ptui-accent); }
.ptui-toast-ico { width: var(--ptui-icon-box-sm); height: var(--ptui-icon-box-sm); }
.ptui-banner-icon { width: var(--ptui-icon-box-sm); height: var(--ptui-icon-box-sm); }
/* Alert inline giu o nho 24px (nam trong dong chu) nhung ve cung 1 quy tac hinh */
.ptui-alert-icon { width: 24px; height: 24px; border-radius: var(--ptui-radius-sm); }
.ptui-alert--featured .ptui-alert-icon { width: var(--ptui-icon-box-md); height: var(--ptui-icon-box-md); border-radius: var(--ptui-radius); }

/* --- (13) EMPTYSTATE: dung lai ----------------------------------------
   Truoc: icon la ky tu `◇`, o 54px lac thang, 2 nut TU CHE khong hover/focus/
   disabled, va class .ptui-empty-secondary KHONG he co dinh nghia CSS. */
.ptui-empty { gap: 0; padding: 48px 24px; }
.ptui-empty-icon {
  width: var(--ptui-icon-box-lg); height: var(--ptui-icon-box-lg);
  background: var(--ptui-bg-muted); color: var(--ptui-text-muted);
  border-radius: var(--ptui-radius-lg);
  font-size: 0; /* khong con nuoi ky tu text */
}
.ptui-empty h3 { margin-top: 16px; font-size: var(--ptui-text-lg); font-weight: var(--ptui-weight-medium); }
.ptui-empty p { margin-top: 6px; max-width: 42ch; color: var(--ptui-text-secondary); font-size: var(--ptui-text-base); line-height: 1.6; }
.ptui-empty-actions { margin-top: 20px; gap: 10px; }
/* Hai nut nay gio COMPOSE .ptui-btn trong JSX; rule cu chi con lam fallback cho
   call-site truyen nut tu do vao. */
.ptui-empty-actions button:not(.ptui-btn) { min-height: var(--ptui-control-height); }

/* --- (14) PILL TABS: dua ve namespace ptui-, giu ten cu lam alias --------
   .pill-tab la cho DUY NHAT trong library ro ri class ra global namespace.
   Doi sang .ptui-pill-tab; ten cu VAN CHAY (alias) nen app dang dung khong vo —
   migrate dan, se go alias o mot ban major sau. */
.ptui-pill-tabs { display: flex; flex-wrap: wrap; gap: 10px; }
.ptui-pill-tab { box-shadow: none; }
.pill-tab.is-active, .ptui-pill-tab.is-active { box-shadow: none; }

/* --- (15) INPUT: bo sung state con thieu ------------------------------- */
.ptui-input { box-shadow: none; }
.ptui-input:focus { box-shadow: 0 0 0 3px var(--ptui-accent-ring); }
.ptui-input:disabled,
.ptui-input[aria-disabled="true"] {
  background: var(--ptui-bg-subtle);
  color: var(--ptui-text-muted);
  cursor: not-allowed;
}
.ptui-input[aria-invalid="true"] { border-color: var(--ptui-danger); }
.ptui-input[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ptui-danger) 22%, transparent); }

/* --- (16) 17 NUT TU CHE -> muon dung dien mao he thong ------------------
   Chung khong compose .ptui-btn duoc (nam trong component khac nhau), nen ta cho
   chung DUNG CHUNG cong thuc. Quan trong nhat: 4 cai truoc day THIEU focus-visible
   (empty, slideout, carousel, calendar) — do la loi a11y that, khong phai tham my. */
.ptui-empty-actions button:not(.ptui-btn),
.ptui-slideout header > button:not(.ptui-btn),
.ptui-carousel-controls button:not(.ptui-btn),
.ptui-calendar-icon,
.ptui-calendar-today,
.ptui-calendar-view,
.ptui-date-picker-control > button:not(.ptui-btn),
.ptui-pagination button:not(.ptui-btn),
.ptui-social-button,
.ptui-wf-zoom button:not(.ptui-btn) {
  background: var(--ptui-surface);
  border: 1px solid var(--ptui-btn-border);
  box-shadow: none;
  transition: var(--ptui-btn-transition);
}
.ptui-empty-actions button:not(.ptui-btn):hover,
.ptui-slideout header > button:not(.ptui-btn):hover,
.ptui-carousel-controls button:not(.ptui-btn):hover,
.ptui-calendar-icon:hover,
.ptui-calendar-today:hover,
.ptui-calendar-view:hover,
.ptui-date-picker-control > button:not(.ptui-btn):hover,
.ptui-pagination button:not(.ptui-btn):hover,
.ptui-social-button:hover,
.ptui-wf-zoom button:not(.ptui-btn):hover {
  background: var(--ptui-surface-hover);
  border-color: var(--ptui-btn-border-hover);
}
.ptui-empty-actions button:not(.ptui-btn):focus-visible,
.ptui-slideout header > button:not(.ptui-btn):focus-visible,
.ptui-carousel-controls button:not(.ptui-btn):focus-visible,
.ptui-calendar-icon:focus-visible,
.ptui-calendar-today:focus-visible,
.ptui-calendar-view:focus-visible,
.ptui-date-picker-control > button:not(.ptui-btn):focus-visible,
.ptui-pagination button:not(.ptui-btn):focus-visible,
.ptui-social-button:focus-visible,
.ptui-tag > button:focus-visible,
.ptui-step > button:focus-visible,
.ptui-wf-zoom button:not(.ptui-btn):focus-visible {
  outline: 2px solid var(--ptui-accent-ring);
  outline-offset: 2px;
}
.ptui-empty-actions button:not(.ptui-btn):disabled,
.ptui-carousel-controls button:not(.ptui-btn):disabled,
.ptui-pagination button:not(.ptui-btn):disabled,
.ptui-wf-zoom button:not(.ptui-btn):disabled {
  opacity: var(--ptui-state-disabled-content);
  cursor: not-allowed;
}
/* Nut chinh cua EmptyState di theo nut primary trung tinh cua he */
.ptui-empty-actions .ptui-empty-primary {
  background: var(--ptui-btn-primary-bg);
  border-color: transparent;
  color: var(--ptui-btn-primary-fg);
}
.ptui-empty-actions .ptui-empty-primary:hover { background: var(--ptui-btn-primary-bg-hover); border-color: transparent; }

/* --- (17) BE MAT: shadow phang hon o panel/table/modal ------------------ */
.ptui-panel { box-shadow: var(--ptui-shadow-control); }
.ptui-table-wrap { box-shadow: var(--ptui-shadow-control); }
.ptui-social-button { box-shadow: none; }
.ptui-toggle span { box-shadow: var(--ptui-shadow-control); }

@media (prefers-reduced-motion: reduce) {
  .ptui-btn, .ptui-iconbtn, .ptui-actionbtn, .ptui-ai-btn { transition: none; }
}

/* --- (18) WORKFLOW NODE HEADER: gradient cuoi cung ngoai texture co chu y ---
   `.ptui-wf-canvas` giu radial-gradient cham bi (texture DUY NHAT duoc phep theo
   luat he). `.ptui-wf-head` thi lam phang cho nhat quan. */
.ptui-wf-head { background: var(--ptui-bg-subtle); }

/* --- (19) 0.14 — glyph text da thay bang SVG -----------------------------
   Truoc 0.14 con 10 cho ve icon bang KY TU: Calendar `‹ › ▦`, Pagination `‹ ›`,
   ProgressSteps `✓`, MultiSelect `⌄ ✓`, Tag `×`, Slideout `×`, EmptyState `◇`,
   va logo Apple la CHU CAI "A". Ky tu do font he thong ve nen net khong bao gio
   can duoc voi icon stroke 2px cua bo <Icon>.
   Bo <Icon> chi co "chevron" tro XUONG — xoay bang CSS de ra trai/phai, khong
   ve them glyph moi. */
.ptui-ico-rot90 > svg { transform: rotate(90deg); }
.ptui-ico-rot270 > svg { transform: rotate(-90deg); }
.ptui-store-mark { display: inline-grid; place-content: center; }

/* ==== v0.14 — ICON TONE + MOTION (DIEU CHINH thu vien) ===================
   Hai nhom: (A) icon co mau theo NGU NGHIA, (B) chuyen dong co ten.
   ========================================================================= */

/* --- (20) ICON TONE ------------------------------------------------------
   LUAT (co can cu, khong phai cam tinh):
   · Microsoft Learn ghi ro "The dominant color for Excel is green, Word is blue,
     PowerPoint is orange" — tuc mau la MA NHAN DANG app.
   · Jensen Harris (Microsoft, 2006): nguoi dung "have a strong expectation to
     click a green icon for Excel" — mau uu tien PHAN BIET hon dong bo thuong hieu.
   · NHUNG: vi sao "bang tinh = xanh la" thi KHONG he nao tai lieu hoa. Do la
     folklore. Nen ta KHONG bia y nghia mau cho tung icon nghiep vu.
   · Icon GIAO DIEN cua ca Google (Material Symbols) lan Microsoft (Fluent) deu
     MONOCHROME. Mau chi danh cho logo SAN PHAM.

   => QUY TAC CUA HE:
   1. Icon MAC DINH trung tinh, ke thua `currentColor`. Day van la duong mac dinh.
   2. Chi to mau khi icon mang Y NGHIA TRANG THAI (thanh cong / canh bao / loi /
      thong tin / dang chay). KHONG to mau de trang tri.
   3. Mau lay tu 10 tone `--ptui-st-*` da co — 0 hex moi, tu flip dark.
   4. WCAG 1.4.1: mau KHONG duoc la tin hieu duy nhat. Icon mau luon di kem chu
      hoac hinh dang khac biet. Doc mau ma khong doc duoc nghia = thiet ke sai. */
.ptui-ico-tone-all { color: var(--ptui-st-all-fg); }
.ptui-ico-tone-gray { color: var(--ptui-st-gray-fg); }
.ptui-ico-tone-blue { color: var(--ptui-st-blue-fg); }
.ptui-ico-tone-amber { color: var(--ptui-st-amber-fg); }
.ptui-ico-tone-purple { color: var(--ptui-st-purple-fg); }
.ptui-ico-tone-teal { color: var(--ptui-st-teal-fg); }
.ptui-ico-tone-green { color: var(--ptui-st-green-fg); }
.ptui-ico-tone-red { color: var(--ptui-st-red-fg); }
.ptui-ico-tone-orange { color: var(--ptui-st-orange-fg); }
.ptui-ico-tone-cyan { color: var(--ptui-st-cyan-fg); }

/* Bien the "co nen" — icon nam trong o mau nhat. Dung khi icon dung mot minh va
   can duoc nhan manh (vd o dau mot hang danh sach), khong dung tran lan. */
.ptui-ico-soft {
  padding: 6px;
  border-radius: var(--ptui-radius-sm);
  background: var(--ptui-bg-muted);
}
.ptui-ico-soft.ptui-ico-tone-all { background: var(--ptui-st-all-bg); }
.ptui-ico-soft.ptui-ico-tone-gray { background: var(--ptui-st-gray-bg); }
.ptui-ico-soft.ptui-ico-tone-blue { background: var(--ptui-st-blue-bg); }
.ptui-ico-soft.ptui-ico-tone-amber { background: var(--ptui-st-amber-bg); }
.ptui-ico-soft.ptui-ico-tone-purple { background: var(--ptui-st-purple-bg); }
.ptui-ico-soft.ptui-ico-tone-teal { background: var(--ptui-st-teal-bg); }
.ptui-ico-soft.ptui-ico-tone-green { background: var(--ptui-st-green-bg); }
.ptui-ico-soft.ptui-ico-tone-red { background: var(--ptui-st-red-bg); }
.ptui-ico-soft.ptui-ico-tone-orange { background: var(--ptui-st-orange-bg); }
.ptui-ico-soft.ptui-ico-tone-cyan { background: var(--ptui-st-cyan-bg); }

/* --- (21) LAC CANH BAO ---------------------------------------------------
   Dung khi nguoi dung bam xac nhan ma dieu kien chua dat, hoac submit form loi.

   SO LIEU CO NGUON (khong phai tu dat):
   · duration 360ms + easing cubic-bezier(0.36,0.07,0.19,0.97) + bien do dinh 8px
     — Animation Patterns "CSS Error Shake Feedback".
   · Cau truc DAMPING (bien do giam dan 8→5→2) lay tu Animate.css `headShake`.
     Ban `shakeX` cua Animate.css giu nguyen +-10px KHONG giam dan — doc thanh
     "rung lien tuc" chu khong phai "lac roi dung", nen ta KHONG dung kieu do.
   · macOS shake mat khau sai: 4 nhip / 0.5s, bien do 5% be rong (~20px voi cua so
     400px). Qua manh cho mot dialog web => ta giu 8px.

   CHAY DUNG MOT LAN, khong loop. Loop se doc thanh "giao dien bi giat".

   A11Y:
   · WCAG 2.3.1 (nhay >3 lan/giay): KHONG cham — day la dich chuyen vi tri, khong
     phai "cap thay doi doi lap ve do choi" (flash).
   · WCAG 2.2.2 (motion tu chay >5s): KHONG cham — do user kich hoat, 360ms.
   · WCAG 2.3.3 (AAA, motion tu tuong tac): CO CHAM. Lac KHONG phai essential —
     loi da truyen duoc bang mau + chu + aria. Nen BAT BUOC co reduced-motion.
   · Va lac khong duoc la tin hieu duy nhat: luon di kem thong bao chu + aria-invalid. */
@keyframes ptui-shake {
  0%, 100% { transform: translate3d(0, 0, 0); }
  15% { transform: translate3d(-8px, 0, 0); }
  30% { transform: translate3d(8px, 0, 0); }
  45% { transform: translate3d(-5px, 0, 0); }
  60% { transform: translate3d(5px, 0, 0); }
  75% { transform: translate3d(-2px, 0, 0); }
  90% { transform: translate3d(2px, 0, 0); }
}
.ptui-shake,
.ptui-modal.is-shaking {
  animation: ptui-shake var(--ptui-motion-shake) var(--ptui-ease-shake) 1 both;
}

/* --- (22) AGENT "DANG SUY NGHI" — 3 cham chay song --------------------
   SO LIEU CO NGUON: SpinKit "three-bounce" — duration 1.4s, easing ease-in-out,
   delay lech -0.32s / -0.16s / 0s. Ba cham vi the doc thanh MOT lan song chay tu
   trai sang phai, thay vi ba cham nhap nhay roi rac.
   Bien do -4px la lua chon cua ta (SpinKit goc dung scale, khong dung translateY);
   translateY doc ro hon trong mot dong chu. */
@keyframes ptui-think-dot {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30% { transform: translateY(-4px); opacity: 1; }
}
.ptui-thinking { display: inline-flex; align-items: center; gap: 4px; }
.ptui-thinking i {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; display: block;
  animation: ptui-think-dot var(--ptui-motion-think) var(--ptui-ease-standard) infinite;
}
.ptui-thinking i:nth-child(2) { animation-delay: var(--ptui-motion-think-stagger); }
.ptui-thinking i:nth-child(3) { animation-delay: calc(var(--ptui-motion-think-stagger) * 2); }

/* --- (23) BAT CHU Y — chay MOT lan, khong lap -------------------------
   Dung cho: hang bang vua duoc them/sua, badge dem vua tang. Khac hoan toan voi
   cac animation `infinite` o tren — cai nay ket thuc, nen khong lam phien. */
@keyframes ptui-attention {
  0% { background-color: var(--ptui-accent-soft); }
  100% { background-color: transparent; }
}
.ptui-attention { animation: ptui-attention var(--ptui-motion-attention) var(--ptui-ease-accelerate); }
@keyframes ptui-pop-in {
  0% { transform: scale(0.7); opacity: 0; }
  70% { transform: scale(1.08); }
  100% { transform: scale(1); opacity: 1; }
}
.ptui-pop-in { animation: ptui-pop-in var(--ptui-motion-attention) var(--ptui-ease-decelerate); }

/* --- (24) SUA LOI reduced-motion cua 0.13 + xu ly dung cach ------------
   BUG THAT DA SUA: block reduced-motion cua 0.13 viet `.ptui-modal { animation: none }`
   — specificity (0,1,0). Nhung rule animation cua placement la
   `.ptui-modal-overlay[data-placement="bottom"] .ptui-modal` — (0,3,0) — nen no
   THANG, drawer/bottom-sheet VAN truot khi user bat "giam chuyen dong".
   Test cu chi kiem "selector co MAT trong block" nen bao xanh: no khang dinh su
   HIEN DIEN cua dong CSS, khong khang dinh rule CO THANG hay khong.
   Kem theo `ptui-wf-pulse` (node dang chay, nhap nhay VO HAN) bi sot han.

   VI SAO DUNG `0.01ms` MA KHONG DUNG `none`:
   `animation: none` lam su kien `animationend` KHONG BAO GIO ban => code nao doi
   su kien do de don dep (vd go class .is-shaking) se ket lai vinh vien.
   Animate.css chon 1ms, A11Y Project khuyen 0.001s, vi cung ly do.

   VA KHONG PHAI CAI GI CUNG TAT: web.dev noi "minimize NON-ESSENTIAL motion".
   Cham "dang suy nghi" la tin hieu he thong dang ban — tat han thi nguoi dung
   tuong treo. Theo vi du chinh thuc cua MDN (thay `pulse` bang `dissolve`), ta
   DOI KENH: bo dich chuyen, giu nhap nhay do mo. */
@media (prefers-reduced-motion: reduce) {
  .ptui-modal-overlay[data-placement] .ptui-modal,
  .ptui-modal-overlay[data-placement] .ptui-modal::before { animation-duration: 0.01ms; }
  .ptui-wf-node--running::after { animation-duration: 0.01ms; }
  .ptui-dt-pop { animation-duration: 0.01ms; }
  .ptui-shake, .ptui-modal.is-shaking,
  .ptui-attention, .ptui-pop-in { animation-duration: 0.01ms; }
  /* Tin hieu essential — GIU, chi doi tu dich chuyen sang do mo */
  .ptui-thinking i {
    animation: ptui-think-fade var(--ptui-motion-think) ease-in-out infinite both;
  }
}
@keyframes ptui-think-fade {
  0%, 80%, 100% { opacity: 0.3; }
  40% { opacity: 1; }
}

/* ==== v0.14b — ANATOMY + 3 DIALOG MOI (DIEU CHINH thu vien) ==============
   Bo sung phan con thieu cua dot 2D: 3 dialog moi, anatomy 4 component, va dua
   .pill-tab ve dung namespace.
   ========================================================================= */

/* --- (25) CHOICE DIALOG — chon 1 trong N -------------------------------
   Dung `radiogroup` that, khong phai menu gia. Nho vay phim mui ten dieu huong
   duoc ngay ma khong phai viet mot dong JS nao. */
.ptui-choice { display: grid; gap: 8px; margin-top: 14px; }
.ptui-choice-item {
  display: grid; grid-template-columns: auto 1fr; align-items: start; gap: 10px;
  padding: 12px 14px; cursor: pointer;
  border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius);
  background: var(--ptui-surface);
  transition: var(--ptui-btn-transition);
}
.ptui-choice-item:hover { background: var(--ptui-surface-hover); border-color: var(--ptui-btn-border-hover); }
.ptui-choice-item.is-selected { border-color: var(--ptui-accent); background: var(--ptui-accent-soft); }
/* Radio that van ton tai va van nhan focus — chi giau khoi mat, KHONG dung
   display:none (se mat khoi tab order va mat dieu huong mui ten). */
.ptui-choice-item input {
  position: absolute; width: 1px; height: 1px; opacity: 0;
  margin: 0; pointer-events: none;
}
.ptui-choice-mark {
  width: 18px; height: 18px; margin-top: 1px; flex: 0 0 auto;
  border: 2px solid var(--ptui-border-strong); border-radius: 50%;
  display: grid; place-content: center;
  transition: var(--ptui-btn-transition);
}
.ptui-choice-mark::after {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ptui-accent); transform: scale(0);
  transition: transform var(--ptui-duration-fast) var(--ptui-ease-decelerate);
}
.ptui-choice-item.is-selected .ptui-choice-mark { border-color: var(--ptui-accent); }
.ptui-choice-item.is-selected .ptui-choice-mark::after { transform: scale(1); }
/* Focus ring nam tren CA HANG, khong chi tren cham tron — vung bam la ca hang. */
.ptui-choice-item:has(input:focus-visible) { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; }
.ptui-choice-item:has(input:disabled) { opacity: var(--ptui-state-disabled-content); cursor: not-allowed; }
.ptui-choice-copy { display: grid; gap: 2px; min-width: 0; }
.ptui-choice-copy strong { font-size: var(--ptui-text-base); font-weight: var(--ptui-weight-medium); }
.ptui-choice-copy small { font-size: var(--ptui-text-md); line-height: 1.5; color: var(--ptui-text-secondary); }

/* --- (26) INPUT: prefix/suffix ---------------------------------------- */
.ptui-input-wrap {
  display: flex; align-items: center; gap: 0;
  border: 1px solid var(--ptui-border); border-radius: var(--ptui-radius);
  background: var(--ptui-surface);
  transition: border-color var(--ptui-duration-fast) var(--ptui-ease-standard),
    box-shadow var(--ptui-duration-fast) var(--ptui-ease-standard);
}
.ptui-input-wrap:focus-within { border-color: var(--ptui-border-focus); box-shadow: 0 0 0 3px var(--ptui-accent-ring); }
/* O nhap ben trong bo het vien/bong cua chinh no — vien da chuyen len wrapper,
   neu khong se thanh HAI vien long nhau. */
.ptui-input-wrap .ptui-input { border: 0; box-shadow: none; background: transparent; }
.ptui-input-wrap .ptui-input:focus { box-shadow: none; }
.ptui-input-affix {
  display: grid; place-content: center; flex: 0 0 auto;
  padding: 0 12px; height: var(--ptui-control-height);
  color: var(--ptui-text-muted); font-size: var(--ptui-text-md); white-space: nowrap;
}
.ptui-input-affix:first-child { padding-right: 0; }
.ptui-input-affix:last-child { padding-left: 0; }

/* --- (27) PANEL: header / body / footer -------------------------------- */
.ptui-panel-head {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 16px 18px; border-bottom: 1px solid var(--ptui-border);
}
.ptui-panel-titles { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }
.ptui-panel-title { margin: 0; font-size: var(--ptui-text-lg); font-weight: var(--ptui-weight-medium); letter-spacing: -0.01em; }
.ptui-panel-sub { margin: 0; font-size: var(--ptui-text-md); line-height: 1.55; color: var(--ptui-text-secondary); }
.ptui-panel-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.ptui-panel-body { padding: 18px; }
.ptui-panel-body.is-flush { padding: 0; }
.ptui-panel-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 14px 18px; border-top: 1px solid var(--ptui-border);
  background: var(--ptui-bg-subtle);
}

/* --- (28) BADGE: size + icon + removable ------------------------------- */
.ptui-badge-sm { height: 20px; padding: 0 8px; font-size: var(--ptui-text-xs); }
.ptui-badge-lg { height: 28px; padding: 0 12px; font-size: var(--ptui-text-md); }
.ptui-badge-ico { display: grid; place-content: center; margin-left: -2px; }
.ptui-badge-x {
  display: grid; place-content: center; margin-right: -4px; margin-left: 2px;
  width: 18px; height: 18px; padding: 0;
  border: 0; border-radius: 50%; background: transparent;
  color: currentColor; cursor: pointer; opacity: 0.65;
  transition: opacity var(--ptui-duration-fast) var(--ptui-ease-standard);
}
.ptui-badge-x:hover { opacity: 1; background: color-mix(in srgb, currentColor 16%, transparent); }
.ptui-badge-x:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 1px; opacity: 1; }

/* --- (29) ICONBUTTON: size ------------------------------------------- */
.ptui-iconbtn-sm { width: 34px; height: 34px; }
.ptui-iconbtn-lg { width: var(--ptui-control-height); height: var(--ptui-control-height); }
/* Nut BAT/TAT ben vung — khac han :active (chi la dang nhan chuot). */
.ptui-iconbtn[aria-pressed="true"] {
  background: var(--ptui-accent-soft);
  border-color: var(--ptui-accent);
  color: var(--ptui-accent);
}

/* --- (30) PILL TABS: dua ve namespace ptui-, giu ten cu lam alias -------
   `.pill-tab` la cho DUY NHAT trong library ro ri class ra global namespace —
   mot app dat `.pill-tab` cua rieng no la dung nhau ngay.
   Doi sang `.ptui-pill-tab`; ten cu VAN CHAY nen app dang dung khong vo, migrate
   dan roi go alias o mot ban major sau. Day la ly do doi nay KHONG breaking. */
.ptui-pill-tabs { display: flex; flex-wrap: wrap; gap: 10px; }
.ptui-pill-tab {
  --pill-tone: var(--ptui-accent);
  --pill-tone-fg: var(--ptui-accent);
  --pill-tone-bg: var(--ptui-accent-soft);
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 36px; padding: 0 14px;
  border: 1px solid var(--ptui-border); border-radius: 999px;
  background: var(--ptui-surface); color: var(--ptui-text-secondary);
  font: var(--ptui-weight-medium) var(--ptui-text-md)/1 var(--ptui-font-sans); cursor: pointer;
  transition: var(--ptui-btn-transition);
}
.ptui-pill-tab:hover { background: var(--ptui-surface-hover); border-color: var(--ptui-btn-border-hover); }
.ptui-pill-tab:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; }
.ptui-pill-tab.is-active {
  border-color: var(--pill-tone); background: var(--pill-tone-bg); color: var(--pill-tone-fg);
}
.ptui-pill-tab-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pill-tone); }
.ptui-pill-tab-count {
  min-width: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--ptui-bg-muted); color: var(--ptui-text-secondary);
  font-size: var(--ptui-text-xs); font-weight: var(--ptui-weight-bold); font-variant-numeric: tabular-nums;
}
.ptui-pill-tab.is-active .ptui-pill-tab-count { background: var(--pill-tone); color: var(--ptui-text-on-accent); }
/* Nhan cua pill tab. Truoc 0.14 `.pill-tab-label` duoc phat ra nhung KHONG he co
   dinh nghia — mot class mo coi. Thay vi mirror cai mo coi do sang namespace moi,
   cho no dung viec no can that: nhan dai phai cat bang ba cham chu khong duoc day
   vo hang pill. `min-width: 0` la bat buoc vi day la flex item — thieu no thi
   text-overflow khong bao gio an. */
.ptui-pill-tab-label, .pill-tab-label {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ptui-pill-tab--all { --pill-tone: var(--ptui-st-all); --pill-tone-fg: var(--ptui-st-all-fg); --pill-tone-bg: var(--ptui-st-all-bg); }
.ptui-pill-tab--gray { --pill-tone: var(--ptui-st-gray); --pill-tone-fg: var(--ptui-st-gray-fg); --pill-tone-bg: var(--ptui-st-gray-bg); }
.ptui-pill-tab--blue { --pill-tone: var(--ptui-st-blue); --pill-tone-fg: var(--ptui-st-blue-fg); --pill-tone-bg: var(--ptui-st-blue-bg); }
.ptui-pill-tab--amber { --pill-tone: var(--ptui-st-amber); --pill-tone-fg: var(--ptui-st-amber-fg); --pill-tone-bg: var(--ptui-st-amber-bg); }
.ptui-pill-tab--purple { --pill-tone: var(--ptui-st-purple); --pill-tone-fg: var(--ptui-st-purple-fg); --pill-tone-bg: var(--ptui-st-purple-bg); }
.ptui-pill-tab--teal { --pill-tone: var(--ptui-st-teal); --pill-tone-fg: var(--ptui-st-teal-fg); --pill-tone-bg: var(--ptui-st-teal-bg); }
.ptui-pill-tab--green { --pill-tone: var(--ptui-st-green); --pill-tone-fg: var(--ptui-st-green-fg); --pill-tone-bg: var(--ptui-st-green-bg); }
.ptui-pill-tab--red { --pill-tone: var(--ptui-st-red); --pill-tone-fg: var(--ptui-st-red-fg); --pill-tone-bg: var(--ptui-st-red-bg); }
.ptui-pill-tab--orange { --pill-tone: var(--ptui-st-orange); --pill-tone-fg: var(--ptui-st-orange-fg); --pill-tone-bg: var(--ptui-st-orange-bg); }
.ptui-pill-tab--cyan { --pill-tone: var(--ptui-st-cyan); --pill-tone-fg: var(--ptui-st-cyan-fg); --pill-tone-bg: var(--ptui-st-cyan-bg); }

@media (prefers-reduced-motion: reduce) {
  .ptui-choice-item, .ptui-choice-mark::after, .ptui-pill-tab,
  .ptui-input-wrap, .ptui-badge-x { transition-duration: 0.01ms; }
}

/* ==== v0.15 — THANG CHU (DIEU CHINH thu vien) =============================
   Dua CO CHU va DO DAM ve mot thang duy nhat (`tokens/typescale.css`).

   VI SAO CAN KHOI NAY: 40 luat duoi day nam trong `components.css` — file dang
   khoa hop dong verbatim voi sample ver6, khong duoc sua. Chung dat cac gia tri
   NGOAI thang (nua-pixel 10.5/11.5/12.5/13.5, va do dam tu che 650/750/800/850).
   Ghi de duoc vi `extras.css` nam SAU `components.css` trong `dist/styles.css`,
   cung specificity thi luat sau thang. KHONG dung `!important`.

   Sinh bang script (soi tung luat, doi sang bac gan nhat cua thang) roi doc lai
   bang tay — khong go tay 40 luat. Da kiem: **0 luat nao trong so nay nam trong
   `@media`**, nen ghi de o ngoai khong lam sai o bat ky breakpoint nao. Neu ban
   sample sau co them khai bao font trong media query thi PHAI kiem lai diem nay.

   Vai thay doi dien mao co y, khong phai tac dung phu:
   - `.ptui-modal-title` / `.ptui-confirm-title`: 17px/750 -> 16px/700. Van tach
     bac ro so voi chu than bai 14px.
   - `.ptui-sidebarBrand h1`: 18px/800 -> 20px/700.
   - Moi cho 650 -> 600 (132 luot). Inter la variable 100-900 nen ca hai deu la
     net that, khong phai net gia do trinh duyet boi dam.
   ========================================================================= */

.ptui-railLabel { font-size: var(--ptui-text-xs); }
.ptui-sidebarBrand h1 { font-size: var(--ptui-text-xl); font-weight: var(--ptui-weight-bold); }
.ptui-navItem { font-weight: var(--ptui-weight-medium); }
.ptui-btn { font-weight: var(--ptui-weight-medium); }
.ptui-metric-value { font-weight: var(--ptui-weight-bold); }
.ptui-metric-percent { font-weight: var(--ptui-weight-bold); }
.ptui-kb-colTitle { font-weight: var(--ptui-weight-bold); }
.ptui-kb-colCount { font-weight: var(--ptui-weight-bold); }
.ptui-kb-empty { font-size: var(--ptui-text-md); }
.ptui-kbc-desc { font-size: var(--ptui-text-md); }
.ptui-kbc-av { font-size: var(--ptui-text-xs); }
.ptui-kbc-creator { font-size: var(--ptui-text-sm); }
.ptui-kbc-creator b { font-weight: var(--ptui-weight-medium); }
.ptui-dt-pop input { font-size: var(--ptui-text-base); }
.ptui-badge { font-weight: var(--ptui-weight-medium); }
.ptui-modal-title { font-size: var(--ptui-text-lg); font-weight: var(--ptui-weight-bold); }
.ptui-confirm-title { font-size: var(--ptui-text-lg); font-weight: var(--ptui-weight-bold); }
.ptui-field-hint { font-size: var(--ptui-text-sm); }
.ptui-wf-kind { font-size: var(--ptui-text-xs); }
.ptui-wf-title { font-size: var(--ptui-text-base); }
.ptui-wf-badge { font-size: var(--ptui-text-xs); }
.ptui-wf-prompt { font-size: var(--ptui-text-md); }
.ptui-wf-prompt b { font-weight: var(--ptui-weight-medium); }
.ptui-wf-file { font-size: var(--ptui-text-md); }
.ptui-wf-file b { font-weight: var(--ptui-weight-medium); }
.ptui-wf-image { font-size: var(--ptui-text-md); }
.ptui-wf-image b { font-weight: var(--ptui-weight-medium); }
.ptui-wf-step-n { font-size: var(--ptui-text-xs); }
.ptui-wf-field b { font-weight: var(--ptui-weight-medium); }
.ptui-wf-foot { font-size: var(--ptui-text-sm); }
.ptui-check-title { font-weight: var(--ptui-weight-medium); }
.ptui-check-lg .ptui-check-title { font-size: var(--ptui-text-lg); }
.ptui-avatar { font-weight: var(--ptui-weight-medium); }
.ptui-btngroup-item { font-weight: var(--ptui-weight-medium); }
.ptui-btngroup-count { font-weight: var(--ptui-weight-medium); }
.ptui-crumb.ptui-active { font-weight: var(--ptui-weight-medium); }
.ptui-toast-title { font-weight: var(--ptui-weight-medium); }
.ptui-toast-act { font-weight: var(--ptui-weight-medium); }
.ptui-tree-item.ptui-active > .ptui-tree-row .ptui-tree-label { font-weight: var(--ptui-weight-medium); }
.ptui-tree-ext { font-size: var(--ptui-text-xs); }

.ptui-avatar { --ptui-avatar-fs: var(--ptui-text-base); --ptui-avatar-fs-more: var(--ptui-text-sm); }
.ptui-avatar-xs { --ptui-avatar-fs: var(--ptui-text-xs); --ptui-avatar-fs-more: var(--ptui-text-xs); }
.ptui-avatar-sm { --ptui-avatar-fs: var(--ptui-text-sm); --ptui-avatar-fs-more: var(--ptui-text-xs); }
.ptui-avatar-md { --ptui-avatar-fs: var(--ptui-text-base); --ptui-avatar-fs-more: var(--ptui-text-sm); }
.ptui-avatar-lg { --ptui-avatar-fs: var(--ptui-text-lg); --ptui-avatar-fs-more: var(--ptui-text-md); }
.ptui-avatar-xl { --ptui-avatar-fs: var(--ptui-text-xl); --ptui-avatar-fs-more: var(--ptui-text-base); }
.ptui-avatar-more { font-size: var(--ptui-avatar-fs-more); }
.ptui-tree { --ptui-tree-fs: var(--ptui-text-base); }
.ptui-tree-md { --ptui-tree-fs: var(--ptui-text-lg); }

/* `<strong>` mac dinh cua trinh duyet la `font-weight: bolder` — KHONG phai 700.
   `bolder` la gia tri TUONG DOI: theo bang quy doi cua CSS, cha 600-700 -> 900.
   Nut nay dat font-weight 600 nen chu "G" ben trong bi keo len 900, tao ra mot
   bac nam ngoai thang ma khong luat nao cua ta viet sai ca.
   Do duoc: day la phan tu DUY NHAT trong library dinh bay nay (quet 445 phan tu
   co chu, chi 1 phan tu ra 900), nen vá dung cho no thay vi viet mot luat quet
   `[class*="ptui-"] strong` — luat quet se de mat cac luat b/strong co chu dich
   o tren (vd `.ptui-kbc-creator b`) vi cung specificity ma nam sau. */
.ptui-social-button strong { font-weight: var(--ptui-weight-bold); }

/* ============================================================ v0.15b — A11Y NHAN LOAI NODE
   `.ptui-wf-kind` (10.5px/700 uppercase) lay mau CHU tu `--ptui-wf`, tuc tone GOC.
   Tone goc duoc thiet ke lam dot/border (nguong 3:1), khong phai lam chu (4.5:1):
   do tren nen `color-mix(--ptui-wf 9%, surface)` thi 8/14 o (7 node x 2 theme) duoi AA
   — vd condition light 2.00, workflow dark 3.93. Bien `-fg` cua cung tone la sac -700
   sinh ra dung cho viec nay: do lai duoc 7/7 PASS o ca hai theme (thap nhat 4.55).
   Fallback ve `--ptui-wf` de node do consumer tu dat `color` khong bi mat chu.
   Khoa bang tests/v015.test.mjs. Chi sua o extras.css — components.css giu verbatim. */
.ptui-wf-kind { color: var(--ptui-wf-fg, var(--ptui-wf)); }

/* ==== v0.17 — VÁCH NGĂN CHO MODAL (ĐIỀU CHỈNH thư viện) ===================
   Thư viện đang mang HAI giải phẫu khác nhau cho CÙNG một vai trò head/body/foot:

     đo bằng getComputedStyle, 01/09/2026
     ┌────────────────────┬──────────────┬──────────────┐
     │                    │ .ptui-modal  │ .ptui-panel  │
     ├────────────────────┼──────────────┼──────────────┤
     │ head border-bottom │     0px      │     1px      │
     │ foot border-top    │     0px      │     1px      │
     │ foot background    │ trong suốt   │  bg-subtle   │
     └────────────────────┴──────────────┴──────────────┘

   Panel có vách ngăn từ 0.14b; Modal port nguyên văn từ sample ver6 ở 0.1.0 và chưa ai
   hoà giải hai bên. Hậu quả nhìn thấy được: trong cùng một trang, Panel có cấu trúc rõ
   còn Dialog thì tiêu đề và nút bấm trôi lơ lửng — người dùng gọi đó là "nghiệp dư".
   Đây đúng là thứ mục 3 của Consistency Gate cấm: MỘT cơ chế cho MỘT loại control.

   Ba luật dưới đây đưa Modal về cùng cơ chế với Panel. GIỮ nhịp đệm rộng hơn của dialog
   (20px thay vì 18px) — dialog chiếm toàn màn hình nên cần thoáng hơn panel nội tuyến;
   cái phải thống nhất là CƠ CHẾ (có vách ngăn), không phải con số đệm.

   Ghi đè được vì extras.css nằm SAU components.css trong dist/styles.css. KHÔNG dùng
   !important, KHÔNG sửa components.css (hợp đồng verbatim với sample).
   ========================================================================== */
.ptui-modal-head {
  border-bottom: 1px solid var(--ptui-border);
}
/* Thân cần đệm trên: trước đây `padding: 0 20px 4px` nên chữ sẽ DÍNH vào vách ngăn mới. */
.ptui-modal-body {
  padding: 16px 20px;
}
.ptui-modal-foot {
  border-top: 1px solid var(--ptui-border);
  background: var(--ptui-bg-subtle);
  /* Vách ngăn thay vai trò của khoảng cách rời — giữ cả hai thì chân bị đẩy xuống hai lần. */
  margin-top: 0;
  padding: 14px 20px;
}
/* ConfirmDialog/Alert/Prompt/Choice không có head (icon + tiêu đề nằm trong body) nên chúng
   chỉ nhận vách CHÂN — đúng ý đồ: khối nội dung liền một mạch, hàng nút tách ra. */

/* ==== v0.17.1 — Ô CHỌN KHÔNG ĐƯỢC TRÀN RA KHỎI KHUNG CHỨA (sửa lỗi) =======
   `.ptui-select select` đang có `min-width: 180px` — một SÀN CỨNG. Component nào có sàn
   cứng thì nó **tràn ra khỏi mọi container hẹp hơn sàn đó**, và CSS không có cách nào can.

   Đo trên bản live 01/09/2026 (dialog "Giao quản lý nick", Peram Chat):
     track lưới dành cho ô chọn : 160px
     ô chọn thực tế             : 180px   ← tràn 20px
     lề phải còn lại            : 1px     (đúng ra phải là 20px)
   Ô chọn ăn trọn lề phải của thân dialog nên trông như bị cắt cụt ở mép.

   `min(180px, 100%)` giữ nguyên hành vi cũ khi còn chỗ (container ≥ 180px → vẫn 180px),
   nhưng khi container hẹp hơn thì sàn tụt theo container → KHÔNG BAO GIỜ tràn được nữa.
   Đây là sửa ở tầng thư viện nên mọi app cùng khỏi, không phải vá riêng một dialog.

   Cùng loại với bẫy đã ghi trong skill: `.ptui-input` có `width: 100%` không được gắn
   thẳng vào chỗ cần co theo nội dung. Bài học chung: control dùng chung KHÔNG được đặt
   kích thước tuyệt đối mà container không thể ghi đè.
   ========================================================================== */
.ptui-select select { min-width: min(180px, 100%); }

/* ==== v0.17.2 — QUÉT TOÀN THƯ VIỆN: KHÔNG CONTROL NÀO ĐƯỢC CÓ SÀN CỨNG ====
   0.17.1 sửa `.ptui-select select`. Quét cả thư viện thì thấy nó KHÔNG đơn độc — có
   **6** chỗ đặt `min-width` bằng px tuyệt đối ≥ 60px. Sàn cứng = component tràn ra khỏi
   mọi khung chứa hẹp hơn nó, và khung chứa không có cách nào can.

   Nhưng KHÔNG gộp chung một cách sửa — hai loại phải xử lý khác nhau:

   (A) Control NẰM TRONG LUỒNG (khung chứa quyết định bề rộng) → `min(Npx, 100%)`:
       giữ nguyên bề rộng thiết kế khi còn chỗ, tụt theo khung chứa khi chật.
         .ptui-select select   180px  (đã sửa ở 0.17.1)
         .ptui-multiselect     230px  ← rủi ro cao nhất, nằm trong form/lưới
         .ptui-store-button    168px
         .ptui-calendar-title  150px

   (B) Lớp NỔI `position: absolute` (menu, popover) → **KHÔNG** dùng `min(…, 100%)`:
       `100%` của chúng tính theo khối chứa định vị, có thể rất nhỏ, và menu sẽ co dúm
       lại — hỏng nặng hơn tràn. Đúng cách là chặn theo VIEWPORT:
         .ptui-menu    220px
         .ptui-dt-pop  220px
       Cả hai trước đây KHÔNG có `max-width` nào → trên màn hẹp chúng tràn khỏi màn hình.

   Bài học đưa vào skill: control dùng chung không được đặt kích thước mà khung chứa
   không ghi đè được. "Bề rộng mong muốn" ≠ "bề rộng tối thiểu tuyệt đối".
   ========================================================================== */

/* (A) trong luồng — tụt theo khung chứa khi chật */
.ptui-multiselect { min-width: min(230px, 100%); }
.ptui-store-button { min-width: min(168px, 100%); }
.ptui-calendar-title { min-width: min(150px, 100%); }

/* (B) lớp nổi — giữ sàn, chặn trần theo viewport để không tràn khỏi màn hình */
.ptui-menu, .ptui-dt-pop { max-width: calc(100vw - 24px); }

/* ==== v0.17.3 — SELECT VỀ ĐÚNG MỘT CƠ CHẾ VỚI CÁC CONTROL KHÁC ===========
   Hai lệch đo được trên bản live (trang Quản trị → Tài khoản chat):

   (1) BO GÓC KHÔNG KHỚP. Giá trị cuối cùng của các control form:
         .ptui-btn · .ptui-iconbtn · .ptui-input · .ptui-input-wrap → --ptui-radius     (10px)
         .ptui-select select · .ptui-multiselect > button           → --ptui-radius-sm   (6px)
       Đặt một Select cạnh một Input trong cùng form là góc bo không khớp. Đúng thứ mục 3
       Consistency Gate cấm: một cơ chế cho một loại control.
       (`.ptui-check-box` giữ 6px — ô tick nhỏ, khác thang, không phải control nhập liệu.)

   (2) CARET LÀM NỬA VỜI. `.ptui-select select` chừa `padding-right: 38px` — bằng chứng ý đồ
       là vẽ caret riêng — nhưng thư viện KHÔNG hề vẽ, cũng không `appearance: none`. Kết quả:
       mũi tên của hệ điều hành hiện lên giữa 38px trống, và mỗi HĐH một kiểu mũi tên.
       Vẽ caret bằng CSS trên wrapper vì `<select>` native không chứa được phần tử con —
       KHÔNG dùng ảnh/data-URI (sẽ phải nhúng mã màu cứng, phá luật 0-hex).
   ========================================================================= */
.ptui-select select,
.ptui-multiselect > button { border-radius: var(--ptui-radius); }

.ptui-select { position: relative; }
.ptui-select select { appearance: none; -webkit-appearance: none; }
/* Chevron: một ô vuông chỉ còn 2 cạnh, xoay 45°. Neo theo ĐÁY wrapper để vẫn đúng chỗ khi
   phía trên có nhãn (`.ptui-select` là grid: nhãn ở trên, select ở dưới). */
.ptui-select::after {
  content: "";
  position: absolute;
  right: 15px;
  bottom: calc(var(--ptui-control-height) / 2 - 3px);
  width: 7px; height: 7px;
  border-right: 1.5px solid var(--ptui-text-muted);
  border-bottom: 1.5px solid var(--ptui-text-muted);
  transform: rotate(45deg);
  pointer-events: none;
}

/* ==== v0.17.5 — CHỮ NHẠT TRÊN NỀN ĐẬM HƠN SURFACE (sửa lỗi WCAG AA) =======
   Luật đã có sẵn trong `tokens/colors.css` từ 14/08/2026 và được `contrast.test.mjs`
   khoá ở TẦNG TOKEN: `--ptui-text-muted` chỉ đạt AA trên `--ptui-bg` (4.51) và
   `--ptui-surface` (4.83); trên nền đậm hơn surface nó TRƯỢT — `bg-subtle` 4.31,
   `bg-muted` 4.09 — nên chữ phụ ở đó PHẢI lên bậc `--ptui-text-secondary` (9.32).

   Lỗ hổng: test cũ chỉ kiểm CẶP TOKEN, không hề quét NƠI DÙNG. Nên luật đúng nằm
   trong comment suốt ~3 tuần trong khi 4 luật CSS thật vẫn vi phạm nó. Đo lại
   02/09/2026 trên 0.17.4 bằng công thức WCAG từ token thật (chỉ LIGHT hỏng; dark
   đạt sẵn 7.24, và lên secondary thành 12.55):

     .ptui-table thead th          4.31 → 9.32   12px/700   (bg-subtle)
     .pill-tab-count               4.31 → 9.32   11px/700   (bg-subtle) — ô đếm ở
        trạng thái KHÔNG chọn; bản is-active đã có test từ 0.7.0, bản thường thì chưa
     .ptui-calendar-day.is-outside 4.31 → 9.32   14px/400   (bg-subtle)
     .ptui-kb-empty                4.39 → 9.47   12.5px/700 (kb-drop-bg ghép trên surface)

   Không ca nào được hưởng ngưỡng large-text 3.0 (large = ≥18.66px bold hoặc ≥24px).

   KHÔNG nâng chính token `muted`: lên zinc-600 thì khoảng cách với `secondary` tụt còn
   1.35, hai bậc chữ gần như không phân biệt được — hỏng thang chữ 4 bậc. Quyết định này
   đã chốt 14/08/2026, giữ nguyên.

   MIỄN TRỪ có chủ đích (máy quét vẫn thấy, cố ý không sửa):
     · `.ptui-btngroup-item:disabled`, `.ptui-input[aria-disabled="true"]` — WCAG 2.1
       §1.4.3 miễn cho control ở trạng thái vô hiệu.
     · `.ptui-empty-icon` — `font-size: 0`, là ô chứa icon chứ không phải chữ.
   ========================================================================= */
.ptui-table thead th { color: var(--ptui-text-secondary); }
/* Nâng th lên secondary làm luật hover cũ (cũng secondary) thành vô hiệu về thị giác;
   đẩy hover lên `--ptui-text` để cột sắp xếp được vẫn còn tín hiệu phản hồi. */
.ptui-table thead th.ptui-th-sortable:hover { color: var(--ptui-text); }
.pill-tab-count { color: var(--ptui-text-secondary); }
.ptui-calendar-day.is-outside { color: var(--ptui-text-secondary); }
.ptui-kb-empty { color: var(--ptui-text-secondary); }

/* --- Cùng họ, máy quét `tests/contrast-usage.test.mjs` bắt được khi lần nền từ selector
   CHA (grep từng rule đơn lẻ không thấy, vì nền nằm ở phần tử bao ngoài) --- */
.ptui-carousel-controls span { color: var(--ptui-text-secondary); }        /* 4.31 → 9.32 */
.ptui-calendar-date-tile span { color: var(--ptui-text-secondary); }       /* 4.31 → 9.32 */
.ptui-uploader-drop > span:last-child { color: var(--ptui-text-secondary); } /* 4.31 → 9.32 */
.ptui-toggle-copy small { color: var(--ptui-text-secondary); }             /* 4.09 → 8.84 */

/* --- Họ THỨ HAI, phát hiện trong cùng lượt quét: `--ptui-text-subtle` bị dùng làm CHỮ.
   subtle (zinc-400) trên surface trắng chỉ 2.56 — trượt AA ngay cả trên nền sáng nhất, và
   dưới cả ngưỡng non-text 3.0 nên icon cũng không thoát. Hạ một bậc xuống `muted` là mức
   tối thiểu đủ đạt (4.83 light / 7.24 dark) mà vẫn giữ được sắc thái "chữ mờ".
   subtle vẫn hợp lệ cho ĐƯỜNG VIỀN và hình trang trí — chỉ không được làm chữ. --- */
.ptui-input::placeholder { color: var(--ptui-text-muted); }                /* 2.56 → 4.83 */
.ptui-dt-pop .ptui-dt-filterwrap svg { color: var(--ptui-text-muted); }    /* 2.56 → 4.83 */

/* =========================================================================
   v0.18.0 — LỚP NỔI ĐỊNH VỊ THEO CHỖ TRỐNG THẬT (`usePopoverPosition`)

   Trước đợt này mọi lớp nổi định vị bằng hằng số CSS: `.ptui-menu` là
   `top: calc(100% + 6px); left: 0`, `.ptui-dt-pop` là `top: 40px; right: 4px`,
   tooltip là 4 class placement tĩnh. Hệ quả đo được: tràn ra ngoài màn hình khi
   trigger nằm sát mép, và — nặng hơn — `position: absolute` bị `overflow` của
   bảng/khung cuộn CẮT.

   Toạ độ nay do JS tính và đặt bằng inline style; các luật dưới đây chỉ lo phần
   CSS không đặt được bằng inline: đổi hệ quy chiếu sang `fixed`, gỡ các hằng số
   cũ, và cho tooltip đã tách khỏi cây DOM của trigger biết cách tự hiện.
   ========================================================================= */

/* Toạ độ tới từ inline style. `inset: auto` xoá sạch hằng số của luật gốc, để một
   thuộc tính sót lại (vd `right: 4px` của `.ptui-dt-pop`) không kéo lệch lớp nổi. */
.ptui-menu--fixed,
.ptui-dt-pop--fixed,
.ptui-multiselect-menu--fixed,
.ptui-date-popover--fixed {
  position: fixed;
  inset: auto;
  max-width: calc(100vw - 24px);
  /* 0.21.2: portal = anh em cua modal => z phai TREN modal (1100), DUOI toast (1200).
     Bug do duoc: MultiSelect trong Modal bam khong chon duoc vi menu nam sau overlay. */
  z-index: var(--ptui-z-popover-floating);
}

/* `.ptui-multiselect-menu` khai z-index 35 tại chỗ — thấp hơn modal (1100), banner và
   toast, nên menu chui xuống dưới mọi thứ. Nó bị bỏ sót khỏi khối đưa-về-token ở trên;
   sửa cho cả bản thường lẫn bản nổi vì cùng một lỗi. */
.ptui-multiselect-menu { z-index: var(--ptui-z-popover); }

/* Tooltip bản `floating` rời khỏi cây DOM của trigger qua portal, nên hai cơ chế cũ đều
   mất tác dụng: `.ptui-tip:hover .ptui-tip-pop` không còn khớp để hiện, và
   `.ptui-tip--{placement} .ptui-tip-arrow` không còn khớp để chỉ hướng. Trạng thái hiện
   do React quyết (chỉ mount khi mở), hướng đọc từ `data-placement` — và đó là hướng ĐÃ
   LẬT thật sự, không phải hướng người viết chọn, nếu không mũi tên chỉ sai phía. */
.ptui-tip-pop--fixed {
  position: fixed;
  inset: auto;
  opacity: 1;
  visibility: visible;
  transform: none;
}
.ptui-tip-pop--fixed.ptui-tip-pop--rich { max-width: 264px; padding: 10px 12px; }

.ptui-tip-pop--fixed[data-placement="top"] .ptui-tip-arrow { bottom: -4px; left: 50%; margin-left: -4px; }
.ptui-tip-pop--fixed[data-placement="bottom"] .ptui-tip-arrow { top: -4px; left: 50%; margin-left: -4px; }
.ptui-tip-pop--fixed[data-placement="left"] .ptui-tip-arrow { right: -4px; top: 50%; margin-top: -4px; }
.ptui-tip-pop--fixed[data-placement="right"] .ptui-tip-arrow { left: -4px; top: 50%; margin-top: -4px; }

/* =========================================================================
   v0.18.1 — CHART TOOLTIP GIA NHAP HO LOP NOI

   `.ptui-chart-tip` la thanh vien cuoi cung con dinh vi bang hang so CSS sau dot
   0.18.0 (co y de ngoai scope vi no thuoc nhom charts). Hai loi do duoc:
   (a) `transform: translate(12px, -50%)` LUON bat sang phai con tro, khong bao gio
       lat -> re chuot sat mep phai thi tooltip bi cat (con tro cach mep 20px,
       tooltip 260px -> tran 252px);
   (b) `z-index: 30` viet tay, khong dung thang token -> nam duoi moi lop noi khac,
       dung hang loi da sua cho `.ptui-multiselect-menu` ngay ben tren.
   ========================================================================= */

/* Tooltip PHAI o bac cao nhat truoc drag-ghost — cung bac voi `.ptui-tip-pop`,
   vi chart co the nam trong Modal (1100) lan trong Toast (1200). */
.ptui-chart-tip { z-index: var(--ptui-z-tip); }

/* Toa do tu inline style cua `usePopoverPosition`. `transform: none` la bat buoc:
   transform duoc ap SAU khi layout xong nen no se day tooltip ra khoi dung vi tri
   vua clamp — tuc lam vo chinh phep do. `inset: auto` xoa not hang so cua luat goc. */
.ptui-chart-tip--fixed {
  position: fixed;
  inset: auto;
  transform: none;
  max-width: min(260px, calc(100vw - 24px));
}

/* =========================================================================
   v0.20 — NUT THEO Y NGHIA (intent) — 04/09/2026

   Chu du an dao quyet dinh "primary trung tinh den" cua 0.14.0: nut chinh ve
   MAU THUONG HIEU (token doi o tokens/intent.css, luat .ptui-btn-primary o khoi
   v0.14 ben tren KHONG can sua vi no da doc qua token). Khoi nay chi THEM 3
   variant con thieu de moi y nghia co dung mot class — ban do day du o
   docs/DESIGN-PRINCIPLES.md ch.2:
     .ptui-btn-success  duyet / chap nhan (chi trong cap quyet dinh, canh danger)
     .ptui-btn-warning  hanh dong can can nhac (tam khoa, thu hoi, gui lai qua han)
     .ptui-btn-ghost    xem / chi tiet — khong vien, khong nen, chi hien nen khi hover
   Ca ba theo dung khuon 2D cua khoi v0.14: 0 gradient, 0 translateY, 0 shadow
   tren nut dac, vien 1px transparent giu box model, chi transition mau.
   0 hex trong khoi nay — moi mau qua token (check:design muc 1 soi tu "v0.14b").
   ========================================================================= */
.ptui-btn-success {
  background: var(--ptui-btn-success-bg);
  border-color: transparent;
  color: var(--ptui-btn-success-fg);
  box-shadow: none;
}
.ptui-btn-success:hover { background: var(--ptui-btn-success-bg-hover); border-color: transparent; box-shadow: none; }
.ptui-btn-success:active { background: var(--ptui-btn-success-bg-active); border-color: transparent; box-shadow: none; }

.ptui-btn-warning {
  background: var(--ptui-btn-warning-bg);
  border-color: transparent;
  color: var(--ptui-btn-warning-fg);
  box-shadow: none;
}
.ptui-btn-warning:hover { background: var(--ptui-btn-warning-bg-hover); border-color: transparent; box-shadow: none; }
.ptui-btn-warning:active { background: var(--ptui-btn-warning-bg-active); border-color: transparent; box-shadow: none; }

/* Ghost: Fluent `subtle` / M3 `text` — chu mau secondary, hover moi hien nen.
   Vien transparent (KHONG bo border) de doi sang variant khac khong nhay 1px. */
.ptui-btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--ptui-text-secondary);
  box-shadow: none;
}
.ptui-btn-ghost:hover { background: var(--ptui-bg-muted); border-color: transparent; color: var(--ptui-text); box-shadow: none; }
.ptui-btn-ghost:active { background: var(--ptui-bg-subtle); border-color: transparent; box-shadow: none; }

/* Icon TRONG nut dac ke thua mau chu cua nut — mot icon do tren nut xanh la la
   loi ngu nghia, nen chan o CSS chu khong chi o tai lieu (DESIGN-PRINCIPLES ch.3:
   "icon theo tone cua nut, khong tu mang tone rieng"). */
.ptui-btn-primary .ptui-ico,
.ptui-btn-success .ptui-ico,
.ptui-btn-warning .ptui-ico,
.ptui-btn-danger .ptui-ico { color: inherit; }

/* =========================================================================
   v0.21 — STATE LAYER THEO TONE (04/09/2026, chu du an chot "giu 2D, them state")

   0.20 cho moi y nghia mot mau; khoi nay cho moi mau DU 8 trang thai ma van 2D:
   (1) focus-visible: vong sang CUNG TONE voi nut (truoc day nut do/xanh la deu
       mang ring xanh accent — sai nghia, Fluent/M3 deu ring theo mau nut);
   (2) hover/pressed cua outline & ghost: lop phu tone 8%/14% (co che state layer
       M3: --ptui-state-hover/-pressed) tinh bang color-mix, khong gradient;
   (3) icon trong nut tu ve 16px (M3/Fluent: icon 20/16 trong nut 40/32) — app
       khong con phai gan class kich thuoc len tung <svg>;
   (4) [aria-busy="true"]: con tro progress + khoa click, giu be rong (khong nhay);
   (5) pressed cua nut dac: them vien trong 1px ban trong suot de "chim" nhe.
   0 hex; moi mau qua token/color-mix; khong translateY/gradient/brightness.
   ========================================================================= */
.ptui-btn:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 2px; }
.ptui-btn-primary:focus-visible { outline-color: color-mix(in srgb, var(--ptui-btn-primary-bg) 45%, transparent); }
.ptui-btn-success:focus-visible { outline-color: color-mix(in srgb, var(--ptui-btn-success-bg) 45%, transparent); }
.ptui-btn-warning:focus-visible { outline-color: color-mix(in srgb, var(--ptui-btn-warning-bg) 45%, transparent); }
.ptui-btn-danger:focus-visible  { outline-color: color-mix(in srgb, var(--ptui-btn-danger-bg) 45%, transparent); }

/* (2) state layer: outline lay accent, ghost lay chu (text) lam mau phu */
.ptui-btn-outline:hover  { background: color-mix(in srgb, var(--ptui-accent) 8%, transparent); }
.ptui-btn-outline:active { background: color-mix(in srgb, var(--ptui-accent) 14%, transparent); }
.ptui-btn-ghost:hover    { background: color-mix(in srgb, var(--ptui-text) 8%, transparent); color: var(--ptui-text); }
.ptui-btn-ghost:active   { background: color-mix(in srgb, var(--ptui-text) 14%, transparent); }

/* (5) nut dac khi nhan: vien trong toi 1px — cam giac "chim" ma khong dich chuyen */
.ptui-btn-primary:active, .ptui-btn-success:active, .ptui-btn-warning:active, .ptui-btn-danger:active {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ptui-text) 18%, transparent);
}

/* (3) icon trong nut: 16px, khong co, canh giua; app truyen class kich thuoc rieng thi thang */
.ptui-btn > svg:not([class*="size-"]), .ptui-ai-btn > svg:not([class*="size-"]), .ptui-actionbtn > svg:not([class*="size-"]) {
  width: 16px; height: 16px; flex: 0 0 auto;
}

/* (4) busy: khong khoa opacity (do la disabled), chi doi con tro + chan click */
.ptui-btn[aria-busy="true"], .ptui-ai-btn[aria-busy="true"] { cursor: progress; pointer-events: none; }

/* =========================================================================
   v0.21.1 — BADGE 10 TONE TRANG THAI (04/09/2026)

   Badge cua sample chi co 5 tone ngu nghia (neutral/accent/success/warning/danger)
   trong khi PillTabs da co 10 tone --ptui-st-* tu 0.8.x. App ATS phai gia lap
   purple/teal/cyan bang class Tailwind — roi bi chinh .ptui-badge-accent de len nen
   "purple" hien XANH. Nay badge va pill-tab dung CUNG thang 10 tone: badge cho
   "phan loai" (giai doan, loai doi tuong) lay tone --ptui-st-*, badge cho "trang thai
   he thong" van dung 5 tone ngu nghia. Dark tu doi qua token -bg/-fg cua status.css.
   ========================================================================= */
.ptui-badge-all    { background: var(--ptui-st-all-bg);    color: var(--ptui-st-all-fg); }
.ptui-badge-gray   { background: var(--ptui-st-gray-bg);   color: var(--ptui-st-gray-fg); }
.ptui-badge-blue   { background: var(--ptui-st-blue-bg);   color: var(--ptui-st-blue-fg); }
.ptui-badge-amber  { background: var(--ptui-st-amber-bg);  color: var(--ptui-st-amber-fg); }
.ptui-badge-purple { background: var(--ptui-st-purple-bg); color: var(--ptui-st-purple-fg); }
.ptui-badge-teal   { background: var(--ptui-st-teal-bg);   color: var(--ptui-st-teal-fg); }
.ptui-badge-green  { background: var(--ptui-st-green-bg);  color: var(--ptui-st-green-fg); }
.ptui-badge-red    { background: var(--ptui-st-red-bg);    color: var(--ptui-st-red-fg); }
.ptui-badge-orange { background: var(--ptui-st-orange-bg); color: var(--ptui-st-orange-fg); }
.ptui-badge-cyan   { background: var(--ptui-st-cyan-bg);   color: var(--ptui-st-cyan-fg); }

/* =========================================================================
   v0.22 — BOOKING: bo lich hen (05/09/2026, DIEU CHINH thu vien)
   Port khoi .cal-* / .appt-* cua Peram Talent ATS (styles.css ~3201-3495) ve
   namespace .ptui-booking-*. Bo cuc: board .ptui-booking (thang = anatomy
   .ptui-calendar-* co san; tuan/ngay = time-grid .ptui-booking-tg-* kieu Outlook),
   rail .ptui-booking-rail (checkbox chu lich + loi moi), dialog .ptui-booking-dialog
   (Teams "New meeting" 5 hang). TOKEN-ONLY: 0 hex ke ca trong comment; spacing
   dung thang 4/8/12/16/24 px vi thu vien KHONG co --ptui-space-* (ATS dung
   --space-* cua app — khong mang sang). Pill giu 999px vi khong co token radius-pill.
   Sua khi port (audit 05/09): header ngay padding 8px (truoc 8px 6px) · pill hom nay
   2px 8px (truoc 1px 8px) · the event 4px 8px, gon 4px · hang rail 4px 0 (truoc 3px 0),
   gap 8px (truoc 6px) · nut go = ActionIcon 34px (truoc 30px tu che) · so ngay thang
   28px (truoc 26px) · head 12px 16px (truoc 10px 14px) · inset the doi xung qua bien.
   GRADIENT: .ptui-booking-tg-event co linear-gradient CO CHU Y — the event la BE MAT
   DU LIEU (nhu KanbanCard), khong phai nut; luat 2D "0 gradient" (ch.1) chi soi
   selector .ptui-btn*. Ghi o docs/DESIGN-PRINCIPLES.md.
   ========================================================================= */

/* ---- Board: bo sung cho anatomy .ptui-calendar-* khi nam trong .ptui-booking ---- */
.ptui-booking { min-width: 0; }
.ptui-booking .ptui-calendar-head { min-width: 0; padding: 12px 16px; }
.ptui-booking .ptui-calendar-month { min-width: 0; }
.ptui-booking .ptui-calendar-title strong { white-space: nowrap; }
.ptui-booking .ptui-calendar-view { width: auto; min-width: 110px; }
.ptui-booking .ptui-calendar-add { flex: 0 0 auto; white-space: nowrap; }
/* Vong "hom nay" — nen accent, chu on-accent (anatomy goc chi co is-selected). */
.ptui-booking .ptui-calendar-day.is-today .ptui-calendar-day-number {
  background: var(--ptui-accent); color: var(--ptui-text-on-accent); font-weight: var(--ptui-weight-bold);
}
.ptui-booking .ptui-calendar-day-number { width: 28px; height: 28px; }

/* ---- TONE: moi tone bom --ptui-booking-tone / -bg / -fg tu status-hue --ptui-st-*
   (accent tu --ptui-accent*). Chip thang (.ptui-calendar-event) nen phang; the
   time-grid dung cung bien de dung vien + gradient + shadow. ---- */
.ptui-booking-tone--blue   { --ptui-booking-tone: var(--ptui-st-blue);   --ptui-booking-tone-bg: var(--ptui-st-blue-bg);   --ptui-booking-tone-fg: var(--ptui-st-blue-fg); }
.ptui-booking-tone--purple { --ptui-booking-tone: var(--ptui-st-purple); --ptui-booking-tone-bg: var(--ptui-st-purple-bg); --ptui-booking-tone-fg: var(--ptui-st-purple-fg); }
.ptui-booking-tone--orange { --ptui-booking-tone: var(--ptui-st-orange); --ptui-booking-tone-bg: var(--ptui-st-orange-bg); --ptui-booking-tone-fg: var(--ptui-st-orange-fg); }
.ptui-booking-tone--amber  { --ptui-booking-tone: var(--ptui-st-amber);  --ptui-booking-tone-bg: var(--ptui-st-amber-bg);  --ptui-booking-tone-fg: var(--ptui-st-amber-fg); }
.ptui-booking-tone--red    { --ptui-booking-tone: var(--ptui-st-red);    --ptui-booking-tone-bg: var(--ptui-st-red-bg);    --ptui-booking-tone-fg: var(--ptui-st-red-fg); }
.ptui-booking-tone--green  { --ptui-booking-tone: var(--ptui-st-green);  --ptui-booking-tone-bg: var(--ptui-st-green-bg);  --ptui-booking-tone-fg: var(--ptui-st-green-fg); }
.ptui-booking-tone--cyan   { --ptui-booking-tone: var(--ptui-st-cyan);   --ptui-booking-tone-bg: var(--ptui-st-cyan-bg);   --ptui-booking-tone-fg: var(--ptui-st-cyan-fg); }
.ptui-booking-tone--teal   { --ptui-booking-tone: var(--ptui-st-teal);   --ptui-booking-tone-bg: var(--ptui-st-teal-bg);   --ptui-booking-tone-fg: var(--ptui-st-teal-fg); }
.ptui-booking-tone--accent { --ptui-booking-tone: var(--ptui-accent);    --ptui-booking-tone-bg: var(--ptui-accent-soft);  --ptui-booking-tone-fg: var(--ptui-accent); }
/* Chip thang: nen phang tone-bg, chu tone-fg, vach trai tone. */
.ptui-booking .ptui-calendar-event[class*="ptui-booking-tone--"] {
  background: var(--ptui-booking-tone-bg); color: var(--ptui-booking-tone-fg);
  border-left: 3px solid var(--ptui-booking-tone);
}
.ptui-booking .ptui-calendar-event.is-past, .ptui-booking-tg-event.is-past { opacity: 0.55; }
/* Badge tren the: ke thua chu tone, chi ha co + vien mong. Specificity 0,2,0 de thang
   .ptui-badge-<tone> (0,1,0) bat ke thu tu khoi. */
.ptui-booking .ptui-booking-tg-event-badge {
  display: inline-block; margin-left: 4px; padding: 0 4px; font-size: var(--ptui-text-xs);
  line-height: 1.5; vertical-align: 1px; border: 1px solid currentColor; background: transparent; color: inherit; opacity: 0.85;
}

/* ---- TIME-GRID (tuan/ngay) kieu Outlook: header ngay + than CUON doc 24h, hang gio cao
   CO DINH (--ptui-booking-hour-h), cuon toi 07:00 khi mo; ngoai gio 08-18 to mo; vach nua
   gio; the event 3 dong (khoang gio · tieu de · phu). ---- */
.ptui-booking-tg {
  --ptui-booking-hour-h: 60px;
  /* inset doi xung cua the event: top/left +inset, height/width -2*inset (JSX doc bien nay). */
  --ptui-booking-event-inset: 2px;
  display: flex; flex-direction: column;
}
.ptui-booking-tg-head, .ptui-booking-tg-body {
  display: grid; grid-template-columns: 56px repeat(var(--ptui-booking-days, 7), minmax(0, 1fr));
}
.ptui-booking-tg-head { border-bottom: 1px solid var(--ptui-border); }
.ptui-booking-tg-corner { border-right: 1px solid var(--ptui-border); }
.ptui-booking-tg-dayhead {
  appearance: none; font: inherit; border: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 8px; background: var(--ptui-surface); color: var(--ptui-text);
  border-right: 1px solid var(--ptui-border);
}
.ptui-booking-tg-dayhead:last-child { border-right: 0; }
.ptui-booking-tg-dayhead:hover { background: var(--ptui-surface-hover); }
.ptui-booking-tg-dayhead:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: -2px; }
.ptui-booking-tg-daywd {
  font-size: var(--ptui-text-xs); font-weight: var(--ptui-weight-bold); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--ptui-text-muted);
}
.ptui-booking-tg-daynum { font-size: var(--ptui-text-lg); font-weight: var(--ptui-weight-bold); color: var(--ptui-text-secondary); font-variant-numeric: tabular-nums; }
.ptui-booking-tg-dayhead.is-today .ptui-booking-tg-daywd { color: var(--ptui-accent); }
.ptui-booking-tg-dayhead.is-today .ptui-booking-tg-daynum {
  color: var(--ptui-text-on-accent); background: var(--ptui-accent); border-radius: 999px; padding: 2px 8px;
}
.ptui-booking-tg-scroll { max-height: calc(100vh - 320px); min-height: 320px; overflow-y: auto; overflow-x: hidden; scrollbar-gutter: stable; }
.ptui-booking-tg-gutter { border-right: 1px solid var(--ptui-border); }
.ptui-booking-tg-hourlabel {
  height: var(--ptui-booking-hour-h); font-size: var(--ptui-text-xs); color: var(--ptui-text-muted); text-align: right;
  padding-right: 6px; font-family: var(--ptui-font-sans); font-variant-numeric: tabular-nums;
  /* Can quang hoc: nhan "09:00" nam DUNG tren vach gio (nua chieu cao chu), khong nam duoi vach. */
  transform: translateY(-7px);
}
.ptui-booking-tg-col { position: relative; border-right: 1px solid var(--ptui-border); }
.ptui-booking-tg-col:last-child { border-right: 0; }
.ptui-booking-tg-col.is-today { background: color-mix(in srgb, var(--ptui-accent-soft) 45%, transparent); }
/* O gio trong = BUTTON tao lich hen (click -> onSlotClick(ymd, hour)). */
.ptui-booking-tg-slot {
  appearance: none; font: inherit; border: 0; padding: 0; cursor: pointer;
  position: relative; display: block; width: 100%; height: var(--ptui-booking-hour-h); background: transparent;
  border-bottom: 1px solid var(--ptui-border);
}
.ptui-booking-tg-slot.is-offhours { background: var(--ptui-bg-subtle); }
/* Vach nua gio mo nhu Outlook — pseudo nen khong them node. */
.ptui-booking-tg-slot::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; pointer-events: none;
  border-top: 1px dashed color-mix(in srgb, var(--ptui-border) 70%, transparent);
}
.ptui-booking-tg-slot:hover { background: color-mix(in srgb, var(--ptui-accent-soft) 55%, transparent); }
.ptui-booking-tg-slot:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: -2px; }
/* The event: vien net cung tone, gradient nhe tren->duoi (tint 16% -> 34% tren surface),
   shadow md + hairline tone; chu la tone -fg nen contrast khong doi. Gradient o day la
   CO CHU Y (be mat du lieu, khong phai nut — xem dau khoi). */
.ptui-booking-tg-event {
  position: absolute; z-index: 2; overflow: hidden; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 1px; padding: 4px 8px;
  font: inherit; font-size: var(--ptui-text-sm); line-height: 1.3;
  container-type: inline-size;
  border-radius: var(--ptui-radius-sm);
  color: var(--ptui-booking-tone-fg, var(--ptui-accent));
  border: 1px solid color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 70%, transparent);
  border-left: 4px solid var(--ptui-booking-tone, var(--ptui-accent));
  background-color: var(--ptui-booking-tone-bg, var(--ptui-accent-soft));
  background-image: linear-gradient(180deg,
    color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 16%, var(--ptui-surface)),
    color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 34%, var(--ptui-surface)));
  box-shadow: var(--ptui-shadow-md), 0 0 0 1px color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 18%, transparent);
}
.ptui-booking-tg-event:hover {
  border-color: var(--ptui-booking-tone, var(--ptui-accent));
  background-image: linear-gradient(180deg,
    color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 14%, var(--ptui-surface)),
    color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 30%, var(--ptui-surface)));
  box-shadow: var(--ptui-shadow-lg), 0 0 0 1px color-mix(in srgb, var(--ptui-booking-tone, var(--ptui-accent)) 24%, transparent);
}
.ptui-booking-tg-event:focus-visible { outline: 2px solid var(--ptui-accent-ring); outline-offset: 1px; }
.ptui-booking-tg-event-time { font-weight: var(--ptui-weight-bold); font-variant-numeric: tabular-nums; display: flex; align-items: baseline; gap: 6px; min-width: 0; white-space: nowrap; }
.ptui-booking-tg-event-start { flex: 0 0 auto; }
.ptui-booking-tg-event-end { font-weight: var(--ptui-weight-regular); opacity: 0.8; }
/* The hep (2+ lan chong gio trong cot tuan) -> che do gon: chi gio bat dau + tieu de. */
@container (max-width: 110px) {
  .ptui-booking-tg-event-end, .ptui-booking-tg-event-creator, .ptui-booking-tg-event-sub { display: none; }
  .ptui-booking-tg-event { padding: 4px; }
}
/* Nguoi tao: dung khoang trong ngang dong gio, canh phai, khong them dong. */
.ptui-booking-tg-event-creator { margin-left: auto; font-weight: var(--ptui-weight-regular); font-size: var(--ptui-text-xs); opacity: 0.75; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 64%; }
.ptui-booking-tg-event-title { font-size: var(--ptui-text-md); font-weight: var(--ptui-weight-bold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ptui-booking-tg-event-sub { font-size: var(--ptui-text-xs); opacity: 0.8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ptui-booking-tg-event-attendees { display: inline-flex; align-items: center; gap: 2px; }
/* Kim do gio hien tai (chi cot hom nay). */
.ptui-booking-tg-now {
  position: absolute; left: 0; right: 0; height: 0; z-index: 3; pointer-events: none;
  border-top: 2px solid var(--ptui-danger);
}
.ptui-booking-tg-now::before {
  content: ""; position: absolute; left: -4px; top: -5px; width: 8px; height: 8px;
  border-radius: 999px; background: var(--ptui-danger);
}

/* ---- MAU CHU LICH (.is-owned — PHAI dung SAU cac luat tone: last-wins ghi de
   --ptui-booking-tone). JSX bom --ptui-booking-owner/-fg/-bg khi ownerId co trong toneById;
   the va cham trong rail cung mot hue. ---- */
.ptui-booking .ptui-calendar-event.is-owned, .ptui-booking-tg-event.is-owned {
  --ptui-booking-tone: var(--ptui-booking-owner);
  --ptui-booking-tone-bg: var(--ptui-booking-owner-bg);
  --ptui-booking-tone-fg: var(--ptui-booking-owner-fg);
  background-color: var(--ptui-booking-owner-bg); color: var(--ptui-booking-owner-fg);
  border-left-color: var(--ptui-booking-owner); border-left-width: 4px;
}

/* ---- DIALOG lich hen kieu Teams "New meeting": moi hang = cot icon 24px + noi dung;
   tieu de + dia diem kieu GACH CHAN (van .ptui-input, chi doi vien/nen — scoped
   .ptui-booking-dialog); nhan MultiSelect/Select giu trong DOM cho a11y, an thi giac. ---- */
.ptui-booking-form { display: grid; gap: 16px; padding-block: 8px; }
.ptui-booking-row { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: 12px; align-items: start; }
.ptui-booking-row-body { min-width: 0; display: grid; gap: 8px; }
.ptui-booking-row-icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: var(--ptui-control-height); color: var(--ptui-text-muted); }
.ptui-booking-row > .ptui-input, .ptui-booking-row > .ptui-textarea-field { min-width: 0; width: 100%; }
.ptui-booking-dialog .ptui-booking-row > .ptui-input:not(.ptui-textarea) {
  border-width: 0 0 1px; border-radius: 0; padding-inline: 0; background: transparent; box-shadow: none;
}
.ptui-booking-dialog .ptui-booking-row > .ptui-input:not(.ptui-textarea):focus { border-bottom-color: var(--ptui-accent); box-shadow: none; }
.ptui-booking-dialog .ptui-input.ptui-booking-title { height: auto; padding-block: 8px; font-size: var(--ptui-text-lg); font-weight: var(--ptui-weight-bold); color: var(--ptui-text); }
.ptui-booking-attendees { display: grid; gap: 8px; min-width: 0; }
.ptui-booking-attendees .ptui-multiselect { min-width: 0; }
.ptui-booking-attendee-tags { display: flex; flex-wrap: wrap; gap: 8px; }
.ptui-booking-attendee-tags .ptui-tag { gap: 8px; }
.ptui-booking-attendee-code { color: var(--ptui-text-muted); font-size: var(--ptui-text-xs); }
.ptui-booking-when { display: grid; gap: 8px; min-width: 0; }
.ptui-booking-time-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ptui-booking-hm select { min-width: 0; width: 112px; }
.ptui-booking-duration { display: block; }
.ptui-booking-dialog .ptui-multiselect > .ptui-field-label, .ptui-booking-dialog .ptui-select.ptui-booking-hm > span:first-child {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.ptui-booking-dialog-foot { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ptui-booking-dialog-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }

/* ---- LAYOUT 2 cot: rail co dinh 264px | board co gian. Rail thua huong flex cua
   trang (viewport-fit) nen board van tinh dung chieu cao 6 hang thang. ---- */
.ptui-booking-layout { display: flex; align-items: stretch; gap: 16px; min-width: 0; min-height: 0; }
.ptui-booking-rail {
  flex: 0 0 264px; width: 264px; min-width: 0; min-height: 0;
  display: flex; flex-direction: column; gap: 12px; overflow-y: auto;
}
.ptui-booking-rail-panel { flex: 0 0 auto; }

/* ---- Danh sach calendar ---- */
.ptui-booking-callist, .ptui-booking-callist-items, .ptui-booking-invites { list-style: none; margin: 0; padding: 0; }
/* Tieu de nhom: tren 12px (tach nhom truoc, = 1 bac spacing) / duoi 4px (dinh vao hang dau cua nhom minh) — ty le 3:1 de nhom doc thanh cum. */
.ptui-booking-callist-group {
  margin: 12px 0 4px; font-size: var(--ptui-text-xs); font-weight: var(--ptui-weight-bold);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--ptui-text-subtle);
}
.ptui-booking-callist > li:first-child > .ptui-booking-callist-group { margin-top: 0; }
.ptui-booking-callist-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.ptui-booking-callist-row > .ptui-check { flex: 1 1 auto; min-width: 0; }
/* .ptui-check-text la block, khong co -> ten khong ellipsis, nut X de len. Ep chuoi co: text -> label -> name. */
.ptui-booking-callist-row .ptui-check-text { flex: 1 1 auto; min-width: 0; }
.ptui-booking-callist-row .ptui-booking-callist-label { display: flex; width: 100%; }
.ptui-booking-callist-label { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.ptui-booking-callist-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ptui-booking-callist-count { flex: 0 0 auto; font-size: var(--ptui-text-xs); color: var(--ptui-text-muted); }
/* Nut go = .ptui-actionbtn 34px (ActionIcon) — chi co dinh khong co, kich thuoc do thu vien. */
.ptui-booking-callist-remove { flex: 0 0 auto; }

/* Cham mau dinh danh chu lich — cung 8 hue voi OWNER_TONES. */
.ptui-booking-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--ptui-st-gray); }
.ptui-booking-dot--blue   { background: var(--ptui-st-blue); }
.ptui-booking-dot--purple { background: var(--ptui-st-purple); }
.ptui-booking-dot--orange { background: var(--ptui-st-orange); }
.ptui-booking-dot--amber  { background: var(--ptui-st-amber); }
.ptui-booking-dot--red    { background: var(--ptui-st-red); }
.ptui-booking-dot--green  { background: var(--ptui-st-green); }
.ptui-booking-dot--cyan   { background: var(--ptui-st-cyan); }
.ptui-booking-dot--teal   { background: var(--ptui-st-teal); }

/* ---- Loi moi xem lich ---- */
.ptui-booking-invite-head { display: inline-flex; align-items: center; gap: 8px; }
.ptui-booking-invite { padding: 12px 0; border-top: 1px solid var(--ptui-border); }
.ptui-booking-invites > li:first-child { border-top: 0; }
.ptui-booking-invite-from { margin: 0; font-size: var(--ptui-text-sm); font-weight: var(--ptui-weight-medium); }
.ptui-booking-invite-msg { margin: 4px 0 0; font-size: var(--ptui-text-sm); color: var(--ptui-text-secondary); }
.ptui-booking-invite-at { margin: 2px 0 0; font-size: var(--ptui-text-xs); color: var(--ptui-text-muted); }
.ptui-booking-invite-actions { display: flex; gap: 8px; margin-top: 8px; }
.ptui-booking-invite-actions > button { flex: 1 1 0; }
.ptui-booking-invite--out { display: flex; align-items: center; gap: 8px; }
.ptui-booking-invite--out > .ptui-booking-callist-name { flex: 1 1 auto; font-size: var(--ptui-text-sm); }

/* ---- Modal chia se ---- */
.ptui-booking-share-form { display: flex; flex-direction: column; gap: 12px; }
.ptui-booking-share-form .ptui-booking-callist-items { max-height: 260px; overflow-y: auto; }

/* ---- VIEWPORT-FIT (.ptui-booking--fill): board chiem het chieu cao khung cha (flex
   column), thang = 6 hang chia deu, tuan/ngay = than luoi CUON trong phan con lai. ---- */
@media (min-width: 761px) and (min-height: 760px) {
  .ptui-booking--fill { flex: 1 1 auto; min-height: 0; height: 100%; display: flex; flex-direction: column; }
  .ptui-booking--fill .ptui-calendar-head { flex: 0 0 auto; }
  .ptui-booking--fill .ptui-calendar-date-tile { width: 52px; height: 52px; }
  .ptui-booking--fill[data-view="month"] .ptui-calendar-month { flex: 1 1 auto; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); }
  .ptui-booking--fill[data-view="month"] .ptui-calendar-weekdays span { padding: 6px; }
  .ptui-booking--fill[data-view="month"] .ptui-calendar-days { min-height: 0; grid-template-rows: repeat(6, minmax(0, 1fr)); }
  .ptui-booking--fill[data-view="month"] .ptui-calendar-day { min-height: 0; overflow: hidden; padding: 4px 6px; }
  .ptui-booking--fill[data-view="month"] .ptui-calendar-events { gap: 2px; margin-top: 2px; }
  .ptui-booking--fill[data-view="month"] .ptui-calendar-event { padding: 2px 5px; line-height: 1.2; }
  .ptui-booking--fill[data-view="week"] .ptui-booking-tg,
  .ptui-booking--fill[data-view="day"] .ptui-booking-tg { flex: 1 1 auto; min-height: 0; height: 100%; }
  /* Tuan/ngay KHONG ep 24 hang vua viewport (moi hang ~19px -> the bep): than cuon, hang giu --ptui-booking-hour-h. */
  .ptui-booking--fill[data-view="week"] .ptui-booking-tg-scroll,
  .ptui-booking--fill[data-view="day"] .ptui-booking-tg-scroll { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; }
  .ptui-booking-layout > .ptui-booking--fill { min-width: 0; }
}

/* Man hep: rail xuong duoi board, trai het be ngang. */
@media (max-width: 1100px) {
  .ptui-booking-layout { flex-direction: column-reverse; }
  .ptui-booking-rail { flex: 0 0 auto; width: 100%; overflow-y: visible; }
}

/* Mobile: toolbar xep luoi, chip thang thanh cham, time-grid cuon ngang, footer dialog doc. */
@media (max-width: 760px) {
  .ptui-booking { width: 100%; max-width: 100%; min-width: 0; overflow: hidden; }
  .ptui-booking .ptui-calendar-head { width: 100%; max-width: 100%; box-sizing: border-box; align-items: flex-start; flex-wrap: wrap; }
  .ptui-booking .ptui-calendar-actions {
    width: 100%; max-width: 100%; min-width: 0; margin-left: 0; box-sizing: border-box;
    display: grid; grid-template-columns: 44px minmax(88px, 1fr) 44px; gap: 8px;
  }
  .ptui-booking .ptui-calendar-view { grid-column: 1 / -1; width: 100%; min-width: 0; }
  .ptui-booking .ptui-calendar-add { grid-column: 1 / -1; width: 100%; margin-left: 0; }
  .ptui-booking .ptui-calendar-month, .ptui-booking .ptui-calendar-weekdays, .ptui-booking .ptui-calendar-days { width: 100%; max-width: 100%; min-width: 0; }
  .ptui-booking .ptui-calendar-day { min-width: 0; min-height: 84px; padding: 4px; }
  .ptui-booking .ptui-calendar-event { display: block; width: 7px; height: 7px; margin: 2px; padding: 0; border-left: 0; border-radius: 50%; font-size: 0; }
  .ptui-booking-time-row > * { flex: 1 1 100%; }
  .ptui-booking-hm select { width: 100%; }
  .ptui-booking-dialog-foot { align-items: stretch; flex-direction: column-reverse; }
  .ptui-booking-dialog-actions { width: 100%; }
  .ptui-booking-dialog-actions > button { flex: 1 1 0; }
  /* Tuan tren mobile: cot giu toi thieu 96px de doc duoc, ca luoi (head + than) rong theo noi dung
     va CUON NGANG ben trong .ptui-booking-tg — khong dat san px cung (gate v0.17.2), khong tran layout. */
  .ptui-booking-tg { overflow-x: auto; }
  .ptui-booking-tg.is-week .ptui-booking-tg-head, .ptui-booking-tg.is-week .ptui-booking-tg-body { grid-template-columns: 56px repeat(var(--ptui-booking-days, 7), minmax(96px, 1fr)); }
  .ptui-booking-tg.is-week .ptui-booking-tg-head, .ptui-booking-tg.is-week .ptui-booking-tg-scroll { width: max-content; min-width: 100%; }
  .ptui-booking .ptui-booking-tg-event-badge { display: none; }
}

/* =========================================================================
   v0.21.3 — CASCADE: lop noi --fixed phai thang luat goc (04/09/2026)
   0.21.2 dat z cho 4 lop `--fixed` o khoi v0.18 (dong ~1532) nhung luat goc
   `.ptui-multiselect-menu { z-index: var(--ptui-z-popover) }` dung SAU no (~1544) va
   cung specificity => luat sau thang => menu MultiSelect trong Modal VAN sau overlay
   (Dropdown/date khong bi vi luat goc cua chung dung TRUOC). Dat lai o CUOI file de
   chac chan thang; tests/v0213.test.mjs mo phong cascade last-wins de khong tai pham.
   ========================================================================= */
.ptui-menu--fixed,
.ptui-dt-pop--fixed,
.ptui-multiselect-menu--fixed,
.ptui-date-popover--fixed { z-index: var(--ptui-z-popover-floating); }

/* =========================================================================
   v0.22.3 — TABLE ROW EXPANSION: hàng chi tiết mở NGAY DƯỚI hàng của nó (13/09/2026)
   Vì sao ở thư viện: app từng phải TỰ render `<table>` chỉ để chèn được một hàng
   `colSpan` (bảng browser LinkedIn của MultiPeram) — mỗi app tự dựng lại anatomy là
   đúng thứ design system sinh ra để chặn. Thư viện lo ANATOMY (hàng + ô bọc, nền
   tách nhẹ, bỏ chiều cao 52px của ô bảng); app lo nút toggle (aria-expanded/
   aria-controls), nội dung và vùng cuộn ngang.
   LƯU Ý cho app có cột sticky: hàng chi tiết mang class `.ptui-row-detail` nên phải
   được miễn khỏi luật `td:last-child { position: sticky }` của app.
   ========================================================================= */
.ptui-table tbody tr.ptui-row-detail > td {
  height: auto;
  padding: 0;
  vertical-align: top;
}
/* Hàng app đang THAO TÁC (khác "đã chọn" về ngữ nghĩa, cùng nền accent để không đẻ ra ngôn ngữ thị giác thứ hai). */
.ptui-table tbody tr.ptui-row-active { background: var(--ptui-accent-soft); }
/* `.ptui-td-detail` la MOC on dinh cho app (gate "khong class .ptui-* mo coi" doi no phai co luat):
   nen tach nhe + hairline tren de hang chi tiet doc ra nhu mot bang rieng, khong lan vao hang du lieu. */
.ptui-table tbody tr.ptui-row-detail > td.ptui-td-detail {
  background: var(--ptui-bg-subtle);
  box-shadow: inset 0 1px 0 var(--ptui-border);
}

/* =========================================================================
   v0.22.4 — O TICK / RADIO: "DA CHON" THANG "HOVER", va "DA CHON + KHOA" van doc ra la da chon (23/09/2026)
   Loi cascade trong components.css: luat hover `.ptui-check:hover .ptui-check-input:not(:disabled) + .ptui-check-box`
   (specificity 0,5,0) thang luat checked `.ptui-check-input:checked + .ptui-check-box` (0,3,0). Ket qua do bang
   getComputedStyle: con tro dang nam tren o DA tick => nen accent-soft (xanh rat nhat) + dau tick TRANG = gan nhu vo
   hinh; tick va bo tick trong y het nhau cho toi khi rut chuot ra — nguoi dung thay "cung, click khong an lien".
   Cung ho: `:disabled` (0,3,0, dung sau) de nen xam len o DA chon => o khoa + da chon trong nhu CHUA chon.
   Sua o day (khong sua components.css): hover tren o da chon = accent-hover (dam hon 1 nac, dung phan hoi hover cua
   nut primary); da chon + khoa = accent mo theo --ptui-state-disabled-content (cung muc voi .ptui-btn:disabled).
   Ap cho ca Radio vi Radio dung chung anatomy `.ptui-check-box`. Khoa bang tests/v0224.test.mjs (mo phong cascade).
   ========================================================================= */
.ptui-check:hover .ptui-check-input:not(:disabled):checked + .ptui-check-box,
.ptui-check:hover .ptui-check-input:not(:disabled):indeterminate + .ptui-check-box {
  background: var(--ptui-accent-hover);
  border-color: var(--ptui-accent-hover);
}
.ptui-check-input:disabled:checked + .ptui-check-box,
.ptui-check-input:disabled:indeterminate + .ptui-check-box {
  background: var(--ptui-accent);
  border-color: var(--ptui-accent);
  color: var(--ptui-text-on-accent);
  opacity: var(--ptui-state-disabled-content);
}
