/* ============================================================================
   kythuat.work — design-system.css
   Bản 2.13.0 · 20/08/2026 · Lớp da cổng khách: token mép bề mặt, thang bo góc
   và thang độ cao đọc theo HỒ SƠ NGƯỜI ĐỌC chứ không cố định cho cả hệ. Cửa
   thợ và buồng lái giữ nguyên từng pixel. Trước đó: `KT.fmt.tuoiNgay` nói
   thành lời. Số 0 cấm in ra "0 ngày" — không ai nói thế, và nó rơi
   đúng vào trường hợp thường gặp nhất (khoản vừa thu sáng nay). Hỏng
   ở HAI cửa cùng lúc nên lời thuộc về hệ, không thuộc về app.

   Bản 2.12.3 · 20/08/2026 · cửa thợ về nền kem (trắng-trên-trắng làm thẻ
   tan vào nền); thêm `.kt-list__row--doc` cho hàng chỉ để đọc.
   Bản 2.12.2 · 20/08/2026 · thêm hình `kt-refresh` (nút lấy lại thôi mượn
   hình vòng quay của trạng thái đang tải).
   Bản 2.12.1 · 20/08/2026 · thanh phân bố tô được: `__fill` là <span> nằm
   trong `__track`, mà <span> là inline nên width và height bị bỏ qua sạch.
   Track thì thoát nạn nhờ nó là ô lưới (lưới tự chuyển con sang khối), còn
   fill thì không có gì cứu — nó dựng ra đủ, đúng lớp, và vẽ ra số không.
   Chính tệp tham chiếu của hệ cũng viết <span>, tức bản mẫu vẽ ra bar rỗng.
   Bản 2.12.0 · 19/08/2026 · dòng thời gian có chỗ đứng: xong, đang, dừng,
   chờ — cùng dữ liệu `dungHanhTrinh()` mà hệ mới chỉ vẽ được theo chiều ngang.
   Bản 2.11.0 · 19/08/2026 · biểu đồ: cột và chấm bằng HTML, trục giá trị,
   lưới ngang, sắc độ cho chuỗi, vạch ngưỡng thật trên thanh xếp hạng
   Bản 2.10.0 · 19/08/2026 · họ nhận việc: chờ, quá hạn, đã nhận, đời cũ
   Bản 2.9.1 · 19/08/2026 · rãnh giữa hai chặng lớn hơn rãnh trong một chặng
   Bản 2.9.0 · 19/08/2026 · chú giải ba tầng: thẻ cửa, chữ có nghĩa, vị trí tự khai vai
   Bản 2.8.0 · 19/08/2026 · thẻ trần tự giữ lề; nhóm phân đoạn trong ô lấp đầy ô
   Bản 2.5.0 · 18/08/2026 · hướng nhận diện C (navy trên nền kem, cam dùng dè)
   Bản 2.2.0 hoà giải với D1, xem VENH.md. Chỉ THÊM .kt-badge--lobby;
   không sửa một token nào, không sửa một thành phần nào của bản 2.1.0.

   KIẾN TRÚC BA TẦNG
     Tầng 1, nguyên thuỷ  --kt-<ramp>-<step>      giá trị thô, không dùng trực tiếp
     Tầng 2, ngữ nghĩa    --kt-<nhóm>-<vai>       vai trò, đây là tầng để dùng
     Tầng 3, thành phần   --kt-<comp>-<thuộc tính> chỉ thành phần đó đọc

   Quy tắc: markup và màn hình CHỈ được đọc tầng 2 và tầng 3. Không màn nào
   đọc tầng 1, không màn nào gõ mã màu.

   Thang màu sinh trong OKLCH trên một trục sáng dùng chung, nên cùng một bậc
   của mọi thang có cùng sức nặng thị giác. Bậc neo (*) là màu thật trong logo.
   Tự chứa: không @import, không CDN, không thư viện ngoài.
   ==========================================================================*/

/* --- Phông ----------------------------------------------------------------
   Be Vietnam Pro, chở đủ dấu tiếng Việt kể cả dấu chồng. Đặt bốn tệp woff2
   vào /fonts/. Chưa có tệp thì rơi về phông hệ điều hành, không gọi mạng.  */
@font-face { font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Be Vietnam Pro Regular"), local("BeVietnamPro-Regular"), url("fonts/BeVietnamPro-Regular.woff2") format("woff2"); }
@font-face { font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 500; font-display: swap; src: local("Be Vietnam Pro Medium"), local("BeVietnamPro-Medium"), url("fonts/BeVietnamPro-Medium.woff2") format("woff2"); }
@font-face { font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 600; font-display: swap; src: local("Be Vietnam Pro SemiBold"), local("BeVietnamPro-SemiBold"), url("fonts/BeVietnamPro-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 700; font-display: swap; src: local("Be Vietnam Pro Bold"), local("BeVietnamPro-Bold"), url("fonts/BeVietnamPro-Bold.woff2") format("woff2"); }

/* ==========================================================================
   TẦNG 1 — NGUYÊN THUỶ
   ==========================================================================*/
:root {
  /* brand, neo 900 = #001E52 */
  --kt-brand-50: #F7FAFF;  --kt-brand-100: #EAF2FF; --kt-brand-200: #D3E4FF; --kt-brand-300: #B7D1FB;
  --kt-brand-400: #95B7EE; --kt-brand-500: #7399D7; --kt-brand-600: #577CB8; --kt-brand-700: #3C5D93;
  --kt-brand-800: #27426D; --kt-brand-900: #001E52; --kt-brand-950: #0A1931;

  /* accent, neo 500 = #EF7C00 */
  --kt-accent-50: #FFF9F4;  --kt-accent-100: #FFEEE3; --kt-accent-200: #FFDBC3; --kt-accent-300: #FFC095;
  --kt-accent-400: #FE994E; --kt-accent-500: #EF7C00; --kt-accent-600: #BB6000; --kt-accent-700: #8F4700;
  --kt-accent-800: #673200; --kt-accent-900: #461F00; --kt-accent-950: #2C1100;

  /* cream, neo 200 = #F5E9C3; bậc 75 là nền trang của hướng C */
  --kt-cream-50: #FBFAF6;  --kt-cream-75: #FBF7EC;  --kt-cream-100: #F4F2E9; --kt-cream-200: #F5E9C3;
  --kt-cream-300: #D7CFB8; --kt-cream-400: #BFB696; --kt-cream-500: #A39874; --kt-cream-600: #867B59;
  --kt-cream-700: #675D3E; --kt-cream-800: #4A4229; --kt-cream-900: #312B18; --kt-cream-950: #1E190B;

  /* slate, neo 800 = #3F4A5E */
  --kt-slate-50: #F8FAFD;  --kt-slate-100: #EFF2F7; --kt-slate-200: #DDE3EE; --kt-slate-300: #C7D0DF;
  --kt-slate-400: #ABB6CB; --kt-slate-500: #8C99B0; --kt-slate-600: #707C92; --kt-slate-700: #535E72;
  --kt-slate-800: #3F4A5E; --kt-slate-900: #252B37; --kt-slate-950: #151A22;

  --kt-success-50: #F3FDF7;  --kt-success-100: #E5F7EB; --kt-success-200: #CAEDD7; --kt-success-300: #A8DEBD;
  --kt-success-400: #7FC99E; --kt-success-500: #54AD7D; --kt-success-600: #349061; --kt-success-700: #16794C;
  --kt-success-800: #00502F; --kt-success-900: #00351D; --kt-success-950: #002010;

  --kt-warning-50: #FFF9F3;  --kt-warning-100: #FFEEE0; --kt-warning-200: #FFDCBE; --kt-warning-300: #F8C496;
  --kt-warning-400: #EAA567; --kt-warning-500: #D18435; --kt-warning-600: #B4690E; --kt-warning-700: #884D00;
  --kt-warning-800: #623600; --kt-warning-900: #422200; --kt-warning-950: #291300;

  --kt-danger-50: #FFF8F7;  --kt-danger-100: #FFEDEA; --kt-danger-200: #FFD9D3; --kt-danger-300: #FFBCB3;
  --kt-danger-400: #FF9387; --kt-danger-500: #EE685D; --kt-danger-600: #CC4941; --kt-danger-700: #A42C27;
  --kt-danger-800: #90000A; --kt-danger-900: #550909; --kt-danger-950: #370202;

  --kt-info-50: #F6FBFF;  --kt-info-100: #E7F3FF; --kt-info-200: #CDE6FF; --kt-info-300: #ACD4FB;
  --kt-info-400: #86BBEE; --kt-info-500: #5F9ED7; --kt-info-600: #4281B8; --kt-info-700: #1E5F94;
  --kt-info-800: #14456D; --kt-info-900: #072D4B; --kt-info-950: #021B31;

  --kt-white: #FFFFFF;
  --kt-black: #000000;

  /* Nguyên thuỷ phi màu */
  --kt-unit: 4px;
  --kt-font-sans: "Be Vietnam Pro", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", Arial, sans-serif;
  /* Mã đơn, mã khách, mã giao dịch: phông đều nét thì mắt so được từng ký tự.
     Chỗ nào in mã ra cho người ta ĐỐI CHIẾU thì phải dùng nó.            */
  --kt-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, "Roboto Mono", monospace;
  --kt-weight-regular: 400; --kt-weight-medium: 500; --kt-weight-semibold: 600; --kt-weight-bold: 700;
  --kt-tracking-tight: -0.011em; --kt-tracking-normal: 0em; --kt-tracking-wide: 0.02em; --kt-tracking-caps: 0.12em;
  --kt-leading-tight: 1.2; --kt-leading-snug: 1.35; --kt-leading-normal: 1.55; --kt-leading-loose: 1.7;
}

/* ==========================================================================
   TẦNG 2 — NGỮ NGHĨA, CHỦ ĐỀ SÁNG
   Số trong chú thích là tương phản đã đo theo WCAG 2.1.
   ==========================================================================*/
:root {
  color-scheme: light;

  /* Nền và bề mặt */
  --kt-bg-canvas: var(--kt-cream-75);
  --kt-bg-canvas-plain: var(--kt-white);
  --kt-bg-subtle: var(--kt-cream-100);
  --kt-bg-inverse: var(--kt-brand-900);
  --kt-surface: var(--kt-white);
  --kt-surface-sunken: var(--kt-cream-100);
  --kt-surface-accent: var(--kt-cream-200);
  --kt-surface-inverse: var(--kt-brand-900);
  --kt-surface-disabled: var(--kt-slate-100);
  --kt-surface-overlay: var(--kt-white);

  /* Chữ */
  --kt-text-primary: var(--kt-brand-900);      /* 15.38 trên nền trang */
  --kt-text-secondary: var(--kt-slate-800);    /*  8.55 */
  --kt-text-tertiary: var(--kt-slate-700);     /*  6.26 */
  --kt-text-disabled: var(--kt-slate-500);     /*  2.75, miễn ngưỡng theo WCAG 1.4.3 */
  --kt-text-placeholder: var(--kt-slate-700);  /*  6.26 */
  --kt-text-on-inverse: var(--kt-white);       /* 16.06 trên navy 900 */
  --kt-text-on-inverse-muted: var(--kt-brand-300); /* 8.02 trên navy 900 */
  --kt-text-on-accent: var(--kt-white);         /* 16.06 trên nền nút navy */
  --kt-text-link: var(--kt-brand-800);          /*  9.64 */
  --kt-text-link-hover: var(--kt-brand-900);    /* 15.00 */
  --kt-text-brand: var(--kt-brand-900);
  --kt-text-accent: var(--kt-accent-700);

  /* Viền */
  --kt-border-subtle: var(--kt-cream-300);
  --kt-border-default: var(--kt-slate-300);
  --kt-border-strong: var(--kt-brand-900);
  --kt-border-accent: var(--kt-accent-600);
  --kt-border-focus: var(--kt-accent-600);
  --kt-border-error: var(--kt-danger-800);

  /* Hành động. Nền nút chính là navy thương hiệu, chữ trắng đạt 16.06.
     Cam sáng 500 không bao giờ làm nền cho chữ: nó là màu chỉ báo, dùng cho vạch
     tiến trình, gạch tab đang chọn, đèn trạng thái, viền dòng đang chọn. */
  --kt-action-fill: var(--kt-brand-900);
  --kt-action-fill-hover: var(--kt-brand-800);
  --kt-action-fill-active: var(--kt-brand-950);
  --kt-action-indicator: var(--kt-accent-500);
  --kt-action-quiet-fg: var(--kt-brand-900);

  /* Ngữ nghĩa trạng thái: fill có chữ trắng, fg là chữ trên nền nhạt */
  --kt-success-fill: var(--kt-success-700); --kt-success-fg: var(--kt-success-800); --kt-success-bg: var(--kt-success-100); --kt-success-border: var(--kt-success-700);
  --kt-warning-fill: var(--kt-warning-600); --kt-warning-fg: var(--kt-warning-700); --kt-warning-bg: var(--kt-warning-100); --kt-warning-border: var(--kt-warning-600);
  --kt-danger-fill: var(--kt-danger-800);   --kt-danger-fg: var(--kt-danger-800);   --kt-danger-bg: var(--kt-danger-100);   --kt-danger-border: var(--kt-danger-800);
  --kt-info-fill: var(--kt-info-700);       --kt-info-fg: var(--kt-info-800);       --kt-info-bg: var(--kt-info-100);       --kt-info-border: var(--kt-info-700);
  --kt-neutral-fill: var(--kt-slate-800);   --kt-neutral-fg: var(--kt-slate-800);   --kt-neutral-bg: var(--kt-slate-100);   --kt-neutral-border: var(--kt-slate-400);

  /* Lớp trạng thái. Một mô hình duy nhất cho mọi thành phần bấm được:
     phủ mực lên bề mặt theo tỉ lệ, không đặt màu riêng cho từng nút. */
  --kt-state-ink: var(--kt-brand-900);
  --kt-state-hover: 8%;
  --kt-state-pressed: 14%;
  --kt-state-selected: 10%;
  --kt-state-disabled-opacity: 0.42;

  /* Lớp che, ánh sáng chạy trên khung xương */
  --kt-scrim: color-mix(in srgb, var(--kt-brand-950) 62%, transparent);
  --kt-sheen: color-mix(in srgb, var(--kt-white) 72%, transparent);

  /* Đổ bóng, pha theo mực nền nên không xám bẩn */
  --kt-shadow-xs: 0 1px 0 color-mix(in srgb, var(--kt-brand-950) 10%, transparent);
  --kt-shadow-sm: 0 1px 2px color-mix(in srgb, var(--kt-brand-950) 12%, transparent);
  --kt-shadow-md: 0 4px 14px color-mix(in srgb, var(--kt-brand-950) 14%, transparent);
  --kt-shadow-lg: 0 12px 32px color-mix(in srgb, var(--kt-brand-950) 20%, transparent);
  --kt-shadow-sheet: 0 -8px 28px color-mix(in srgb, var(--kt-brand-950) 20%, transparent);
}

/* ==========================================================================
   TẦNG 2 — CHỮ, KHOẢNG CÁCH, HÌNH HỌC, CHUYỂN ĐỘNG, TẦNG LỚP
   ==========================================================================*/
:root {
  /* Vai chữ. Mỗi vai gói đủ cỡ, độ cao dòng, cân nặng, giãn chữ. */
  --kt-type-display-size: 34px;   --kt-type-display-leading: var(--kt-leading-tight); --kt-type-display-weight: var(--kt-weight-bold);     --kt-type-display-tracking: var(--kt-tracking-tight);
  --kt-type-headline-size: 26px;  --kt-type-headline-leading: var(--kt-leading-tight); --kt-type-headline-weight: var(--kt-weight-bold);   --kt-type-headline-tracking: var(--kt-tracking-tight);
  --kt-type-title-size: 20px;     --kt-type-title-leading: var(--kt-leading-tight);   --kt-type-title-weight: var(--kt-weight-bold);      --kt-type-title-tracking: var(--kt-tracking-normal);
  --kt-type-subtitle-size: 17px;  --kt-type-subtitle-leading: var(--kt-leading-snug); --kt-type-subtitle-weight: var(--kt-weight-semibold); --kt-type-subtitle-tracking: var(--kt-tracking-normal);
  --kt-type-body-size: 15px;      --kt-type-body-leading: var(--kt-leading-normal);   --kt-type-body-weight: var(--kt-weight-regular);    --kt-type-body-tracking: var(--kt-tracking-normal);
  --kt-type-label-size: 13px;     --kt-type-label-leading: var(--kt-leading-snug);    --kt-type-label-weight: var(--kt-weight-medium);    --kt-type-label-tracking: var(--kt-tracking-normal);
  --kt-type-caption-size: 12px;   --kt-type-caption-leading: var(--kt-leading-snug);  --kt-type-caption-weight: var(--kt-weight-regular); --kt-type-caption-tracking: var(--kt-tracking-normal);
  --kt-type-overline-size: 11px;  --kt-type-overline-leading: var(--kt-leading-snug); --kt-type-overline-weight: var(--kt-weight-bold);   --kt-type-overline-tracking: var(--kt-tracking-caps);

  /* Khoảng cách, bội của --kt-unit */
  --kt-space-0: 0px;  --kt-space-1: 4px;  --kt-space-2: 8px;  --kt-space-3: 12px; --kt-space-4: 16px;
  --kt-space-5: 20px; --kt-space-6: 24px; --kt-space-7: 28px; --kt-space-8: 32px; --kt-space-10: 40px;
  --kt-space-12: 48px; --kt-space-16: 64px; --kt-space-20: 80px;

  /* Hình học */
  --kt-radius-none: 0px; --kt-radius-sm: 0px; --kt-radius-md: 0px; --kt-radius-lg: 0px; --kt-radius-full: 999px;
  --kt-radius-sheet: 0px; --kt-radius-pill: 0px;

  /* MÉP CỦA MỘT BỀ MẶT.
     Thẻ, đơn và dòng dịch vụ đều tự vẽ `border: 2px solid navy`, nên muốn
     một cổng nhẹ tay hơn thì phải sửa ba chỗ và nhớ mãi là có ba chỗ. Ba
     token này gom câu hỏi đó về một nơi: mép dày bao nhiêu, màu gì, và bề
     mặt có nổi lên khỏi nền không. Mặc định giữ ĐÚNG hình cũ, nên cửa thợ
     và buồng lái không lệch một pixel. Cổng khách ghi đè ở §lớp da. */
  --kt-surface-edge-w: var(--kt-border-w);
  --kt-surface-edge: var(--kt-border-strong);
  --kt-surface-lift: none;
  --kt-border-w-hair: 1px; --kt-border-w: 2px; --kt-border-w-thick: 3px;
  --kt-focus-ring-w: 3px; --kt-focus-ring-offset: 2px;

  /* Tầng lớp */
  --kt-z-base: 0; --kt-z-sticky: 100; --kt-z-nav: 200; --kt-z-scrim: 300; --kt-z-drawer: 400;
  --kt-z-sheet: 500; --kt-z-dialog: 600; --kt-z-popover: 700; --kt-z-toast: 800; --kt-z-tooltip: 900;

  /* Chuyển động */
  --kt-dur-instant: 80ms; --kt-dur-fast: 120ms; --kt-dur-normal: 180ms; --kt-dur-slow: 240ms; --kt-dur-slower: 320ms;
  --kt-ease-standard: cubic-bezier(0.2, 0, 0.2, 1);
  --kt-ease-decelerate: cubic-bezier(0, 0, 0.2, 1);
  --kt-ease-accelerate: cubic-bezier(0.4, 0, 1, 1);
  --kt-transition-color: color var(--kt-dur-fast) var(--kt-ease-standard), background-color var(--kt-dur-fast) var(--kt-ease-standard), border-color var(--kt-dur-fast) var(--kt-ease-standard);

  /* Mốc màn hình và bề rộng vùng đọc */
  --kt-bp-sm: 390px; --kt-bp-md: 768px; --kt-bp-lg: 1024px; --kt-bp-xl: 1440px;
  --kt-measure: 68ch;
}

/* ==========================================================================
   TẦNG 3 — TOKEN THÀNH PHẦN THEO MẬT ĐỘ
   Ba hồ sơ mật độ. Chỉ đổi kích thước, không đổi màu thương hiệu.
     touch       cửa thợ, một tay, ngoài nắng, tay bẩn
     comfortable cửa khách, thoáng và trấn an
     compact     buồng lái, nén và quét nhanh
   .kt-mode-* là bút danh cũ, giữ lại để mã đang chạy không vỡ.
   ==========================================================================*/
:root, [data-kt-density="comfortable"], .kt-mode-khach {
  --kt-control-h: 48px; --kt-control-h-sm: 40px; --kt-control-h-lg: 56px;
  --kt-control-px: var(--kt-space-4);
  --kt-tap-min: 48px;
  --kt-gap: var(--kt-space-4);
  --kt-pad: var(--kt-space-4);
  --kt-pad-tight: var(--kt-space-3);
  --kt-font-ui: var(--kt-type-body-size);
  --kt-font-ui-strong: var(--kt-type-subtitle-size);
  --kt-row-h: 52px;
  --kt-icon-size: 20px;
  --kt-choice-size: 24px;
  --kt-choice-gap: var(--kt-space-3);
  --kt-switch-w: 52px; --kt-switch-h: 28px;
}
[data-kt-density="touch"], .kt-mode-ktv {
  --kt-control-h: 56px; --kt-control-h-sm: 48px; --kt-control-h-lg: 64px;
  --kt-control-px: var(--kt-space-5);
  --kt-tap-min: 56px;
  --kt-gap: var(--kt-space-5);
  --kt-pad: var(--kt-space-5);
  --kt-pad-tight: var(--kt-space-4);
  --kt-font-ui: var(--kt-type-subtitle-size);
  --kt-font-ui-strong: var(--kt-type-title-size);
  --kt-row-h: 64px;
  --kt-icon-size: 24px;
  --kt-choice-size: 28px;
  --kt-choice-gap: var(--kt-space-4);
  --kt-switch-w: 60px; --kt-switch-h: 32px;
}
[data-kt-density="compact"], .kt-mode-admin {
  --kt-control-h: 32px; --kt-control-h-sm: 28px; --kt-control-h-lg: 40px;
  --kt-control-px: var(--kt-space-3);
  --kt-tap-min: 32px;
  --kt-gap: var(--kt-space-3);
  --kt-pad: var(--kt-space-3);
  --kt-pad-tight: var(--kt-space-2);
  --kt-font-ui: 14px;
  --kt-font-ui-strong: var(--kt-type-body-size);
  --kt-row-h: 38px;
  --kt-icon-size: 18px;
  --kt-choice-size: 18px;
  --kt-choice-gap: var(--kt-space-2);
  --kt-switch-w: 40px; --kt-switch-h: 22px;
}
/* Buồng lái dùng nền trắng để tương phản tối đa: nó là bảng số dày đặc,
   và ở đó mọi thứ đều nằm trong bảng có viền nên nền không phải gánh việc
   tách khối.

   CỬA THỢ ĐÃ TRẢ VỀ NỀN KEM (20/08). Lý do cũ — "tương phản tối đa" —
   nghe đúng mà thực tế ngược lại: bề mặt thẻ của hệ LÀ màu trắng, nên
   trắng-trên-trắng làm mọi cái thẻ tan vào nền và cả màn dẹt thành một tờ
   giấy. Tương phản là chuyện GIỮA hai lớp, không phải chuyện của một màu
   đứng một mình. Nền kem `--kt-cream-75` với bề mặt trắng chính là cặp
   mà hệ đã cân sẵn. */
.kt-mode-admin { --kt-bg-canvas: var(--kt-bg-canvas-plain); }

/* ==========================================================================
   LỚP DA CỔNG KHÁCH — .kt-mode-khach
   Đổi 20/08/2026, anh Vũ quyết. Hiến pháp §5b.

   `.kt-mode-khach` từng chỉ là bút danh cũ của hồ sơ `comfortable`. Nay nó
   là CÔNG TẮC LỚP DA, và hai thứ đó cố ý tách nhau: mật độ trả lời câu
   "ngón tay to bao nhiêu", lớp da trả lời câu "người đọc màn này là ai".
   Một công cụ nội bộ vẫn có thể muốn mật độ thoáng mà không muốn hình dáng
   của một sản phẩm tiêu dùng.

   Vì sao cổng khách khác hai cổng kia: thợ và buồng lái là CÔNG CỤ LÀM
   VIỆC, và với chúng góc vuông cùng viền navy 2px đọc ra là nghiêm túc,
   dày đặc thông tin, không phí một điểm ảnh nào. Cư dân thì không phải
   người vận hành. Với họ, cùng thứ hình khối ấy đọc ra là BIỂU MẪU HÀNH
   CHÍNH — thứ người ta phải điền, không phải thứ người ta chọn mua.

   Khối này CHỈ đụng hình khối và độ cao. Nó không đổi một màu thương hiệu
   nào, không đổi một khoá nào, không đổi một chữ nào. Ba cổng vẫn là một
   thương hiệu, và ai cũng nhận ra điều đó ngay từ màu.
   ==========================================================================*/
.kt-mode-khach {
  /* Hình khối. Bậc chọn theo VAI của bề mặt, không theo cỡ của nó:
     ô điều khiển 8, thứ bấm được 12, tấm chứa nội dung 16, tấm trượt 20.
     Đi quá 20 thì bắt đầu đọc ra như đồ chơi, và niềm tin là thứ hệ này
     bán trước cả dịch vụ. */
  --kt-radius-sm: 8px;
  --kt-radius-md: 12px;
  --kt-radius-lg: 16px;
  --kt-radius-sheet: 20px;
  --kt-radius-pill: var(--kt-radius-full);

  /* Độ cao HAI LỚP: một bóng tiếp xúc rất gần và đặc, một bóng môi trường
     xa và loãng. Bóng một lớp là thứ làm giao diện đọc ra rẻ tiền — nó
     không giống cách ánh sáng thật rơi lên vật thật. Vẫn pha theo mực nền
     navy chứ không pha xám, nên bóng không bao giờ bẩn trên nền kem. */
  --kt-shadow-xs: 0 1px 2px color-mix(in srgb, var(--kt-brand-950) 6%, transparent);
  --kt-shadow-sm: 0 1px 2px color-mix(in srgb, var(--kt-brand-950) 6%, transparent),
                  0 2px 8px color-mix(in srgb, var(--kt-brand-950) 6%, transparent);
  --kt-shadow-md: 0 2px 4px color-mix(in srgb, var(--kt-brand-950) 6%, transparent),
                  0 8px 24px color-mix(in srgb, var(--kt-brand-950) 10%, transparent);
  --kt-shadow-lg: 0 4px 8px color-mix(in srgb, var(--kt-brand-950) 8%, transparent),
                  0 20px 48px color-mix(in srgb, var(--kt-brand-950) 14%, transparent);
  --kt-shadow-sheet: 0 -2px 8px color-mix(in srgb, var(--kt-brand-950) 8%, transparent),
                     0 -16px 48px color-mix(in srgb, var(--kt-brand-950) 16%, transparent);

  /* Mép bề mặt. Viền navy 2px thôi gánh việc tách khối, độ cao gánh thay.
     Giữ lại một sợi tóc màu kem đậm vì màn hình rẻ và chế độ tương phản
     cao đều làm bóng biến mất, và lúc đó thẻ vẫn phải còn là thẻ. */
  --kt-surface-edge-w: var(--kt-border-w-hair);
  --kt-surface-edge: var(--kt-border-subtle);
  --kt-surface-lift: var(--kt-shadow-sm);
}

/* Tương phản cao: bóng không tồn tại, nên mép phải quay lại gánh việc. */
@media (prefers-contrast: more) {
  .kt-mode-khach {
    --kt-surface-edge-w: var(--kt-border-w);
    --kt-surface-edge: var(--kt-border-strong);
    --kt-surface-lift: none;
  }
}

/* ==========================================================================
   NỀN CHUNG
   ==========================================================================*/
.kt-app {
  margin: 0;
  font-family: var(--kt-font-sans);
  font-size: var(--kt-type-body-size);
  line-height: var(--kt-type-body-leading);
  color: var(--kt-text-primary);
  background: var(--kt-bg-canvas);
  -webkit-text-size-adjust: 100%;
  text-wrap: pretty;
  font-variant-numeric: proportional-nums;
}
.kt-app *, .kt-app *::before, .kt-app *::after { box-sizing: border-box; }
.kt-app h1, .kt-app h2, .kt-app h3, .kt-app h4 { margin: 0; font-weight: var(--kt-weight-bold); line-height: var(--kt-leading-tight); letter-spacing: var(--kt-tracking-tight); }
.kt-app h1 { font-size: var(--kt-type-headline-size); }
.kt-app h2 { font-size: var(--kt-type-title-size); }
.kt-app h3 { font-size: var(--kt-type-subtitle-size); }
.kt-app p { margin: 0; max-width: var(--kt-measure); }
.kt-app a, .kt-link { color: var(--kt-text-link); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.kt-app a:hover, .kt-link:hover { color: var(--kt-text-link-hover); text-decoration-thickness: 2px; }
.kt-app ::selection { background: var(--kt-accent-200); color: var(--kt-brand-900); }
.kt-app :focus-visible { outline: var(--kt-focus-ring-w) solid var(--kt-border-focus); outline-offset: var(--kt-focus-ring-offset); }
.kt-app [hidden] { display: none !important; }

/* Vai chữ dùng được như lớp tiện ích. Đặt trong .kt-app để thắng kiểu thẻ mặc định. */
.kt-app .kt-display  { font-size: var(--kt-type-display-size);  line-height: var(--kt-type-display-leading);  font-weight: var(--kt-type-display-weight);  letter-spacing: var(--kt-type-display-tracking); }
.kt-app .kt-headline { font-size: var(--kt-type-headline-size); line-height: var(--kt-type-headline-leading); font-weight: var(--kt-type-headline-weight); letter-spacing: var(--kt-type-headline-tracking); }
.kt-app .kt-title    { font-size: var(--kt-type-title-size);    line-height: var(--kt-type-title-leading);    font-weight: var(--kt-type-title-weight); }
.kt-app .kt-subtitle { font-size: var(--kt-type-subtitle-size); line-height: var(--kt-type-subtitle-leading); font-weight: var(--kt-type-subtitle-weight); }
.kt-app .kt-body     { font-size: var(--kt-type-body-size);     line-height: var(--kt-type-body-leading); }
.kt-app .kt-label-text { font-size: var(--kt-type-label-size);  line-height: var(--kt-type-label-leading);  font-weight: var(--kt-type-label-weight); color: var(--kt-text-secondary); }
.kt-app .kt-caption  { font-size: var(--kt-type-caption-size);  line-height: var(--kt-type-caption-leading); color: var(--kt-text-tertiary); }
.kt-app .kt-eyebrow, .kt-app .kt-overline { font-size: var(--kt-type-overline-size); line-height: var(--kt-type-overline-leading); font-weight: var(--kt-type-overline-weight); letter-spacing: var(--kt-type-overline-tracking); text-transform: uppercase; color: var(--kt-text-tertiary); }

/* Bố cục cơ bản */
.kt-stack { display: flex; flex-direction: column; gap: var(--kt-gap); }
.kt-row { display: flex; align-items: center; gap: var(--kt-space-2); }
.kt-between { display: flex; align-items: center; justify-content: space-between; gap: var(--kt-space-2); }
.kt-rule { height: 0; border: 0; border-top: var(--kt-border-w) solid var(--kt-border-strong); margin: 0; }
.kt-divider { height: 0; border: 0; border-top: var(--kt-border-w-hair) solid var(--kt-border-subtle); margin: 0; }
.kt-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.kt-skiplink { position: absolute; left: -9999px; top: 0; z-index: var(--kt-z-tooltip); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); padding: var(--kt-space-3) var(--kt-space-4); font-weight: var(--kt-weight-bold); }
.kt-skiplink:focus { left: var(--kt-space-2); top: var(--kt-space-2); }

/* Biểu tượng, sprite icons.svg trong repo.
   Đầu nét CẮT PHẲNG và góc NHỌN, không bo. Hệ này bo góc bằng 0 ở mọi bậc,
   nên biểu tượng đầu tròn góc tròn tuy lấy đúng nguồn vẫn đứng lệch khỏi
   phần còn lại của màn. `stroke-miterlimit: 2` cắt gai ở những góc quá nhọn
   (tia sét, ngôi sao) thành vát, chứ mặc định 4 thì gai chọc ra ngoài khung.
   BẪY: sáu hình vẽ CHẤM bằng thủ thuật đoạn dài 0,01 và trông thấy được chỉ
   nhờ đầu nét tròn. Đổi sang `butt` là chấm biến mất sạch, không lỗi, không
   log · nên chúng khai `stroke-linecap="square"` ngay trên path trong sprite
   (thuộc tính trên chính phần tử thắng giá trị kế thừa từ đây), và ra đúng
   ô vuông 2×2, hợp hệ hơn cả chấm tròn cũ. */
.kt-icon { width: var(--kt-icon-size); height: var(--kt-icon-size); flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 2; }
.kt-icon--sm { width: 16px; height: 16px; }
.kt-icon--lg { width: 28px; height: 28px; }
.kt-icon--xl { width: 36px; height: 36px; }
.kt-icon-tile { border-radius: var(--kt-radius-md); display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: none; background: var(--kt-surface-accent); color: var(--kt-brand-900); border: var(--kt-border-w) solid var(--kt-border-strong); }
.kt-spin { animation: kt-spin 900ms linear infinite; }
@keyframes kt-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   HÀNH ĐỘNG — nút, nhóm nút, nút biểu tượng
   Nút luôn: nền đầy hoặc viền 2px mực, nhãn 700, kèm biểu tượng, không có
   nhãn nổi phía trên. Ô nhập luôn: nền lõm, gạch chân dày, có nhãn phía trên.
   Hai họ này không được nhìn giống nhau. Xem mục Ô NHẬP.
   ==========================================================================*/
.kt-btn {
  --kt-btn-h: var(--kt-control-h);
  position: relative;
  display: inline-flex; align-items: center; justify-content: flex-start; gap: var(--kt-space-2);
  min-height: var(--kt-btn-h); min-width: var(--kt-btn-h);
  padding: var(--kt-space-2) var(--kt-control-px);
  font: inherit; font-size: var(--kt-font-ui); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-wide);
  text-align: left; text-decoration: none; white-space: normal; text-wrap: balance;
  border: var(--kt-border-w) solid transparent; border-radius: var(--kt-radius-md);
  cursor: pointer; transition: var(--kt-transition-color);
  isolation: isolate;
}
/* Lớp trạng thái dùng chung, một cơ chế cho mọi biến thể */
.kt-btn::after { content: ""; position: absolute; inset: 0; background: var(--kt-state-ink); opacity: 0; transition: opacity var(--kt-dur-fast) var(--kt-ease-standard); z-index: -1; }
.kt-btn:hover::after { opacity: calc(var(--kt-state-hover) / 100%); }
.kt-btn:active::after { opacity: calc(var(--kt-state-pressed) / 100%); }
.kt-btn--primary { background: var(--kt-action-fill); color: var(--kt-text-on-accent); border-color: var(--kt-action-fill); --kt-state-ink: var(--kt-black); }
.kt-btn--secondary { background: var(--kt-surface); color: var(--kt-action-quiet-fg); border-color: var(--kt-border-strong); }
.kt-btn--ghost { background: transparent; color: var(--kt-action-quiet-fg); border-color: transparent; }
.kt-btn--danger { background: var(--kt-danger-fill); color: var(--kt-white); border-color: var(--kt-danger-fill); --kt-state-ink: var(--kt-black); }
.kt-btn--inverse { background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); border-color: var(--kt-surface-inverse); --kt-state-ink: var(--kt-white); }
.kt-btn--sm { --kt-btn-h: var(--kt-control-h-sm); font-size: var(--kt-type-label-size); padding: 0 var(--kt-space-3); }
.kt-btn--lg { --kt-btn-h: var(--kt-control-h-lg); font-size: var(--kt-font-ui-strong); }
.kt-btn--block { display: flex; width: 100%; }
.kt-btn--icon { padding: 0; justify-content: center; }
.kt-btn--center { justify-content: center; text-align: center; }
.kt-btn[disabled], .kt-btn[aria-disabled="true"] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; }
.kt-btn[disabled]::after, .kt-btn[aria-disabled="true"]::after { display: none; }
.kt-btn.is-loading { color: transparent; pointer-events: none; }
.kt-btn.is-loading::before {
  content: ""; position: absolute; inset: 0; margin: auto; width: 20px; height: 20px;
  border-radius: var(--kt-radius-full);
  border: var(--kt-border-w) solid var(--kt-text-on-accent); border-top-color: transparent;
  animation: kt-spin 700ms linear infinite;
}
.kt-btn--secondary.is-loading::before, .kt-btn--ghost.is-loading::before { border-color: var(--kt-action-quiet-fg); border-top-color: transparent; }
.kt-btn__trailing { margin-left: auto; }

.kt-btn-group { display: inline-flex; }
.kt-btn-group > .kt-btn { border-radius: 0; margin-left: calc(var(--kt-border-w) * -1); }
.kt-btn-group > .kt-btn:first-child { margin-left: 0; }
.kt-btn-group > .kt-btn:focus-visible { z-index: 1; }

/* Gợi ý bàn phím */
.kt-kbd { border-radius: var(--kt-radius-sm); font-family: ui-monospace, monospace; font-size: var(--kt-type-caption-size); padding: 1px var(--kt-space-1); border: var(--kt-border-w-hair) solid var(--kt-border-default); background: var(--kt-surface-sunken); color: var(--kt-text-secondary); }

/* ==========================================================================
   Ô NHẬP VÀ LỰA CHỌN
   Hình thức riêng: nền lõm, viền mảnh, gạch chân dày ba pixel. Không bao giờ
   trông giống nút.
   ==========================================================================*/
.kt-form { display: flex; flex-direction: column; gap: var(--kt-gap); }
.kt-fieldset { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--kt-pad-tight); }
.kt-legend { padding: 0; font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; color: var(--kt-text-tertiary); }
.kt-field { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-field > label { font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); color: var(--kt-text-secondary); }
.kt-required { color: var(--kt-danger-fg); }
.kt-input, .kt-select, .kt-textarea {
  font: inherit; font-size: var(--kt-font-ui); color: var(--kt-text-primary);
  min-height: var(--kt-control-h); width: 100%;
  padding: var(--kt-space-2) var(--kt-pad-tight);
  background: var(--kt-surface-sunken);
  border: var(--kt-border-w-hair) solid var(--kt-border-default);
  border-bottom: var(--kt-border-w-thick) solid var(--kt-slate-400);
  border-radius: var(--kt-radius-md);
  transition: var(--kt-transition-color);
}
.kt-textarea { min-height: calc(var(--kt-control-h) * 2); resize: vertical; }
.kt-input:hover, .kt-select:hover, .kt-textarea:hover { border-bottom-color: var(--kt-brand-700); }
.kt-input:focus, .kt-select:focus, .kt-textarea:focus { background: var(--kt-surface); border-bottom-color: var(--kt-brand-900); outline: none; }
.kt-input:focus-visible, .kt-select:focus-visible, .kt-textarea:focus-visible { outline: var(--kt-focus-ring-w) solid var(--kt-border-focus); outline-offset: var(--kt-focus-ring-offset); }
.kt-input::placeholder, .kt-textarea::placeholder { color: var(--kt-text-placeholder); }
.kt-input[disabled], .kt-select[disabled], .kt-textarea[disabled] { background: var(--kt-surface-disabled); color: var(--kt-text-disabled); border-bottom-color: var(--kt-border-default); cursor: not-allowed; }
.kt-input[readonly] { background: transparent; border-bottom-style: dotted; }
.kt-select { appearance: none; padding-right: var(--kt-space-8);
  background-image: linear-gradient(45deg, transparent 48%, currentColor 48%, currentColor 58%, transparent 58%),
                    linear-gradient(-45deg, transparent 48%, currentColor 48%, currentColor 58%, transparent 58%);
  background-size: 9px 9px, 9px 9px; background-position: right 18px center, right 11px center; background-repeat: no-repeat; }
.kt-field.is-error .kt-input, .kt-field.is-error .kt-select, .kt-field.is-error .kt-textarea { border-color: var(--kt-border-error); border-bottom-color: var(--kt-border-error); }
.kt-field-hint { font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
.kt-field-error { display: flex; gap: var(--kt-space-1); font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); color: var(--kt-danger-fg); }
.kt-field-error::before { content: "✕"; }
.kt-input-group { display: flex; align-items: stretch; }
.kt-input-group__addon { border-radius: var(--kt-radius-md); display: inline-flex; align-items: center; padding: 0 var(--kt-pad-tight); font-size: var(--kt-font-ui); color: var(--kt-text-secondary); background: var(--kt-surface-accent); border: var(--kt-border-w-hair) solid var(--kt-border-default); border-right: 0; }

/* Điền thông minh: câu đọc lại số tiền, và bộ chọn nhanh thực thể.
   Luật ở HE-THIET-KE.md §13. Câu đọc lại KHÔNG phải chú thích trang trí,
   nó là lưới an toàn cho lỗi thừa một số 0, nên nó không được nhạt tới
   mức người ta thôi liếc vào.                                              */
.kt-nhap__doc { display: block; margin-top: var(--kt-space-1); font-size: var(--kt-type-label-size); line-height: var(--kt-leading-snug); color: var(--kt-text-secondary); }
.kt-nhap__doc:empty { display: none; }
.kt-nhap__doc--canh { color: var(--kt-warning-fg); font-weight: var(--kt-weight-semibold); }

.kt-chon { position: relative; }
.kt-chon__ds { border-radius: var(--kt-radius-md); position: absolute; z-index: var(--kt-z-popover); inset-inline: 0; top: 100%; margin-top: var(--kt-space-1);
  max-height: 264px; overflow-y: auto; overscroll-behavior: contain;
  background: var(--kt-surface-overlay); border: var(--kt-border-w) solid var(--kt-border-strong); box-shadow: var(--kt-shadow-md); }
.kt-chon__muc { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 0 var(--kt-space-2);
  padding: var(--kt-space-2) var(--kt-pad-tight); min-height: var(--kt-tap-min); cursor: pointer; border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-chon__muc:last-child { border-bottom: 0; }
.kt-chon__muc > b { font-size: var(--kt-font-ui); font-weight: var(--kt-weight-semibold); color: var(--kt-text-primary); overflow-wrap: anywhere; }
.kt-chon__phu { grid-column: 1; font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); overflow-wrap: anywhere; }
.kt-chon__ma { grid-row: 1 / span 2; font-family: var(--kt-font-mono); font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); white-space: nowrap; }
/* Mục đang chọn phải đọc ra được cả khi lọc xám: đổi nền THÌ đổi luôn
   viền trái, vì chỉ đổi nền là một tín hiệu duy nhất và nó là màu.       */
.kt-chon__muc.is-chon, .kt-chon__muc:hover { background: var(--kt-surface-accent); box-shadow: inset 3px 0 0 var(--kt-brand-900); }
.kt-chon__trong { padding: var(--kt-space-2) var(--kt-pad-tight); font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
/* Dòng xác nhận: hiện RA NGƯỜI vừa chọn, không hiện lại cái mã. Mã nào
   cũng giống mã nào, nên chọn nhầm bằng mã thì không có gì tự lộ.         */
.kt-chon__da { display: block; margin-top: var(--kt-space-1); padding-inline-start: var(--kt-space-2); box-shadow: inset 3px 0 0 var(--kt-brand-900);
  font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); color: var(--kt-text-primary); }

/* Hộp kiểm, ô chọn một, công tắc: đều là ô vuông mực, khác nhau ở dấu bên trong.
   Kích thước đi theo mật độ qua --kt-choice-size, nhãn căn giữa theo ô.        */
.kt-check, .kt-radio { display: inline-flex; align-items: center; gap: var(--kt-choice-gap); min-height: var(--kt-tap-min); font-size: var(--kt-font-ui); line-height: var(--kt-leading-snug); cursor: pointer; }
.kt-check > input, .kt-radio > input { appearance: none; margin: 0; flex: none; width: var(--kt-choice-size); height: var(--kt-choice-size); background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-strong); cursor: pointer; transition: var(--kt-transition-color); display: grid; place-content: center; }
.kt-radio > input { border-radius: var(--kt-radius-full); }
.kt-check > input:checked { background: var(--kt-brand-900); }
.kt-check > input:checked::after { content: ""; display: block; width: calc(var(--kt-choice-size) * 0.5); height: calc(var(--kt-choice-size) * 0.25); border-left: var(--kt-border-w) solid var(--kt-white); border-bottom: var(--kt-border-w) solid var(--kt-white); transform: translateY(-12%) rotate(-45deg); }
.kt-check > input:indeterminate { background: var(--kt-brand-900); }
.kt-check > input:indeterminate::after { content: ""; display: block; width: calc(var(--kt-choice-size) * 0.5); height: var(--kt-border-w); background: var(--kt-white); }
.kt-radio > input:checked { border-width: calc(var(--kt-choice-size) * 0.28); border-color: var(--kt-brand-900); }
.kt-check > input[disabled], .kt-radio > input[disabled] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; }
.kt-check--top, .kt-radio--top { align-items: flex-start; }
.kt-check--top > input, .kt-radio--top > input { margin-top: calc((var(--kt-font-ui) * var(--kt-leading-snug) - var(--kt-choice-size)) / 2); }

.kt-switch { display: inline-flex; align-items: center; gap: var(--kt-choice-gap); min-height: var(--kt-tap-min); font-size: var(--kt-font-ui); cursor: pointer; }
.kt-switch > input { appearance: none; margin: 0; flex: none; position: relative; width: var(--kt-switch-w); height: var(--kt-switch-h); background: var(--kt-surface-sunken); border: var(--kt-border-w) solid var(--kt-border-strong); cursor: pointer; transition: background var(--kt-dur-normal) var(--kt-ease-standard); }
.kt-switch > input::after { content: ""; position: absolute; top: 2px; left: 2px; width: calc(var(--kt-switch-h) - 8px); height: calc(var(--kt-switch-h) - 8px); background: var(--kt-brand-900); transition: transform var(--kt-dur-normal) var(--kt-ease-standard); }
.kt-switch > input:checked { background: var(--kt-success-fill); border-color: var(--kt-success-fill); }
.kt-switch > input:checked::after { transform: translateX(calc(var(--kt-switch-w) - var(--kt-switch-h))); background: var(--kt-white); }
.kt-switch > input[disabled] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; }

/* Nhóm phân đoạn và chip lựa chọn */
.kt-seg { border-radius: var(--kt-radius-md); display: inline-flex; border: var(--kt-border-w) solid var(--kt-border-strong); background: var(--kt-surface); }
.kt-seg > .kt-seg__opt { font: inherit; font-size: var(--kt-font-ui); font-weight: var(--kt-weight-semibold); min-height: var(--kt-control-h); padding: 0 var(--kt-control-px); background: transparent; color: var(--kt-action-quiet-fg); border: 0; border-left: var(--kt-border-w) solid var(--kt-border-strong); cursor: pointer; }
.kt-seg > .kt-seg__opt:first-child { border-left: 0; }
.kt-seg > .kt-seg__opt:hover { background: color-mix(in srgb, var(--kt-state-ink) var(--kt-state-hover), transparent); }
.kt-seg > .kt-seg__opt.is-active, .kt-seg > .kt-seg__opt[aria-pressed="true"] { background: var(--kt-brand-900); color: var(--kt-text-on-inverse); }
/* Nhóm phân đoạn đứng trong một ô biểu mẫu thì nó LÀ ô ấy, nên nó lấp đầy
   bề ngang và chia đều cho từng lựa chọn. Để nguyên `inline-flex` thì cột
   ô kéo nó rộng hết hàng mà mấy cái nút vẫn co về bên trái, và phần thừa
   bên phải trông y hệt một ô nhập rỗng nằm dính vào nút. */
.kt-field > .kt-seg { display: flex; }
.kt-field > .kt-seg > .kt-seg__opt { flex: 1 1 0; min-width: 0; }

.kt-chip { border-radius: var(--kt-radius-md); display: inline-flex; align-items: center; gap: var(--kt-space-2); min-height: var(--kt-control-h-sm); padding: 0 var(--kt-space-3); font: inherit; font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); color: var(--kt-text-secondary); background: var(--kt-surface); border: var(--kt-border-w-hair) solid var(--kt-border-default); cursor: pointer; transition: var(--kt-transition-color); }
.kt-chip:hover { border-color: var(--kt-border-strong); color: var(--kt-text-primary); }
.kt-chip.is-selected, .kt-chip[aria-pressed="true"] { background: var(--kt-surface-accent); border: var(--kt-border-w) solid var(--kt-border-strong); color: var(--kt-text-primary); }
.kt-chip[disabled] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; }
.kt-chip-set { display: flex; flex-wrap: wrap; gap: var(--kt-space-2); }

.kt-stepper { border-radius: var(--kt-radius-md); display: inline-flex; align-items: stretch; border: var(--kt-border-w) solid var(--kt-border-strong); background: var(--kt-surface); }
.kt-stepper > button { font: inherit; font-size: var(--kt-font-ui-strong); font-weight: var(--kt-weight-bold); width: var(--kt-control-h); min-height: var(--kt-control-h); background: transparent; color: var(--kt-action-quiet-fg); border: 0; cursor: pointer; }
.kt-stepper > button:hover { background: color-mix(in srgb, var(--kt-state-ink) var(--kt-state-hover), transparent); }
.kt-stepper > output { display: inline-flex; align-items: center; justify-content: center; min-width: 56px; font-variant-numeric: tabular-nums; font-weight: var(--kt-weight-bold); border-left: var(--kt-border-w) solid var(--kt-border-strong); border-right: var(--kt-border-w) solid var(--kt-border-strong); }

.kt-upload { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; align-items: flex-start; gap: var(--kt-space-2); padding: var(--kt-space-6) var(--kt-pad); background: var(--kt-surface-sunken); border: var(--kt-border-w) dashed var(--kt-border-default); color: var(--kt-text-secondary); font-size: var(--kt-type-label-size); cursor: pointer; }
.kt-upload:hover, .kt-upload.is-dragover { border-color: var(--kt-border-accent); color: var(--kt-text-primary); }
.kt-upload.is-error { border-style: solid; border-color: var(--kt-border-error); background: var(--kt-danger-bg); color: var(--kt-danger-fg); }

/* ==========================================================================
   ĐIỀU HƯỚNG — thanh trên, thanh đáy, tab, vụn đường dẫn, phân trang, ray, khay
   ==========================================================================*/
.kt-appbar { display: flex; align-items: center; justify-content: space-between; gap: var(--kt-space-3); padding: var(--kt-pad-tight) var(--kt-pad); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); position: sticky; top: 0; z-index: var(--kt-z-sticky); }
.kt-appbar__title { font-size: var(--kt-font-ui-strong); font-weight: var(--kt-weight-bold); }
.kt-appbar .kt-btn--ghost { color: var(--kt-text-on-inverse); --kt-state-ink: var(--kt-white); }

.kt-tabbar { position: sticky; bottom: 0; z-index: var(--kt-z-nav); display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; background: var(--kt-surface); border-top: var(--kt-border-w) solid var(--kt-border-strong); padding-bottom: env(safe-area-inset-bottom); }
.kt-tabbar__item { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-height: var(--kt-tap-min); padding: var(--kt-space-2) var(--kt-space-1); font: inherit; font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-semibold); color: var(--kt-text-tertiary); background: transparent; border: 0; border-top: var(--kt-border-w-thick) solid transparent; cursor: pointer; }
.kt-tabbar__item:hover { background: var(--kt-surface-sunken); }
.kt-tabbar__item.is-active, .kt-tabbar__item[aria-current="page"] { color: var(--kt-text-brand); border-top-color: var(--kt-action-indicator); }
.kt-tabbar__item[aria-disabled="true"] { opacity: var(--kt-state-disabled-opacity); pointer-events: none; }

.kt-tabs { display: flex; gap: var(--kt-space-4); border-bottom: var(--kt-border-w) solid var(--kt-border-strong); overflow-x: auto; }
.kt-tab { position: relative; font: inherit; font-size: var(--kt-font-ui); font-weight: var(--kt-weight-semibold); color: var(--kt-text-tertiary); background: transparent; border: 0; padding: var(--kt-space-3) 0; min-height: var(--kt-tap-min); cursor: pointer; white-space: nowrap; }
.kt-tab:hover { color: var(--kt-text-primary); }
.kt-tab[aria-selected="true"] { color: var(--kt-text-primary); font-weight: var(--kt-weight-bold); box-shadow: inset 0 calc(var(--kt-border-w-thick) * -1) 0 var(--kt-action-indicator); }
.kt-tab__count { display: inline-block; margin-left: var(--kt-space-2); font-variant-numeric: tabular-nums; color: var(--kt-text-tertiary); }

.kt-breadcrumb { display: flex; align-items: center; gap: var(--kt-space-2); font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
.kt-breadcrumb__sep { color: var(--kt-border-default); }
.kt-breadcrumb [aria-current="page"] { color: var(--kt-text-primary); font-weight: var(--kt-weight-semibold); }

.kt-pager { display: flex; align-items: center; gap: var(--kt-space-2); }
.kt-pager__info { font-size: var(--kt-type-label-size); color: var(--kt-text-secondary); font-variant-numeric: tabular-nums; }
.kt-pager__btn { border-radius: var(--kt-radius-md); font: inherit; font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); min-width: var(--kt-control-h-sm); min-height: var(--kt-control-h-sm); background: var(--kt-surface); color: var(--kt-action-quiet-fg); border: var(--kt-border-w-hair) solid var(--kt-border-default); cursor: pointer; }
.kt-pager__btn:hover { border-color: var(--kt-border-strong); }
.kt-pager__btn[aria-current="page"] { background: var(--kt-brand-900); color: var(--kt-text-on-inverse); border-color: var(--kt-brand-900); }
.kt-pager__btn[disabled] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; }

.kt-rail { display: flex; flex-direction: column; gap: 2px; padding: var(--kt-space-3) var(--kt-space-2); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); min-width: 216px; }
.kt-rail__item { display: flex; align-items: center; gap: var(--kt-space-3); min-height: var(--kt-control-h); padding: 0 var(--kt-space-3); font: inherit; font-size: var(--kt-font-ui); font-weight: var(--kt-weight-medium); color: var(--kt-text-on-inverse-muted); background: transparent; border: 0; border-left: var(--kt-border-w-thick) solid transparent; cursor: pointer; text-align: left; transition: var(--kt-transition-color); }
.kt-rail__item > svg { opacity: 0.75; }
.kt-rail__item:hover { color: var(--kt-text-on-inverse); background: color-mix(in srgb, var(--kt-white) 8%, transparent); }
.kt-rail__item:hover > svg { opacity: 1; }
.kt-rail__item.is-active, .kt-rail__item[aria-current="page"] { color: var(--kt-text-on-inverse); font-weight: var(--kt-weight-bold); border-left-color: var(--kt-action-indicator); background: color-mix(in srgb, var(--kt-white) 12%, transparent); }
.kt-rail__item.is-active > svg { opacity: 1; }
.kt-rail__count { margin-left: auto; font-size: var(--kt-type-caption-size); font-weight: var(--kt-weight-semibold); font-variant-numeric: tabular-nums; color: var(--kt-text-on-inverse-muted); }
.kt-rail__item.is-active .kt-rail__count { color: var(--kt-text-on-inverse); }
.kt-rail__group { margin: var(--kt-space-5) 0 var(--kt-space-1); padding: 0 var(--kt-space-3); font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-semibold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; color: color-mix(in srgb, var(--kt-text-on-inverse-muted) 80%, transparent); }
.kt-rail__group:first-of-type { margin-top: var(--kt-space-3); }
.kt-rail__brand { display: flex; align-items: center; gap: var(--kt-space-3); padding: var(--kt-space-2) var(--kt-space-3) var(--kt-space-4); border-bottom: var(--kt-border-w-hair) solid color-mix(in srgb, var(--kt-white) 18%, transparent); }

.kt-drawer { border-radius: var(--kt-radius-md); position: fixed; top: 0; bottom: 0; left: 0; z-index: var(--kt-z-drawer); width: min(88vw, 360px); background: var(--kt-surface); border-right: var(--kt-border-w) solid var(--kt-border-strong); box-shadow: var(--kt-shadow-lg); display: flex; flex-direction: column; }

/* ==========================================================================
   BỀ MẶT NỔI — lớp che, tấm trượt, hộp thoại, cửa sổ nhỏ, trình đơn, mách nhỏ
   ==========================================================================*/
.kt-scrim { position: fixed; inset: 0; z-index: var(--kt-z-scrim); background: var(--kt-scrim); }
.kt-sheet { border-radius: var(--kt-radius-sheet) var(--kt-radius-sheet) 0 0; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--kt-z-sheet); background: var(--kt-surface-overlay); border-top: var(--kt-border-w-thick) solid var(--kt-border-strong); box-shadow: var(--kt-shadow-sheet); padding: var(--kt-pad); padding-bottom: max(var(--kt-pad), env(safe-area-inset-bottom)); display: flex; flex-direction: column; gap: var(--kt-pad-tight); animation: kt-rise var(--kt-dur-slow) var(--kt-ease-decelerate); }
.kt-sheet__grip { border-radius: var(--kt-radius-pill); width: 56px; height: var(--kt-border-w-thick); background: var(--kt-border-default); align-self: center; }
.kt-sheet__title { font-size: var(--kt-type-title-size); font-weight: var(--kt-weight-bold); }
@keyframes kt-rise { from { transform: translateY(16px); opacity: 0; } }

/* GỐC BỆNH PHÔNG CHÂN, cả ba cửa cùng dính. `.kt-app` là chỗ DUY NHẤT khai
   `font-family`, mà `KT.ui.confirm` và `KT.ui.toast` lại dựng phần tử rồi
   `document.body.appendChild()` — tức là chúng nằm NGOÀI `.kt-app`. Hậu quả:
   mọi hộp xác nhận và mọi tin báo nổi của khách, thợ lẫn buồng lái đều chạy
   bằng phông chân mặc định của trình duyệt, giữa một hệ Be Vietnam Pro. Màu
   với khoảng cách vẫn đúng vì token nằm ở `:root`, nên lỗi này không phá bố
   cục — nó chỉ đổi mặt chữ, và vì thế sống rất lâu mà không ai gọi tên.
   Ba gốc treo ngoài thân trang phải tự đứng được, đừng trông vào cha. */
.kt-dialog, .kt-toast-host, .kt-scrim {
  font-family: var(--kt-font-sans);
  font-size: var(--kt-type-body-size);
  line-height: var(--kt-type-body-leading);
  color: var(--kt-text-primary);
}
/* Hộp thoại có LỀ RIÊNG, không mượn `--kt-pad` của thẻ. Thẻ nằm trên nền
   trang và có cả trang quanh nó để thở; hộp thoại là bề mặt trên cùng, che
   mất mọi thứ, nên lề của nó phải rộng hơn hẳn — 12px ở mật độ compact là
   lề của một ô bảng, không phải lề của một quyết định.

   Và khoảng cách GIỮA hai khối phải khác hẳn khoảng cách TRONG một khối.
   Bản cũ để `gap: --kt-pad-tight` cho cả hộp, nên tiêu đề, dòng phụ, dải
   cảnh báo, bảng tiền, ô nhập và hàng nút đều cách nhau đúng 8px: sáu thứ
   khác loại xếp đều tăm tắp thì không thứ nào thuộc về thứ nào, và mắt
   không có chỗ nào để bám mà chia nhóm. */
.kt-dialog { border-radius: var(--kt-radius-lg); --kt-dialog-pad: var(--kt-space-6);
  background: var(--kt-surface-overlay); border: var(--kt-border-w) solid var(--kt-border-strong);
  box-shadow: var(--kt-shadow-md); padding: var(--kt-dialog-pad); max-width: 440px;
  display: flex; flex-direction: column; gap: var(--kt-space-4); }
.kt-dialog__title { font-size: var(--kt-type-title-size); font-weight: var(--kt-weight-bold); line-height: var(--kt-leading-tight); }
.kt-dialog__body { font-size: var(--kt-font-ui); color: var(--kt-text-secondary); }
/* Dòng phụ ngay dưới tiêu đề là MỘT khối với tiêu đề, không phải khối thứ
   hai. Kéo nó lại gần để cái tên và cái kỳ đọc thành một câu. */
.kt-dialog__title + .kt-dialog__body { margin-top: calc(var(--kt-space-3) * -1); }
/* Hàng nút chốt: dính đáy trong chính khung cuộn của hộp, tràn ra hai mép,
   có đường kẻ trên. Hộp thoại nào cũng có lúc dài hơn màn, và thứ đầu tiên
   trôi khỏi tầm mắt luôn là thứ người ta mở hộp lên để bấm. */
.kt-dialog__actions { display: flex; gap: var(--kt-space-2); flex-wrap: wrap; justify-content: flex-end;
  position: sticky; bottom: calc(var(--kt-dialog-pad) * -1);
  margin: var(--kt-space-2) calc(var(--kt-dialog-pad) * -1) calc(var(--kt-dialog-pad) * -1);
  padding: var(--kt-space-4) var(--kt-dialog-pad);
  background: var(--kt-surface-overlay);
  border-top: var(--kt-border-w) solid var(--kt-border-strong); }
/* Lý do nút chốt đang tắt. Nút tắt mà không nói vì sao thì người ta bấm ba
   lần rồi đóng hộp đi, tưởng hệ hỏng. Đẩy sang trái để nó không chen vào
   giữa hai cái nút. */
.kt-dialog__why { order: -1; flex: 0 0 100%; margin: 0;
  font-size: var(--kt-type-label-size); line-height: var(--kt-leading-snug); color: var(--kt-text-tertiary); }
.kt-dialog__actions > .kt-btn { flex: 0 0 auto; }
.kt-dialog__why:empty { display: none; }
.kt-dialog--destructive { border-color: var(--kt-danger-border); border-width: var(--kt-border-w-thick); }
.kt-dialog--destructive .kt-dialog__title { color: var(--kt-danger-fg); }
/* Hộp thoại nổi giữa màn hình.

   Trước đây mỗi màn tự gõ lại chuỗi `position:fixed;left:50%;top:50%;...`,
   bảy chỗ bảy bản, và chỉ MỘT bản nhớ chặn chiều cao. Hộp thoại nào dài
   hơn màn thì phần đáy tràn ra ngoài, mà đáy chính là chỗ đặt nút chốt:
   hộp vẫn mở, vẫn đúng nội dung, chỉ là không ai bấm được nút nào. Trần
   chiều cao ở đây là phần bắt buộc, không phải phần trang trí.

   Bề ngang khai bằng `--kt-dialog-w` chứ không bằng lớp con, vì bảy hộp
   đang dùng bảy con số khác nhau và số ấy là chuyện của từng hộp. */
.kt-dialog--noi {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(var(--kt-dialog-w, 460px), calc(100vw - var(--kt-space-8)));
  max-width: none;
  max-height: calc(100vh - var(--kt-space-8));
  overflow-y: auto;
  z-index: var(--kt-z-dialog);
}
.kt-dialog--destructive::before { content: ""; height: var(--kt-space-2); background: var(--kt-danger-fill); margin: calc(var(--kt-dialog-pad) * -1) calc(var(--kt-dialog-pad) * -1) 0; }

.kt-popover { border-radius: var(--kt-radius-md); background: var(--kt-surface-overlay); border: var(--kt-border-w) solid var(--kt-border-strong); box-shadow: var(--kt-shadow-md); padding: var(--kt-pad-tight); z-index: var(--kt-z-popover); }
.kt-menu { border-radius: var(--kt-radius-md); min-width: 200px; background: var(--kt-surface-overlay); border: var(--kt-border-w) solid var(--kt-border-strong); box-shadow: var(--kt-shadow-md); padding: var(--kt-space-1) 0; z-index: var(--kt-z-popover); }
.kt-menu__item { display: flex; align-items: center; gap: var(--kt-space-3); width: 100%; min-height: var(--kt-control-h); padding: 0 var(--kt-pad-tight); font: inherit; font-size: var(--kt-font-ui); color: var(--kt-text-primary); background: transparent; border: 0; text-align: left; cursor: pointer; }
.kt-menu__item:hover { background: var(--kt-surface-sunken); }
.kt-menu__item--danger { color: var(--kt-danger-fg); }
.kt-menu__item[aria-disabled="true"] { opacity: var(--kt-state-disabled-opacity); pointer-events: none; }
.kt-menu__sep { height: 0; border-top: var(--kt-border-w-hair) solid var(--kt-border-subtle); margin: var(--kt-space-1) 0; }

.kt-tooltip { position: relative; display: inline-flex; }
.kt-tooltip__bubble { border-radius: var(--kt-radius-sm); position: absolute; bottom: calc(100% + var(--kt-space-2)); left: 0; z-index: var(--kt-z-tooltip); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); font-size: var(--kt-type-caption-size); padding: var(--kt-space-1) var(--kt-space-2); white-space: nowrap; }

/* ==========================================================================
   THÔNG BÁO — dải băng, cảnh báo trong dòng, tin báo nổi kèm hoàn tác
   ==========================================================================*/
.kt-banner { border-radius: var(--kt-radius-md); display: flex; align-items: flex-start; gap: var(--kt-space-3); padding: var(--kt-pad-tight) var(--kt-pad); font-size: var(--kt-font-ui); background: var(--kt-info-bg); color: var(--kt-info-fg); border-left: var(--kt-space-2) solid var(--kt-info-border); flex-wrap: wrap; }
.kt-banner--warning { background: var(--kt-warning-bg); color: var(--kt-warning-fg); border-left-color: var(--kt-warning-border); }
.kt-banner--danger { background: var(--kt-danger-bg); color: var(--kt-danger-fg); border-left-color: var(--kt-danger-border); }
.kt-banner--success { background: var(--kt-success-bg); color: var(--kt-success-fg); border-left-color: var(--kt-success-border); }
.kt-banner--offline { background: var(--kt-neutral-bg); color: var(--kt-neutral-fg); border-left-color: var(--kt-neutral-border); }
.kt-banner__body { display: flex; flex-direction: column; gap: var(--kt-space-1); flex: 1; min-width: 14ch; }
.kt-banner__title { font-weight: var(--kt-weight-bold); }
.kt-banner__action { margin-left: auto; flex: none; }

.kt-alert { border-radius: var(--kt-radius-md); display: flex; align-items: flex-start; gap: var(--kt-space-2); padding: var(--kt-space-2) var(--kt-pad-tight); font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); background: var(--kt-danger-bg); color: var(--kt-danger-fg); border: var(--kt-border-w-hair) solid var(--kt-danger-border); }

.kt-toast { border-radius: var(--kt-radius-md); display: flex; align-items: center; gap: var(--kt-space-3); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); padding: var(--kt-pad-tight) var(--kt-pad); font-size: var(--kt-font-ui); border-left: var(--kt-space-2) solid var(--kt-action-indicator); box-shadow: var(--kt-shadow-md); max-width: 520px; }
.kt-toast--success { border-left-color: var(--kt-success-fill); }
.kt-toast--danger { border-left-color: var(--kt-danger-fill); }
.kt-toast--info { border-left-color: var(--kt-info-fill); }
.kt-toast__action { margin-left: auto; font: inherit; font-weight: var(--kt-weight-bold); color: var(--kt-text-on-inverse); background: transparent; border: 0; border-bottom: var(--kt-border-w) solid currentColor; padding: 0 0 1px; cursor: pointer; white-space: nowrap; }

/* ==========================================================================
   HIỂN THỊ DỮ LIỆU — thẻ, thẻ đơn, danh sách, bảng, chỉ số, dòng thời gian
   ==========================================================================*/
.kt-card { border-radius: var(--kt-radius-lg); background: var(--kt-surface); border: var(--kt-surface-edge-w) solid var(--kt-surface-edge); box-shadow: var(--kt-surface-lift); --kt-card-pad: var(--kt-pad); }
.kt-card__head { padding: var(--kt-pad-tight) var(--kt-pad); border-bottom: var(--kt-surface-edge-w) solid var(--kt-surface-edge); background: var(--kt-surface-accent); }
.kt-card__body { padding: var(--kt-pad); display: flex; flex-direction: column; gap: var(--kt-pad-tight); }
.kt-card__foot { padding: var(--kt-pad); border-top: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-card__title { font-size: var(--kt-type-title-size); font-weight: var(--kt-weight-bold); line-height: var(--kt-leading-tight); }

/* ── THẺ TRẦN: thẻ vẫn phải là thẻ khi không ai viết ô con ────────────────
   Lề của thẻ nằm ở ba ô con `__head` `__body` `__foot`, nên thẻ viết trần
   không có lề nào: chữ tì lên đường viền, ô nhập chạy hết bề ngang, và
   mấy thẻ trần xếp chồng trong ngăn kéo đọc ra thành MỘT tảng liền chứ
   không ra mấy khối tách bạch. Đo trên bản đang chạy: buồng lái 291/359
   thẻ viết trần, cửa thợ 40/62. Sửa 331 chỗ gọi bằng tay là sửa triệu
   chứng; thứ hỏng là chính thành phần, vì nó chỉ đúng khi người viết
   NHỚ bọc thêm một lớp. Nay thẻ trần tự giữ lề, thẻ có ô con giữ nguyên
   hình cũ từng pixel (`:has` chỉ chạm nhánh không có ô con nào).
   Bảng vẫn tràn ra mép: đầu bảng và sọc ngựa vằn phải chạm viền thì mới
   đọc ra là một bảng, thụt vào thì nó thành một khối chữ có kẻ dòng. */
.kt-card:not(:has(> :is(.kt-card__head, .kt-card__body, .kt-card__foot))) {
  display: flex; flex-direction: column; gap: var(--kt-pad-tight);
  padding: var(--kt-card-pad);
}
.kt-card:not(:has(> :is(.kt-card__head, .kt-card__body, .kt-card__foot))) > .kt-table-wrap {
  margin-inline: calc(var(--kt-card-pad) * -1);
}
.kt-card:not(:has(> :is(.kt-card__head, .kt-card__body, .kt-card__foot))) > .kt-table-wrap:first-child {
  margin-top: calc(var(--kt-card-pad) * -1);
}
.kt-card:not(:has(> :is(.kt-card__head, .kt-card__body, .kt-card__foot))) > .kt-table-wrap:last-child {
  margin-bottom: calc(var(--kt-card-pad) * -1);
}
/* Thẻ NỬA: có đầu thẻ mà không có thân thẻ. Nội dung lạc ở giữa cũng
   không có lề, cùng một bệnh, khác chỗ đứng. */
.kt-card:has(> .kt-card__head):not(:has(> .kt-card__body)) > :not(.kt-card__head):not(.kt-card__foot):not(.kt-table-wrap) {
  margin-inline: var(--kt-card-pad);
}
.kt-card:has(> .kt-card__head):not(:has(> .kt-card__body)) > :last-child:not(.kt-card__head):not(.kt-card__foot):not(.kt-table-wrap) {
  margin-bottom: var(--kt-card-pad);
}

.kt-order { border-radius: var(--kt-radius-lg); background: var(--kt-surface); border: var(--kt-surface-edge-w) solid var(--kt-surface-edge); box-shadow: var(--kt-surface-lift); display: flex; flex-direction: column; }
.kt-order__top { display: flex; align-items: center; justify-content: space-between; gap: var(--kt-space-2); padding: var(--kt-pad-tight) var(--kt-pad); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); }
.kt-order__code { font-variant-numeric: tabular-nums; font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); }
.kt-order__body { padding: var(--kt-pad); display: flex; flex-direction: column; gap: var(--kt-pad-tight); }
.kt-order__service { font-size: var(--kt-font-ui-strong); font-weight: var(--kt-weight-bold); line-height: var(--kt-leading-tight); }
.kt-order__place { font-size: var(--kt-font-ui); color: var(--kt-text-secondary); }
.kt-order__note { display: flex; gap: var(--kt-space-2); background: var(--kt-surface-accent); color: var(--kt-warning-fg); padding: var(--kt-pad-tight); font-size: var(--kt-type-label-size); }
.kt-order__foot { display: flex; align-items: center; justify-content: space-between; padding: var(--kt-pad-tight) var(--kt-pad); border-top: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-order:hover { box-shadow: var(--kt-shadow-xs); }
.kt-order.is-selected { outline: var(--kt-border-w-thick) solid var(--kt-action-indicator); outline-offset: -1px; }

.kt-list { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-strong); }
.kt-list__row { display: flex; align-items: center; gap: var(--kt-pad-tight); padding: var(--kt-pad-tight) var(--kt-pad); min-height: var(--kt-row-h); border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); text-align: left; background: transparent; border-left: 0; border-right: 0; border-top: 0; font: inherit; color: inherit; cursor: pointer; width: 100%; }
/* Hàng CHỈ ĐỂ ĐỌC. Con trỏ tay và nền khi rê chuột là lời mời bấm, mà
   một hàng không bấm được thì lời mời ấy dẫn tới hư không — cái nút chết
   không cần ai viết ra. Khai bằng biến thể chứ không bám thẻ `button`:
   hệ này không đặt luật lên phần tử trần (cổng 6 gác), và khai rõ thì
   người viết màn phải TRẢ LỜI câu "hàng này bấm được không". */
.kt-list__row--doc { cursor: default; }
.kt-list__row:last-child { border-bottom: 0; }
.kt-list__row:hover { background: var(--kt-surface-sunken); }
.kt-list__row--doc:hover { background: transparent; }
.kt-list__row.is-selected { background: var(--kt-accent-100); box-shadow: inset var(--kt-border-w-thick) 0 0 var(--kt-action-indicator); }
.kt-list__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.kt-list__title { font-weight: var(--kt-weight-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kt-list__meta { font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }

.kt-table-wrap { border-radius: var(--kt-radius-lg); overflow-x: auto; max-width: 100%; background: var(--kt-surface); }
.kt-table-wrap > .kt-table { min-width: max-content; }
.kt-table { width: 100%; border-collapse: collapse; font-size: var(--kt-font-ui); background: var(--kt-surface); }
.kt-table caption { text-align: left; padding: var(--kt-pad-tight) 0; font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
.kt-table th { text-align: left; font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); padding: var(--kt-space-2) var(--kt-pad-tight); white-space: nowrap; position: sticky; top: 0; z-index: var(--kt-z-sticky); }
.kt-table th[aria-sort] { cursor: pointer; }
.kt-table th[aria-sort]:hover { background: var(--kt-brand-800); }
.kt-table th[aria-sort="ascending"]::after { content: " ▲"; }
.kt-table th[aria-sort="descending"]::after { content: " ▼"; }
.kt-table td { padding: 0 var(--kt-pad-tight); height: var(--kt-row-h); border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); vertical-align: middle; }
.kt-table tbody tr:nth-child(even) { background: var(--kt-bg-subtle); }
.kt-table tbody tr:hover { background: var(--kt-brand-100); }
.kt-table tbody tr.is-selected { background: var(--kt-accent-100); box-shadow: inset var(--kt-border-w-thick) 0 0 var(--kt-action-indicator); }
.kt-table .kt-num { text-align: right; font-variant-numeric: tabular-nums; }
/* Ô chứa ngưỡi: ảnh đại diện và tên luôn cùng một dòng, dài quá thì cắt bằng ba chấm. */
.kt-cell-user { display: inline-flex; align-items: center; gap: var(--kt-space-2); min-width: 0; max-width: 100%; white-space: nowrap; }
.kt-cell-user > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.kt-table td:has(.kt-cell-user) { white-space: nowrap; }
.kt-table--zebra-off tbody tr:nth-child(even) { background: transparent; }
.kt-bulkbar { display: flex; align-items: center; gap: var(--kt-space-3); padding: var(--kt-space-2) var(--kt-pad); background: var(--kt-brand-900); color: var(--kt-text-on-inverse); font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); }
.kt-bulkbar .kt-btn { --kt-state-ink: var(--kt-white); }

.kt-stat { border-radius: var(--kt-radius-md); display: flex; flex-direction: column; gap: var(--kt-space-1); padding: var(--kt-pad); background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-strong); }
.kt-stat__label { font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; color: var(--kt-text-tertiary); }
.kt-stat__value { font-size: var(--kt-type-display-size); font-weight: var(--kt-weight-bold); line-height: var(--kt-leading-tight); font-variant-numeric: tabular-nums; }
.kt-stat__delta { font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); }
.kt-stat__delta--up { color: var(--kt-success-fg); }
.kt-stat__delta--down { color: var(--kt-danger-fg); }

.kt-timeline { display: flex; flex-direction: column; }
.kt-timeline__item { display: grid; grid-template-columns: 20px 1fr; gap: var(--kt-space-3); padding-bottom: var(--kt-space-4); position: relative; }
.kt-timeline__dot { width: 12px; height: 12px; margin-top: 4px; background: var(--kt-brand-900); }
.kt-timeline__item:not(:last-child)::before { content: ""; position: absolute; left: 5px; top: 20px; bottom: 0; width: var(--kt-border-w); background: var(--kt-border-subtle); }
.kt-timeline__time { font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); font-variant-numeric: tabular-nums; }
/* Bốn chỗ đứng của một mốc. Hệ vẽ chuỗi có thứ tự theo chiều NGANG bằng
   `.kt-progress`; bảy chặng kèm giờ thật và một câu giải thích thì không
   xếp ngang nổi ở 390px, nên cùng dữ liệu `dungHanhTrinh()` đổ vào dòng
   thời gian DỌC. Thiếu bốn lớp này thì mọi chặng vẽ giống hệt nhau, và
   người mở màn ra mất đúng thứ họ đến để xem: việc đang đứng ở đâu.
   `is-cho` KHÔNG phải mặc định. Chặng chưa tới phải tự khai, vì một chặng
   quên khai đọc ra thành đã xong, mà sai theo hướng đó là hệ hứa hộ. */
.kt-timeline__item.is-done .kt-timeline__dot { background: var(--kt-success-fill); }
.kt-timeline__item.is-now .kt-timeline__dot { background: var(--kt-action-indicator); box-shadow: 0 0 0 4px var(--kt-accent-100); }
.kt-timeline__item.is-stop .kt-timeline__dot { background: var(--kt-danger-fill); }
.kt-timeline__item.is-cho .kt-timeline__dot { background: var(--kt-surface-sunken); box-shadow: inset 0 0 0 var(--kt-border-w) var(--kt-border-default); }
.kt-timeline__item.is-done:not(:last-child)::before { background: var(--kt-success-border); }
.kt-timeline__label { font-size: var(--kt-font-ui); font-weight: var(--kt-weight-semibold); }
.kt-timeline__item.is-cho .kt-timeline__label { color: var(--kt-text-tertiary); font-weight: var(--kt-weight-regular); }
.kt-timeline__note { font-size: var(--kt-type-label-size); color: var(--kt-text-secondary); line-height: var(--kt-leading-normal); }

.kt-avatar { border-radius: var(--kt-radius-pill); display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; flex: none; background: var(--kt-surface-accent); color: var(--kt-brand-900); border: var(--kt-border-w) solid var(--kt-border-strong); font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold); }
.kt-avatar--sm { width: 28px; height: 28px; font-size: var(--kt-type-caption-size); }

/* ==========================================================================
   TRẠNG THÁI NGHIỆP VỤ
   ==========================================================================*/
/* Sáu trạng thái đơn: màu, ký hiệu hình học, kiểu viền, ba tín hiệu cùng lúc */
.kt-badge { border-radius: var(--kt-radius-sm); display: inline-flex; align-items: center; gap: var(--kt-space-1); font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold); letter-spacing: 0.02em; padding: 3px var(--kt-space-2); border: var(--kt-border-w) solid currentColor; white-space: nowrap; }
.kt-badge::before { font-size: 1.05em; line-height: 1; }
.kt-badge--pending   { color: var(--kt-text-secondary); border-style: dashed; }
.kt-badge--pending::before   { content: "○"; }
.kt-badge--assigned  { color: var(--kt-info-fg); border-style: solid; }
.kt-badge--assigned::before  { content: "◔"; }
.kt-badge--enroute   { color: var(--kt-info-fill); border-style: double; border-width: var(--kt-border-w-thick); }
.kt-badge--enroute::before   { content: "▶"; }
/* Mốc tới sảnh. Cùng MÀU với chặng đang tới vì cùng một họ "chưa vào nhà",
   khác ở ký hiệu và ở kiểu viền: hai tín hiệu, in đen trắng vẫn đọc ra.
   Đây là chặng Grab và bTaskee không có, vì họ không mô hình hoá toà nhà. */
.kt-badge--lobby     { color: var(--kt-info-fill); border-style: solid; border-width: var(--kt-border-w-thick); }
.kt-badge--lobby::before     { content: "◈"; }
.kt-badge--working   { color: var(--kt-warning-fg); background: var(--kt-warning-bg); border-style: solid; }
.kt-badge--working::before   { content: "◑"; }
.kt-badge--done      { color: var(--kt-success-fg); background: var(--kt-success-bg); border-style: solid; }
.kt-badge--done::before      { content: "✓"; }
.kt-badge--cancelled { color: var(--kt-danger-fg); background: var(--kt-danger-bg); border-style: solid; text-decoration: line-through; }
.kt-badge--cancelled::before { content: "✕"; text-decoration: none; }

/* Sáu giai đoạn vòng đời thợ: chữ in hoa, gạch chân dày, không viền */
.kt-stage { display: inline-flex; align-items: center; gap: var(--kt-space-2); font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; padding-bottom: 3px; border-bottom: var(--kt-border-w-thick) solid currentColor; }
.kt-stage--candidate { color: var(--kt-text-tertiary); }
.kt-stage--probation { color: var(--kt-warning-fg); }
.kt-stage--active    { color: var(--kt-text-brand); }
.kt-stage--senior    { color: var(--kt-success-fg); }
.kt-stage--paused    { color: var(--kt-text-secondary); }
.kt-stage--left      { color: var(--kt-danger-fg); }

/* Trạng thái nhận việc hôm nay: đèn tròn, chữ thường, không viền */
.kt-duty { display: inline-flex; align-items: center; gap: var(--kt-space-2); font-size: var(--kt-type-label-size); color: var(--kt-text-secondary); }
.kt-duty::before { content: ""; width: 10px; height: 10px; flex: none; border: var(--kt-border-w) solid currentColor; }
.kt-duty--free::before { background: var(--kt-success-fill); border-color: var(--kt-success-fill); }
.kt-duty--busy::before { background: var(--kt-action-indicator); border-color: var(--kt-accent-700); border-radius: var(--kt-radius-full); }
.kt-duty--off::before  { background: transparent; border-color: var(--kt-text-tertiary); }

/* Cờ nghiệp vụ: quá hạn, bảo hành, đang chờ đồng bộ. Không phải trạng thái đơn. */
.kt-flag { border-radius: var(--kt-radius-sm); display: inline-flex; align-items: center; gap: var(--kt-space-1); font-size: var(--kt-type-caption-size); font-weight: var(--kt-weight-bold); padding: 1px var(--kt-space-2); border: var(--kt-border-w-hair) solid currentColor; }
.kt-flag--late { color: var(--kt-danger-fg); background: var(--kt-danger-bg); }
.kt-flag--warranty { color: var(--kt-success-fg); background: var(--kt-success-bg); }
.kt-flag--queued { color: var(--kt-neutral-fg); background: var(--kt-neutral-bg); border-style: dashed; }

/* ── Bước nhận việc ─────────────────────────────────────────────────
   Ba tín hiệu mỗi trạng thái, không chỉ màu: ký hiệu ở `::before`, màu
   chữ, và kiểu viền. Lọc xám vẫn đọc ra được, và người không phân biệt
   được đỏ với xanh vẫn thấy ○ khác ✓.

   `--cu` viền NÉT ĐỨT vì nó nói "hệ không biết", khác hẳn "chưa nhận".
   Cùng cách `kt-flag--queued` dùng nét đứt cho thứ chưa chắc chắn. */
.kt-nhan { border-radius: var(--kt-radius-sm); display: inline-flex; align-items: center; gap: var(--kt-space-1);
  font-size: var(--kt-type-caption-size); font-weight: var(--kt-weight-bold);
  padding: 1px var(--kt-space-2); border: var(--kt-border-w-hair) solid currentColor; }
.kt-nhan::before { font-weight: var(--kt-weight-regular); }
.kt-nhan--cho  { color: var(--kt-warning-fg); background: var(--kt-warning-bg); }
.kt-nhan--cho::before  { content: "\25D4"; }
.kt-nhan--qua  { color: var(--kt-danger-fg); background: var(--kt-danger-bg); }
.kt-nhan--qua::before  { content: "\25CB"; }
.kt-nhan--xong { color: var(--kt-success-fg); background: var(--kt-success-bg); }
.kt-nhan--xong::before { content: "\2713"; }
.kt-nhan--cu   { color: var(--kt-neutral-fg); background: var(--kt-neutral-bg); border-style: dashed; }
.kt-nhan--cu::before   { content: "\25C8"; }
.kt-nhan--chua { color: var(--kt-text-tertiary); background: transparent; border-style: dotted; }
.kt-nhan--chua::before { content: "\25CB"; }

/* Thanh tiến trình sáu bước của đơn */
/* Rãnh GIỮA hai chặng phải lớn hơn hẳn rãnh TRONG một chặng (8px với 4px).
   Bản trước để cả hai bằng var(--kt-space-1), tức khoảng cách nối thanh với
   nhãn của CÙNG một chặng bằng đúng khoảng cách tách chặng này khỏi chặng
   bên: mắt hết căn cứ phân nhóm, và nhãn của chặng đang chờ (in đậm nên
   rộng ra) đọc như dính vào nhãn chặng kế. Cùng luật tỷ lệ đã áp cho ngăn
   kéo ở bản 2.8.0. Bản gọn không đụng tới: nó không chở chữ. */
.kt-progress { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--kt-space-2); }
.kt-progress__step { display: flex; flex-direction: column; gap: var(--kt-space-1); font-size: var(--kt-type-overline-size); color: var(--kt-text-tertiary); }
.kt-progress__bar { border-radius: var(--kt-radius-pill); height: var(--kt-space-2); background: var(--kt-surface-sunken); border: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-progress__step.is-done .kt-progress__bar { background: var(--kt-brand-900); border-color: var(--kt-brand-900); }
.kt-progress__step.is-done { color: var(--kt-text-secondary); }
.kt-progress__step.is-current .kt-progress__bar { background: var(--kt-action-indicator); border-color: var(--kt-accent-700); }
.kt-progress__step.is-current { color: var(--kt-warning-fg); font-weight: var(--kt-weight-bold); }
.kt-progress__step.is-cancelled .kt-progress__bar { background: var(--kt-danger-fill); border-color: var(--kt-danger-fill); }
/* Bản gọn cho BẢNG nhiều dòng. Không chữ, nên bề ngang cố định thay vì chia
   đều: trong một ô bảng thì `1fr` co theo cột hẹp nhất và tám chặng dồn
   thành một vệt không đọc được. Nhãn ở trong `title`. */
.kt-progress--gon { grid-auto-columns: var(--kt-space-4); gap: 2px; }
.kt-progress--gon .kt-progress__step { gap: 0; }
.kt-progress--gon .kt-progress__bar { height: var(--kt-space-3); }
/* Chặng đang chờ mà KẸT. Ba tín hiệu: nền cảnh báo, viền đậm hơn, và dấu
   gạch đứng ở giữa để phân biệt được khi lọc xám. */
.kt-progress__step.is-ket .kt-progress__bar {
  background: var(--kt-danger-fill); border-color: var(--kt-danger-fg);
  border-width: var(--kt-border-w-thick);
}

/* Thanh tiến trình liên tục và con quay */
.kt-bar { border-radius: var(--kt-radius-pill); height: var(--kt-space-2); background: var(--kt-surface-sunken); border: var(--kt-border-w-hair) solid var(--kt-border-subtle); overflow: hidden; }
.kt-bar__fill { border-radius: var(--kt-radius-pill); height: 100%; background: var(--kt-action-indicator); transition: width var(--kt-dur-slow) var(--kt-ease-standard); }
.kt-bar--indeterminate .kt-bar__fill { width: 40%; animation: kt-slide 1.2s var(--kt-ease-standard) infinite; }
@keyframes kt-slide { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
.kt-spinner { width: 20px; height: 20px; border-radius: var(--kt-radius-full); border: var(--kt-border-w) solid var(--kt-border-default); border-top-color: var(--kt-action-indicator); animation: kt-spin 700ms linear infinite; }

/* Ảnh nghiệm thu trước và sau */
.kt-photos { display: grid; grid-template-columns: 1fr 1fr; gap: var(--kt-space-2); }
.kt-photo { border-radius: var(--kt-radius-md); border: var(--kt-border-w) solid var(--kt-border-strong); background: var(--kt-surface-sunken); display: flex; flex-direction: column; }
.kt-photo__label { border-radius: var(--kt-radius-sm); font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; padding: var(--kt-space-1) var(--kt-space-2); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); }
.kt-photo__slot { aspect-ratio: 4 / 3; display: flex; align-items: center; justify-content: center; font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
.kt-photo.is-empty { border-style: dashed; border-color: var(--kt-border-default); }
.kt-photo.is-empty .kt-photo__label { background: var(--kt-surface-sunken); color: var(--kt-text-tertiary); }

/* Chấm sao */
.kt-stars { display: inline-flex; align-items: center; gap: 2px; font-size: var(--kt-type-subtitle-size); line-height: 1; color: var(--kt-border-default); }
.kt-star { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.kt-stars--input .kt-star { min-width: var(--kt-tap-min); min-height: var(--kt-tap-min); }
.kt-star.is-on { color: var(--kt-accent-600); }
.kt-rating { display: inline-flex; align-items: center; gap: var(--kt-space-2); font-size: var(--kt-font-ui); }
.kt-rating__value { font-weight: var(--kt-weight-bold); font-variant-numeric: tabular-nums; }
.kt-rating--low { background: var(--kt-danger-bg); border: var(--kt-border-w) solid var(--kt-danger-border); color: var(--kt-danger-fg); padding: 2px var(--kt-space-2); font-weight: var(--kt-weight-bold); }
.kt-rating--low .kt-star.is-on { color: var(--kt-danger-fill); }

/* Tiền và thời lượng. Một định dạng duy nhất toàn hệ: 350.000 VNĐ. */
.kt-money { font-variant-numeric: tabular-nums; font-weight: var(--kt-weight-bold); white-space: nowrap; }
.kt-money__unit { font-weight: var(--kt-weight-semibold); font-size: 0.82em; margin-left: 0.22em; }
.kt-money--total { font-size: var(--kt-type-display-size); line-height: var(--kt-leading-tight); }
.kt-money--void { color: var(--kt-text-tertiary); text-decoration: line-through; }
.kt-duration { font-variant-numeric: tabular-nums; color: var(--kt-text-secondary); white-space: nowrap; }

/* ==========================================================================
   TRẠNG THÁI MÀN — rỗng, lỗi, đang tải
   ==========================================================================*/
.kt-empty, .kt-errorblock { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; align-items: flex-start; gap: var(--kt-space-2); padding: var(--kt-space-8) var(--kt-pad); background: var(--kt-surface); border: var(--kt-border-w) dashed var(--kt-border-default); }
.kt-empty__title, .kt-errorblock__title { font-size: var(--kt-type-subtitle-size); font-weight: var(--kt-weight-bold); }
.kt-empty__text, .kt-errorblock__text { font-size: var(--kt-font-ui); color: var(--kt-text-secondary); }
.kt-errorblock { border-style: solid; border-color: var(--kt-danger-border); background: var(--kt-danger-bg); }
.kt-errorblock__title { color: var(--kt-danger-fg); }

.kt-skel { border-radius: var(--kt-radius-sm); position: relative; overflow: hidden; background: var(--kt-surface-sunken); height: 1em; }
.kt-skel--line { height: 12px; }
.kt-skel--title { height: 20px; width: 60%; }
.kt-skel--block { height: 72px; }
.kt-skel::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, var(--kt-sheen), transparent); animation: kt-shimmer 1.2s infinite; }
@keyframes kt-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* ==========================================================================
   THÀNH PHẦN NGHIỆP VỤ
   Mười sáu khối chỉ có nghĩa với nền điều phối dịch vụ kỹ thuật. Nhãn và luật
   của chúng khai trong design-system.js, không gõ lại trong màn.
   ==========================================================================*/

/* Thẻ dịch vụ trong danh mục: biểu tượng, tên, thời lượng, giá khởi điểm */
.kt-svc { border-radius: var(--kt-radius-md); display: flex; align-items: center; gap: var(--kt-pad-tight); width: 100%; padding: var(--kt-pad-tight) var(--kt-pad); background: var(--kt-surface); box-shadow: var(--kt-surface-lift); border: var(--kt-surface-edge-w) solid var(--kt-border-subtle); font: inherit; color: inherit; text-align: left; cursor: pointer; transition: var(--kt-transition-color); }
.kt-svc:hover { border-color: var(--kt-border-strong); }
.kt-svc.is-selected { border-color: var(--kt-border-strong); background: var(--kt-surface-accent); }
.kt-svc__icon { border-radius: var(--kt-radius-md); display: inline-flex; align-items: center; justify-content: center; width: var(--kt-control-h); height: var(--kt-control-h); flex: none; color: var(--kt-text-brand); background: var(--kt-surface-accent); border: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-svc__main { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.kt-svc__name { font-size: var(--kt-font-ui); font-weight: var(--kt-weight-semibold); }
.kt-svc__meta { font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
.kt-svc__price { text-align: right; }
.kt-svc[disabled] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; }

/* Lưới giờ hẹn: ngày ở trên, ô giờ ở dưới */
.kt-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: var(--kt-space-2); }
.kt-slot { border-radius: var(--kt-radius-md); display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-height: var(--kt-control-h); padding: var(--kt-space-2); font: inherit; font-size: var(--kt-font-ui); font-weight: var(--kt-weight-semibold); color: var(--kt-text-primary); background: var(--kt-surface); border: var(--kt-border-w-hair) solid var(--kt-border-default); cursor: pointer; transition: var(--kt-transition-color); }
.kt-slot__note { font-size: var(--kt-type-caption-size); font-weight: var(--kt-weight-regular); color: var(--kt-text-tertiary); }
.kt-slot:hover { border-color: var(--kt-border-strong); }
.kt-slot.is-selected { border: var(--kt-border-w) solid var(--kt-border-strong); background: var(--kt-surface-accent); }
.kt-slot[disabled] { opacity: var(--kt-state-disabled-opacity); cursor: not-allowed; text-decoration: line-through; }
.kt-slot--soonest { border-left: var(--kt-border-w-thick) solid var(--kt-action-indicator); }

/* Thẻ thợ: một hình thức duy nhất dùng ở cả ba cửa */
.kt-tech { border-radius: var(--kt-radius-lg); display: flex; align-items: flex-start; gap: var(--kt-pad-tight); padding: var(--kt-pad-tight); background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-subtle); }
.kt-tech__main { display: flex; flex-direction: column; gap: var(--kt-space-1); flex: 1; min-width: 0; }
.kt-tech__name { font-size: var(--kt-font-ui); font-weight: var(--kt-weight-bold); }
.kt-tech__line { display: flex; align-items: center; gap: var(--kt-space-3); flex-wrap: wrap; }
.kt-tech__dist { font-size: var(--kt-type-label-size); color: var(--kt-text-secondary); font-variant-numeric: tabular-nums; }
.kt-tech--suggested { border-color: var(--kt-border-strong); box-shadow: inset var(--kt-border-w-thick) 0 0 var(--kt-action-indicator); }

/* Bốn chỉ số chất lượng thợ, máy tự đo từ đơn */
.kt-quality { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-quality__row { display: grid; grid-template-columns: 1fr 68px 44px; align-items: center; gap: var(--kt-space-2); font-size: var(--kt-type-label-size); }
.kt-quality__track { border-radius: var(--kt-radius-pill); height: 6px; background: var(--kt-surface-sunken); border: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-quality__fill { border-radius: var(--kt-radius-pill); display: block; height: 100%; background: var(--kt-success-fill); }
.kt-quality__row.is-weak .kt-quality__fill { background: var(--kt-danger-fill); }
.kt-quality__val { text-align: right; font-weight: var(--kt-weight-bold); font-variant-numeric: tabular-nums; }

/* Đồng hồ bậc hoa hồng: ba bậc, vị trí hiện tại, còn mấy đơn lên bậc */
.kt-tier { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-tier__bars { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-space-1); }
.kt-tier__bar { border-radius: var(--kt-radius-pill); height: var(--kt-space-2); background: var(--kt-surface-sunken); border: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-tier__bar.is-reached { background: var(--kt-brand-900); border-color: var(--kt-brand-900); }
.kt-tier__bar.is-current { background: var(--kt-action-indicator); border-color: var(--kt-accent-700); }
.kt-tier__legend { display: flex; justify-content: space-between; font-size: var(--kt-type-caption-size); color: var(--kt-text-tertiary); }

/* Bảo hành: viên thuốc có đếm ngày, ba mức */
.kt-warranty { border-radius: var(--kt-radius-md); display: inline-flex; align-items: center; gap: var(--kt-space-2); padding: 2px var(--kt-space-2); font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold); border: var(--kt-border-w-hair) solid currentColor; }
.kt-warranty--active { color: var(--kt-success-fg); background: var(--kt-success-bg); }
.kt-warranty--expiring { color: var(--kt-warning-fg); background: var(--kt-warning-bg); }
.kt-warranty--expired { color: var(--kt-text-tertiary); background: var(--kt-surface-sunken); text-decoration: line-through; }

/* Đồng hồ hạn giờ hẹn, ba mức, dùng ở buồng lái và cửa thợ */
.kt-sla { border-radius: var(--kt-radius-md); display: inline-flex; align-items: center; gap: var(--kt-space-1); padding: 2px var(--kt-space-2); font-size: var(--kt-type-caption-size); font-weight: var(--kt-weight-bold); font-variant-numeric: tabular-nums; border: var(--kt-border-w-hair) solid currentColor; }
.kt-sla--ok { color: var(--kt-text-secondary); }
.kt-sla--warn { color: var(--kt-warning-fg); background: var(--kt-warning-bg); }
.kt-sla--late { color: var(--kt-danger-fg); background: var(--kt-danger-bg); }

/* Mời nhận đơn: có vạch đếm ngược tự rút, hết thì đơn trả về hàng đợi */
.kt-invite { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-strong); }
.kt-invite__timer { border-radius: var(--kt-radius-sm); height: var(--kt-space-2); background: var(--kt-surface-sunken); }
.kt-invite__timer > span { display: block; height: 100%; background: var(--kt-danger-fill); transition: width 250ms linear; }
.kt-invite__head { display: flex; align-items: center; justify-content: space-between; gap: var(--kt-space-2); padding: var(--kt-pad-tight) var(--kt-pad); border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-invite__body { padding: var(--kt-pad); display: flex; flex-direction: column; gap: var(--kt-pad-tight); }
.kt-invite__actions { display: flex; flex-direction: column; gap: var(--kt-space-2); padding: 0 var(--kt-pad) var(--kt-pad); }

/* Luật gửi xe theo toà: khối chữ có biểu tượng, không phải đoạn văn trơn */
.kt-parking { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; gap: var(--kt-space-2); padding: var(--kt-pad-tight); background: var(--kt-surface-accent); color: var(--kt-warning-fg); font-size: var(--kt-type-label-size); }
.kt-parking__row { display: flex; align-items: flex-start; gap: var(--kt-space-2); }
.kt-parking__key { color: var(--kt-text-secondary); min-width: 92px; }

/* Bảng bóc tách tiền: từng dòng cộng lại thành tổng, luôn có dòng tổng */
.kt-breakdown { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-breakdown__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--kt-space-3); font-size: var(--kt-font-ui); }
.kt-breakdown__row > span:first-child { color: var(--kt-text-secondary); }
.kt-breakdown__row--discount { color: var(--kt-success-fg); }
.kt-breakdown__total { display: flex; align-items: baseline; justify-content: space-between; gap: var(--kt-space-3); padding-top: var(--kt-space-2); border-top: var(--kt-border-w) solid var(--kt-border-strong); font-weight: var(--kt-weight-bold); }

/* Chọn cách trả tiền: ô lớn, một cột trên điện thoại */
.kt-pay { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-pay__tile { border-radius: var(--kt-radius-md); display: flex; align-items: center; gap: var(--kt-pad-tight); min-height: var(--kt-control-h); padding: var(--kt-space-2) var(--kt-pad-tight); background: var(--kt-surface); border: var(--kt-border-w-hair) solid var(--kt-border-default); cursor: pointer; font-size: var(--kt-font-ui); }
.kt-pay__tile:hover { border-color: var(--kt-border-strong); }
.kt-pay__tile.is-selected { border: var(--kt-border-w) solid var(--kt-border-strong); background: var(--kt-surface-accent); }
.kt-pay__tile > input { appearance: none; margin: 0; width: var(--kt-choice-size); height: var(--kt-choice-size); flex: none; border-radius: var(--kt-radius-full); border: var(--kt-border-w) solid var(--kt-border-strong); }
.kt-pay__tile > input:checked { border-width: calc(var(--kt-choice-size) * 0.28); }
.kt-qr { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; align-items: center; gap: var(--kt-space-2); padding: var(--kt-pad); background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-strong); }
.kt-qr__code { width: 168px; height: 168px; background: var(--kt-surface-sunken); border: var(--kt-border-w-hair) solid var(--kt-border-default); display: grid; place-content: center; color: var(--kt-text-tertiary); font-size: var(--kt-type-caption-size); }

/* Hoá đơn: danh sách dòng có số lượng và đơn giá */
.kt-invoice { display: flex; flex-direction: column; }
.kt-invoice__row { display: grid; grid-template-columns: 1fr 44px 96px; gap: var(--kt-space-2); padding: var(--kt-space-2) 0; border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); font-size: var(--kt-font-ui); }
.kt-invoice__row > :nth-child(2) { text-align: center; color: var(--kt-text-tertiary); font-variant-numeric: tabular-nums; }
.kt-invoice__row > :nth-child(3) { text-align: right; }

/* Sự vụ và khiếu nại: mức độ, hạn xử lý, người phụ trách */
.kt-case { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; gap: var(--kt-space-2); padding: var(--kt-pad-tight); background: var(--kt-surface); border-left: var(--kt-space-2) solid var(--kt-neutral-border); border-top: var(--kt-border-w-hair) solid var(--kt-border-subtle); border-right: var(--kt-border-w-hair) solid var(--kt-border-subtle); border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-case--high { border-left-color: var(--kt-danger-fill); }
.kt-case--mid { border-left-color: var(--kt-warning-fill); }
.kt-case__head { display: flex; align-items: center; justify-content: space-between; gap: var(--kt-space-2); }
.kt-case__id { font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold); font-variant-numeric: tabular-nums; }

/* Chọn địa bàn năm cấp: dòng thụt theo cấp, cấp ghi đè có cờ */
.kt-addr { border-radius: var(--kt-radius-lg); display: flex; flex-direction: column; background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-subtle); }
.kt-addr__row { display: flex; align-items: center; gap: var(--kt-space-2); min-height: var(--kt-row-h); padding: var(--kt-space-2) var(--kt-pad-tight); border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); font: inherit; font-size: var(--kt-font-ui); color: inherit; background: transparent; border-left: 0; border-right: 0; border-top: 0; text-align: left; cursor: pointer; width: 100%; }
.kt-addr__row:last-child { border-bottom: 0; }
.kt-addr__row:hover { background: var(--kt-surface-sunken); }
.kt-addr__row.is-selected { background: var(--kt-accent-100); box-shadow: inset var(--kt-border-w-thick) 0 0 var(--kt-action-indicator); }
.kt-addr__row[data-level="2"] { padding-left: calc(var(--kt-pad-tight) + var(--kt-space-5)); }
.kt-addr__row[data-level="3"] { padding-left: calc(var(--kt-pad-tight) + var(--kt-space-10)); }
.kt-addr__row[data-level="4"] { padding-left: calc(var(--kt-pad-tight) + var(--kt-space-12)); }
.kt-addr__row[data-level="5"] { padding-left: calc(var(--kt-pad-tight) + var(--kt-space-16)); }
.kt-addr__meta { margin-left: auto; font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }

/* Hàng chờ đồng bộ khi thợ mất mạng */
.kt-queue { border-radius: var(--kt-radius-lg); display: flex; align-items: center; gap: var(--kt-space-2); padding: var(--kt-space-2) var(--kt-pad-tight); background: var(--kt-neutral-bg); color: var(--kt-neutral-fg); font-size: var(--kt-type-label-size); border: var(--kt-border-w-hair) dashed var(--kt-neutral-border); }
.kt-queue__count { font-weight: var(--kt-weight-bold); font-variant-numeric: tabular-nums; }

/* Ảnh nghiệm thu bắt buộc: thiếu thì viền đỏ và có chữ nhắc */
.kt-photos.is-required .kt-photo.is-empty { border-color: var(--kt-border-error); }
.kt-photos.is-required .kt-photo.is-empty .kt-photo__label { background: var(--kt-danger-bg); color: var(--kt-danger-fg); }

/* Chỗ đặt tin báo nổi do KT.ui.toast dựng ra */
.kt-toast-host { position: fixed; left: 50%; transform: translateX(-50%); bottom: var(--kt-space-5); z-index: var(--kt-z-toast); display: flex; flex-direction: column; gap: var(--kt-space-2); width: min(520px, calc(100vw - 32px)); }

/* ==========================================================================
   LỚP VĂN BẢN DÀI
   Thang chữ giao diện không dùng được cho bài viết: câu dài cần cỡ lớn hơn,
   dòng thưa hơn, bề rộng vùng đọc hẹp hơn. Đây là lớp riêng cho bài viết,
   trang giới thiệu, sổ tay và tài liệu in.
   ==========================================================================*/
.kt-article { max-width: 720px; margin: 0 auto; padding: var(--kt-space-8) var(--kt-pad); }
.kt-article--wide { max-width: 960px; }
.kt-kicker { font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; color: var(--kt-text-accent); }
.kt-headline-xl { font-size: clamp(28px, 4.4vw, 44px); line-height: 1.12; font-weight: var(--kt-weight-bold); letter-spacing: -0.015em; }
.kt-lede { font-size: 19px; line-height: 1.6; color: var(--kt-text-secondary); max-width: 62ch; }
.kt-byline { display: flex; align-items: center; gap: var(--kt-space-3); font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }

.kt-prose { font-size: 17px; line-height: 1.7; color: var(--kt-text-primary); max-width: 68ch; }
.kt-prose > * + * { margin-top: var(--kt-space-5); }
.kt-prose h2 { font-size: 26px; line-height: 1.25; margin-top: var(--kt-space-10); }
.kt-prose h3 { font-size: 20px; line-height: 1.3; margin-top: var(--kt-space-8); }
.kt-prose h2 + p, .kt-prose h3 + p { margin-top: var(--kt-space-3); }
.kt-prose p { max-width: 68ch; }
.kt-prose strong { font-weight: var(--kt-weight-bold); }
.kt-prose a { color: var(--kt-text-link); text-decoration: underline; text-underline-offset: 3px; }
.kt-prose ul, .kt-prose ol { padding-left: var(--kt-space-6); display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-prose li { padding-left: var(--kt-space-1); }
.kt-prose hr { height: 0; border: 0; border-top: var(--kt-border-w) solid var(--kt-border-strong); margin: var(--kt-space-10) 0; }
.kt-prose table { width: 100%; border-collapse: collapse; font-size: var(--kt-type-body-size); }
.kt-prose th { text-align: left; font-size: var(--kt-type-overline-size); letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; border-bottom: var(--kt-border-w) solid var(--kt-border-strong); padding: var(--kt-space-2) var(--kt-space-3) var(--kt-space-2) 0; }
.kt-prose td { border-bottom: var(--kt-border-w-hair) solid var(--kt-border-subtle); padding: var(--kt-space-3) var(--kt-space-3) var(--kt-space-3) 0; vertical-align: top; }
.kt-prose--compact { font-size: var(--kt-type-body-size); line-height: 1.62; }

.kt-quote { border-left: var(--kt-border-w-thick) solid var(--kt-border-strong); padding-left: var(--kt-pad); font-size: 20px; line-height: 1.5; }
.kt-quote__by { display: block; margin-top: var(--kt-space-2); font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); }
.kt-figure { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-figcaption { font-size: var(--kt-type-label-size); color: var(--kt-text-tertiary); border-left: var(--kt-border-w) solid var(--kt-border-subtle); padding-left: var(--kt-space-3); }
.kt-callout { border-radius: var(--kt-radius-md); display: flex; flex-direction: column; gap: var(--kt-space-2); padding: var(--kt-pad); background: var(--kt-surface-accent); border-left: var(--kt-space-2) solid var(--kt-border-strong); font-size: var(--kt-type-body-size); }
.kt-callout__title { font-weight: var(--kt-weight-bold); }
.kt-toc { display: flex; flex-direction: column; gap: var(--kt-space-2); padding: var(--kt-pad); background: var(--kt-surface-sunken); font-size: var(--kt-type-body-size); }
.kt-steps { counter-reset: kt-step; display: flex; flex-direction: column; gap: var(--kt-space-4); --kt-step-size: 34px; }
[data-kt-density="compact"] .kt-steps, .kt-mode-admin .kt-steps { --kt-step-size: 26px; gap: var(--kt-space-3); }
.kt-steps > li { counter-increment: kt-step; display: block; list-style: none; padding: 0; line-height: 1.6; text-wrap: pretty; overflow-wrap: break-word; }
.kt-steps > li::after { content: ""; display: block; clear: both; }
/* Câu dẫn in đậm nằm riêng một dòng, để phần giải thích không bị ngắt lẻ chữ. */
.kt-steps > li > b:first-child { display: block; margin-bottom: 2px; }
.kt-steps > li::before { content: counter(kt-step); float: left; margin: 2px var(--kt-space-3) var(--kt-space-1) 0; display: grid; place-items: center; width: var(--kt-step-size); height: var(--kt-step-size); background: var(--kt-surface-inverse); color: var(--kt-text-on-inverse); font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold); }

/* Khung màn */
.kt-screen { display: flex; flex-direction: column; min-height: 100%; }
.kt-screen__body { flex: 1; padding: var(--kt-pad); display: flex; flex-direction: column; gap: var(--kt-gap); }

/* ==========================================================================
   TÔN TRỌNG THIẾT LẬP NGƯỜI DÙNG
   ==========================================================================*/
@media (prefers-reduced-motion: reduce) {
  .kt-app *, .kt-app *::before, .kt-app *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}
@media (prefers-contrast: more) {
  :root { --kt-border-default: var(--kt-brand-900); --kt-text-secondary: var(--kt-brand-900); --kt-text-tertiary: var(--kt-slate-900); }
}
@media print {
  .kt-app { background: var(--kt-white); }
  .kt-tabbar, .kt-appbar, .kt-toast, .kt-sheet, .kt-scrim, .kt-drawer { display: none !important; }
  .kt-badge, .kt-flag, .kt-nhan { border-color: var(--kt-black) !important; color: var(--kt-black) !important; background: transparent !important; }
}

/* Ô lịch trong bảng điều phối theo giờ: trống, đang có đơn, hoặc đích để phân đơn đang giữ */
.kt-cell { display: block; width: 100%; min-height: 30px; padding: 3px 6px; font: inherit; font-size: var(--kt-type-caption-size); font-weight: var(--kt-weight-bold); text-align: left; color: var(--kt-text-tertiary); background: transparent; border: var(--kt-border-w-hair) dashed var(--kt-border-subtle); cursor: default; }
.kt-cell--busy { color: var(--kt-info-fg); background: var(--kt-info-bg); border: var(--kt-border-w) solid var(--kt-info-border); }
.kt-cell--target { color: var(--kt-accent-800); background: var(--kt-accent-100); border: var(--kt-border-w) dashed var(--kt-border-accent); cursor: pointer; }
.kt-cell--target:hover { background: var(--kt-accent-200); }

/* ── Biểu đồ ─────────────────────────────────────────────────────────────
   Bo góc 0 như mọi thứ khác. Không dải màu chuyển, không khối nổi, không
   hình tròn. Màu lấy từ token trạng thái tầng 2, và chỉ chỗ gọi mới được
   khai trạng thái: hình KHÔNG tự suy tốt xấu từ dấu của con số.

   Cột và chấm dựng bằng HTML, không bằng SVG. Hai lý do, cả hai đã trả
   giá: SVG ở đây kéo giãn tự do theo bề ngang thẻ nên mọi chữ vẽ trong nó
   đều méo, tức hình không mang nổi một cái nhãn số nào; và thẻ dẫn bọc
   quanh một hình SVG thì dính luật display:contents, thứ đã giết mọi cột
   có số suốt từ ngày dựng. Nét đường vẫn là SVG, vì nét là toạ độ. */
.kt-chart { --kt-chart-h: 160px;
  display: flex; flex-direction: column; gap: var(--kt-space-2); margin: 0; }
.kt-chart__title { font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold); color: var(--kt-text-primary); }
.kt-chart__meta { color: var(--kt-text-tertiary); }

/* Khung đo: trục giá trị bên trái, sàn vẽ, trục kỳ bên dưới. Chừa lề trên
   cho nhãn số đứng trên đầu cột cao nhất. */
.kt-chart__khung { display: grid; grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--kt-space-2); row-gap: var(--kt-space-1); padding-top: var(--kt-space-4); }
.kt-chart__truc-y { display: flex; flex-direction: column; justify-content: space-between;
  align-items: flex-end; height: var(--kt-chart-h); font-size: var(--kt-type-caption-size);
  line-height: 1; color: var(--kt-text-tertiary); font-variant-numeric: tabular-nums; }
.kt-chart__san { position: relative; height: var(--kt-chart-h); }
.kt-chart__luoi { position: absolute; inset: 0; display: flex; flex-direction: column;
  justify-content: space-between; pointer-events: none; }
.kt-chart__luoi > i { display: block; border-top: var(--kt-border-w-hair) solid var(--kt-border-subtle); }
.kt-chart__luoi > i:last-child { border-top-color: var(--kt-border-default); }

/* Cột. `min-height` để một con số bé xíu khác không vẫn nhìn thấy được:
   một cột mỏng hơn nét kẻ đọc ra y hệt không có cột nào. */
.kt-chart__cots { position: absolute; inset: 0; display: flex; align-items: flex-end; gap: var(--kt-space-1); }
.kt-chart__o { position: relative; flex: 1 1 0; min-width: 0; height: 100%; }
.kt-chart__cot { position: absolute; left: 0; right: 0; background: var(--kt-text-brand);
  min-height: var(--kt-border-w-thick); }
.kt-chart__cot.is-can { background: var(--kt-warning-fill); }
.kt-chart__cot.is-chan { background: var(--kt-danger-fill); }
.kt-chart__cot.is-yen { background: var(--kt-success-fill); }
/* Kỳ không đo được: khối mờ suốt chiều cao, KHÔNG phải cột cao 0. Cột cao
   0 đọc ra là "tháng ấy bằng không", tức bịa ra một con số chưa từng đo. */
.kt-chart__rong { position: absolute; inset: 0; background: var(--kt-surface-sunken); opacity: .55; }
.kt-chart__so { position: absolute; left: 0; right: 0; text-align: center; line-height: 1;
  padding-bottom: var(--kt-space-1); font-size: var(--kt-type-caption-size);
  color: var(--kt-text-secondary); font-variant-numeric: tabular-nums; }

/* Nét đường và chấm. Chấm vuông chứ không tròn, đúng luật bo góc 0. */
.kt-chart__ve { position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: visible; }
.kt-chart__duong { fill: none; stroke: var(--kt-text-brand); stroke-width: 2; vector-effect: non-scaling-stroke; }
.kt-chart__duong.is-can { stroke: var(--kt-warning-fill); }
.kt-chart__duong.is-chan { stroke: var(--kt-danger-fill); }
.kt-chart__duong.is-yen { stroke: var(--kt-success-fill); }
.kt-chart__diem { position: absolute; width: var(--kt-space-5); height: var(--kt-space-5);
  margin: 0 0 calc(var(--kt-space-5) / -2) calc(var(--kt-space-5) / -2);
  display: flex; align-items: center; justify-content: center; }
.kt-chart__diem > i { display: block; width: var(--kt-space-2); height: var(--kt-space-2);
  background: var(--kt-text-brand); outline: var(--kt-border-w) solid var(--kt-surface); }
.kt-chart__duong.is-day-1 { stroke: var(--kt-brand-900); }
.kt-chart__duong.is-day-2 { stroke: var(--kt-brand-700); }
.kt-chart__duong.is-day-3 { stroke: var(--kt-brand-500); }
.kt-chart__duong.is-day-4 { stroke: var(--kt-brand-300); }
.kt-chart__duong.is-day-5 { stroke: var(--kt-brand-200); }
.kt-chart__diem.is-day-1 > i { background: var(--kt-brand-900); }
.kt-chart__diem.is-day-2 > i { background: var(--kt-brand-700); }
.kt-chart__diem.is-day-3 > i { background: var(--kt-brand-500); }
.kt-chart__diem.is-day-4 > i { background: var(--kt-brand-300); }
.kt-chart__diem.is-day-5 > i { background: var(--kt-brand-200); }
.kt-chart__diem.is-can > i { background: var(--kt-warning-fill); }
.kt-chart__diem.is-chan > i { background: var(--kt-danger-fill); }
.kt-chart__diem.is-yen > i { background: var(--kt-success-fill); }

/* Vạch ngưỡng, nét đứt, nằm trong sàn. */
.kt-chart__moc { position: absolute; left: 0; right: 0;
  border-top: var(--kt-border-w) dashed var(--kt-text-tertiary); pointer-events: none; }
.kt-chart__moc-nhan { position: absolute; right: 0; padding-bottom: var(--kt-space-1);
  color: var(--kt-text-tertiary); background: var(--kt-surface); }

/* Trục kỳ. Nhãn nào bị thưa đi thì để lại một ô RỖNG chứ không dồn hàng:
   ô rỗng giữ cho nhãn còn lại đứng thẳng cột với cái nó nói về. */
.kt-chart__truc { grid-column: 2; display: flex; gap: var(--kt-space-1); }
.kt-chart__truc > .kt-chart__nhan { flex: 1 1 0; min-width: 0; text-align: center;
  font-size: var(--kt-type-caption-size); color: var(--kt-text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Đã thưa thì cho nhãn TRÀN khỏi ô của nó: ô bên cạnh đang rỗng nên không
   đè ai, còn cắt "02/26" thành "02/…" thì cái trục ghi một chuỗi không ai
   đọc ra — mất nhãn đắt hơn nhiều so với thừa vài pixel. */
.kt-chart__truc.is-thua > .kt-chart__nhan { overflow: visible; }
/* Màn hẹp thì thưa thêm một nấc nữa. Hệ đã thưa theo SỐ KỲ ở lúc dựng,
   nhưng số kỳ không biết gì về bề ngang: mười hai kỳ vừa vặn trong một thẻ
   nửa màn hình để bàn lại chen chúc trong 390px. Bỏ nhãn ở vị trí xen kẽ
   và GIỮ CHỖ (visibility) chứ không gỡ khỏi hàng, để nhãn còn lại vẫn đứng
   thẳng cột với cái nó nói về. Kỳ cuối luôn sống sót vì phép đếm bắt đầu
   từ ô thứ hai. */
@media (max-width: 560px) {
  .kt-chart__truc.is-thua > .kt-chart__nhan:nth-child(4n + 2) { visibility: hidden; }
}

/* Chỗ bấm được của một điểm. `display: contents` chỉ đúng cho thẻ dẫn nằm
   trong HTML thường; bên trong SVG nó cắt luôn con khỏi cây vẽ. Khai chung
   một luật cho cả hai chỗ đã giết mọi cột và mọi chấm CÓ SỐ, trong khi ô
   "chưa đo được" không bọc thẻ dẫn nên vẫn hiện: hình vẽ ra đúng phần nó
   không đo được. Nên luật khai theo đúng chỗ nó đúng. */
.kt-chart__di { cursor: pointer; }
.kt-chart__xep > .kt-chart__di, .kt-chart__o > .kt-chart__di,
.kt-chart__hang > .kt-chart__di { display: contents; }
.kt-chart__di:focus-visible .kt-chart__cot,
.kt-chart__di:focus-visible .kt-chart__diem > i {
  outline: var(--kt-focus-ring-w) solid var(--kt-border-focus); outline-offset: var(--kt-focus-ring-offset); }

/* Thanh chồng. Phần nào không tự khai trạng thái thì nhận một bậc sắc độ
   theo thứ tự: bốn phần cùng một màu mực thì cái thanh không tách được
   phần nào với phần nào, và người đọc phải bỏ hình mà xuống đếm dòng chú
   thích. Sắc độ chỉ để tách, nó không khen và không chê ai. */
.kt-chart__xep { display: flex; width: 100%; height: var(--kt-space-6);
  background: var(--kt-surface-sunken); overflow: hidden; }
.kt-chart__phan { display: block; height: 100%; background: var(--kt-text-brand); }
.kt-chart__phan.is-can { background: var(--kt-warning-fill); }
.kt-chart__phan.is-chan { background: var(--kt-danger-fill); }
.kt-chart__phan.is-yen { background: var(--kt-success-fill); }
.kt-chart__phan.is-day-1 { background: var(--kt-brand-900); }
.kt-chart__phan.is-day-2 { background: var(--kt-brand-700); }
.kt-chart__phan.is-day-3 { background: var(--kt-brand-500); }
.kt-chart__phan.is-day-4 { background: var(--kt-brand-300); }
.kt-chart__phan.is-day-5 { background: var(--kt-brand-200); }
.kt-chart__phan + .kt-chart__phan { border-left: var(--kt-border-w-hair) solid var(--kt-surface); }
.kt-chart__chu { display: flex; flex-wrap: wrap; gap: var(--kt-space-2) var(--kt-space-4); list-style: none; margin: 0; padding: 0; }
.kt-chart__chu-muc { display: inline-flex; align-items: center; gap: var(--kt-space-2); font-size: var(--kt-type-label-size); }
.kt-chart__o-mau { width: 10px; height: 10px; background: var(--kt-text-brand); }
.kt-chart__chu-muc.is-can .kt-chart__o-mau { background: var(--kt-warning-fill); }
.kt-chart__chu-muc.is-chan .kt-chart__o-mau { background: var(--kt-danger-fill); }
.kt-chart__chu-muc.is-yen .kt-chart__o-mau { background: var(--kt-success-fill); }
.kt-chart__chu-muc.is-day-1 .kt-chart__o-mau { background: var(--kt-brand-900); }
.kt-chart__chu-muc.is-day-2 .kt-chart__o-mau { background: var(--kt-brand-700); }
.kt-chart__chu-muc.is-day-3 .kt-chart__o-mau { background: var(--kt-brand-500); }
.kt-chart__chu-muc.is-day-4 .kt-chart__o-mau { background: var(--kt-brand-300); }
.kt-chart__chu-muc.is-day-5 .kt-chart__o-mau { background: var(--kt-brand-200); }

/* Thanh xếp hạng ngang. Vạch ngưỡng vẽ THẬT lên thanh: một cái vạch nói ra
   ai vượt chỉ bằng cách nhìn, còn một dòng chữ "Vạch: 3.000.000 VNĐ" bắt
   người đọc so nhẩm mười lăm lần rồi vẫn không chắc. */
.kt-chart__hangs { display: flex; flex-direction: column; gap: var(--kt-space-2); }
.kt-chart__hang { display: grid; grid-template-columns: minmax(0, 9rem) minmax(0, 1fr) auto; align-items: center; gap: var(--kt-space-3); }
.kt-chart__hang-ten { display: flex; flex-direction: column; min-width: 0;
  font-size: var(--kt-type-label-size); line-height: var(--kt-leading-snug); }
.kt-chart__hang-ten, .kt-chart__hang-phu { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kt-chart__hang-phu { color: var(--kt-text-tertiary); }
.kt-chart__hang-thanh { position: relative; display: block; height: var(--kt-space-4); background: var(--kt-surface-sunken); }
.kt-chart__hang-thanh > span { display: block; height: 100%; background: var(--kt-text-brand); }
.kt-chart__hang-moc { position: absolute; top: 0; bottom: 0;
  border-left: var(--kt-border-w) dashed var(--kt-text-primary); }
.kt-chart__hang.is-can .kt-chart__hang-thanh > span { background: var(--kt-warning-fill); }
.kt-chart__hang.is-chan .kt-chart__hang-thanh > span { background: var(--kt-danger-fill); }
.kt-chart__hang.is-yen .kt-chart__hang-thanh > span { background: var(--kt-success-fill); }
.kt-chart__hang-so { font-variant-numeric: tabular-nums; font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-semibold); white-space: nowrap; }

/* Chỗ đứng của đường xử lý trong khối báo tin. Bốn mức báo tin dùng chung
   hai lớp này, xem `render.baoTin`. Mức `chan` bắt buộc có, vì nói ra một
   chỗ bị chặn mà không chỉ được làm gì tiếp là chưa xong việc.
   BẪY vừa vấp: grep `kt-banner__act` khớp trúng `.kt-banner__action` đã có
   sẵn (một lớp khác hẳn, đẩy nút sang phải), nên em tưởng mình khai trùng
   rồi gỡ đi mất. Khớp tiền tố không phải khớp tên. */
.kt-banner__act { display: flex; flex-wrap: wrap; gap: var(--kt-space-2); margin-top: var(--kt-space-2); }
.kt-empty__act { display: flex; flex-wrap: wrap; gap: var(--kt-space-2); margin-top: var(--kt-space-1); }

/* ==========================================================================
   CHÚ GIẢI · ba tầng
   Hòn đá thứ ba của nền móng đã có hai hòn: luật đường xử lý (màn nói ra một
   vấn đề thì phải chỉ được đường xử) và luật con số sống (màn nói ra một con
   số thì phải chỉ được nó từ đâu ra). Luật này: màn bày ra một thứ thì phải
   khai được nó là gì và người đọc được lợi gì.
   CHỮ thuộc về Worker, ở đây chỉ có HÌNH.
   ==========================================================================*/

/* ── Tầng 1 · thẻ cửa tự giới thiệu ─────────────────────────────────────
   Nằm TRONG dòng chảy của màn, không phải tấm phủ chào mừng. Tấm phủ chặn
   mất màn hình đúng lúc người ta đang có việc gấp, và chạy được đúng một
   lần. Thẻ này đóng được, mở lại được, và không giành chỗ khi đã đóng. */
.kt-guide { border-radius: var(--kt-radius-md); display: flex; flex-direction: column; gap: var(--kt-space-3);
  padding: var(--kt-pad); background: var(--kt-surface-accent);
  border-left: var(--kt-space-2) solid var(--kt-border-strong); }
.kt-guide__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--kt-space-4); }
.kt-guide__q { font-size: var(--kt-type-body-size); font-weight: var(--kt-weight-bold); line-height: 1.45; text-wrap: pretty; }
.kt-guide__body { display: flex; flex-direction: column; gap: var(--kt-space-3); }
.kt-guide__row { display: grid; grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr); gap: var(--kt-space-2) var(--kt-space-4); align-items: start; }
@media (max-width: 640px) { .kt-guide__row { grid-template-columns: minmax(0, 1fr); gap: 2px; } }
.kt-guide__k { font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold);
  letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; color: var(--kt-text-tertiary); padding-top: 2px; }
.kt-guide__v { font-size: var(--kt-type-body-size); line-height: 1.6; color: var(--kt-text-primary); text-wrap: pretty; }
/* Tầm nhìn: cửa nhiều tầm nhìn thì mỗi tầm nhìn tự nói nó trả lời câu gì.
   Không có dòng này thì hai tầm nhìn cạnh nhau chỉ là hai cái nhãn. */
.kt-guide__views { display: flex; flex-direction: column; gap: var(--kt-space-2);
  padding-top: var(--kt-space-3); border-top: var(--kt-border-w-hair) solid var(--kt-border-default); }
.kt-guide__view { display: grid; grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr); gap: var(--kt-space-4); font-size: var(--kt-type-label-size); line-height: 1.55; }
@media (max-width: 640px) { .kt-guide__view { grid-template-columns: minmax(0, 1fr); gap: 0; } }
.kt-guide__view b { font-weight: var(--kt-weight-semibold); }
/* Thẻ thiếu ô bắt buộc thì MANG DẤU trên màn, không im. Cùng luật với khối
   báo tin thiếu `vi`: chú giải giữ chỗ còn tệ hơn không có chú giải, vì nó
   trông như đã xong. */
.kt-guide.is-thieu { border-left-color: var(--kt-danger-border); background: var(--kt-danger-bg); }

/* ── Tầng 2 và 3 · chữ có nghĩa, và vị trí tự khai vai ───────────────────
   `title=` KHÔNG dùng được: không chạm được trên điện thoại, không đọc được
   bằng bàn phím, và không đo được ai đã mở. Ba lý do, mỗi lý do đủ để loại. */
.kt-term { position: relative; display: inline; padding: 0; margin: 0; font: inherit; color: inherit;
  background: none; border: 0; border-bottom: var(--kt-border-w) dotted var(--kt-border-strong);
  cursor: help; text-align: left; }
.kt-term:hover, .kt-term[aria-expanded="true"] { background: var(--kt-surface-accent); }
.kt-term[aria-expanded="true"] { border-bottom-style: solid; }
/* Nút chú giải vị trí: đứng cạnh nhãn của ô số hay đầu bảng, nên nó phải
   nhỏ hơn chữ quanh nó mà vẫn bấm được. */
.kt-note { position: relative; display: inline-flex; align-items: center; gap: 3px;
  padding: 2px var(--kt-space-2); margin-left: var(--kt-space-2); font: inherit;
  font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold);
  letter-spacing: var(--kt-tracking-caps); text-transform: uppercase;
  color: var(--kt-text-tertiary); background: transparent;
  border: var(--kt-border-w-hair) solid var(--kt-border-default); cursor: pointer; }
.kt-note:hover, .kt-note[aria-expanded="true"] { color: var(--kt-text-primary);
  background: var(--kt-surface-accent); border-color: var(--kt-border-strong); }

/* Khối bung. Neo tuyệt đối vào chữ, JS tự lật khi tràn khung nhìn.
   Một cái một lúc, đúng luật của hộp thoại. */
.kt-pop { position: absolute; z-index: var(--kt-z-popover); top: calc(100% + var(--kt-space-1)); left: 0;
  width: min(22rem, calc(100vw - var(--kt-space-8))); display: flex; flex-direction: column; gap: var(--kt-space-3);
  padding: var(--kt-pad); text-align: left; white-space: normal; font-weight: var(--kt-weight-regular);
  letter-spacing: normal; text-transform: none;
  background: var(--kt-surface); border: var(--kt-border-w) solid var(--kt-border-strong);
  box-shadow: var(--kt-shadow-lg); cursor: auto; }
.kt-pop.is-phai { left: auto; right: 0; }
.kt-pop.is-tren { top: auto; bottom: calc(100% + var(--kt-space-1)); }
.kt-pop__chu { font-size: var(--kt-type-label-size); font-weight: var(--kt-weight-bold);
  color: var(--kt-text-brand); text-transform: none; letter-spacing: normal; }
.kt-pop__cau { font-size: var(--kt-type-body-size); line-height: 1.6; color: var(--kt-text-primary); text-wrap: pretty; }
.kt-pop__row { display: flex; flex-direction: column; gap: 2px; }
.kt-pop__k { font-size: var(--kt-type-overline-size); font-weight: var(--kt-weight-bold);
  letter-spacing: var(--kt-tracking-caps); text-transform: uppercase; color: var(--kt-text-tertiary); }
.kt-pop__v { font-size: var(--kt-type-label-size); line-height: 1.55; color: var(--kt-text-secondary); text-wrap: pretty; }
/* Vế "đừng lẫn với" là vế đắt nhất của một mục từ điển: năm cặp chữ trong
   hệ này lẫn nhau là năm con số sai đi ra ngoài. Nên nó được tô riêng. */
.kt-pop__row--lan { padding: var(--kt-space-2) var(--kt-space-3);
  background: var(--kt-warning-bg); border-left: var(--kt-border-w-thick) solid var(--kt-warning-border); }
.kt-pop__row--lan .kt-pop__k, .kt-pop__row--lan .kt-pop__v { color: var(--kt-warning-fg); }
.kt-pop__foot { display: flex; flex-wrap: wrap; gap: var(--kt-space-2); padding-top: var(--kt-space-2);
  border-top: var(--kt-border-w-hair) solid var(--kt-border-default); }

/* Dòng chữ có nghĩa dưới tiêu đề màn. Các nút chữ nằm trong một dòng văn nên
   phải xuống dòng được, và dấu chấm ngăn cách KHÔNG được dính vào nút kế khi
   dòng gãy — nó là chữ của người đọc, không phải viền của cái nút. */
.kt-chu-hang { display: block; line-height: 1.9; }
.kt-chu-cach { color: var(--kt-text-tertiary); padding: 0 2px; }
