/**
 * Design System v2 — Warm Modern Editorial
 *
 * Single source of truth for colors, typography, spacing, motion.
 * Import AFTER legacy tokens to override gradually.
 *
 * Aesthetic: 60% Airbnb UX + 25% Apartamento editorial rhythm + 15% Vietnamese earth warmth
 *
 * Usage (CSS):
 *   .my-component { color: var(--ds-ink); background: var(--ds-cream); }
 * Usage (Tailwind arbitrary):
 *   className="text-[var(--ds-ink)] bg-[var(--ds-cream)]"
 */

:root {
  /* ============================================================
     COLORS — Warm Modern Editorial palette
     ============================================================ */

  /* Primary palette */
  /* ═══ HE MAU JETBLACK + CANDY BLUE — sep chot 04/09 ═══════════════════════════════════
     Thay he cu "Warm Modern Editorial" (Dawn Tan #D4A574 + kem am). Moi gia tri duoi day
     chon bang SO, khong bang cam giac — quet dai xanh candy roi lay diem thoa DONG THOI ba
     rang buoc, va chi co mot vung hex lam duoc:
       (1) chu Jetblack tren nut  >= 4,5   -> can L(nen) >= 0,212
       (2) ranh gioi nut vs TRANG >= 3     -> WCAG 1.4.11, can L(nen) <= 0,30
       (3) ranh gioi nut vs NEN TRANG >= 3 -> chat hon (1), can L(nen) <= 0,278
     #0293DA: chu Jetblack 5,79 · vs trang 3,39 · vs nen 3,18 — dat ca ba.
     Sac tuoi hon (#56C5FF "dung chat keo" nhat) chi dat 1,94 o rang buoc (2) nen KHONG
     dung duoc o che do sang; no duoc dua xuong khoi TOI, noi no cho 10,14. */
  --ds-primary: #0293DA;          /* Candy Blue — nen nut, diem nhan */
  --ds-primary-hover: #0281C4;    /* candy dam hon 1 bac — chu Jetblack tren no 4,63 */
  --ds-primary-fg: #0B0B0D;       /* text on primary */
  /* Candy Blue lam MAU CHU tren nen sang. Ban nen (#0293DA) khong lam chu duoc: tren trang
     chi 3,39 — dung nguong 4,5 cho chu thuong. Gia tri nay dat 4/4 nen cua he:
       trang 5,93  ·  --ds-cream 5,56  ·  --ds-mist 5,04  ·  --ds-mist-hover 4,57
     CHI dung khi candy la CHU tren nen sang. Nen nut, vien, diem nhan giu --ds-primary.
     (Cung vai tro voi ban gold #8A5B24 cua he cu — doi 04/09 cung dot Jetblack + Candy.) */
  --ds-primary-ink: #0369A1;
  /* #253 — NỀN candy đậm cho chữ TRẮNG (gradient ở theme-overrides.css). Tách khỏi `-ink`/`-hover`
     vì hai token đó SÁNG LÊN ở chế độ tối (#7DD3FC): đo 30/09 nút "Đặt phòng" chữ trắng 1,67. */
  --ds-primary-deep: #0369A1;        /* chữ trắng 5,93 */
  --ds-primary-deep-hover: #0281C4;  /* = --ds-primary-hover bản sáng */

  /* TEN GIU NGUYEN vi 422 luot dung trong ma; GIA TRI nay khong con la xanh rung.
     Doi 04/09: #2D4A3E (xanh rung am) -> Jetblack surface. Doi ten token = sua 422 cho,
     khong dang; ai doc chi can biet day la "be mat toi" cua he. */
  --ds-forest: #16181D;           /* Jetblack surface — section toi, khoi nhan manh */
  --ds-forest-hover: #0B0B0D;
  --ds-forest-fg: #F5F8FA;        /* text on forest */

  /* Neutrals */
  --ds-bg: #FFFFFF;               /* white card/input surface */
  --ds-cream: #F5F8FA;            /* page background */
  --ds-mist: #E8EDF2;             /* surface, subtle cards */
  --ds-mist-hover: #DBE3EA;
  --ds-ink: #0B0B0D;              /* primary text */
  --ds-ink-soft: #33383F;         /* secondary text */
  /* #6c6963 chứ KHÔNG phải #78756E (bản cũ). Đo prod 31/08 trên nền THẬT của từng phần tử
     (canvas quy màu → rgb, công thức WCAG), bản cũ FAIL AA ở mọi nền trừ trắng:
       nền --ds-mist #F0EAE0 → 3,84 · nền xám nhạt → 4,39 · nền --ds-cream → 4,27 · trắng → 4,60
     Quy mô đo được: /vip 336 chỗ trên 28 nhóm class (riêng .nextcore-vip-group-insight 160 chỗ),
     /homestays 18, /dashboard/nextcore-credits 9. Trang /vip là trang BÁN HÀNG công khai.
     Đây là vi phạm quy tắc ĐÃ CÓ, không phải lựa chọn thẩm mỹ: `glass-depth-design` §5 đòi ≥4,5
     "đo tại điểm nền xấu nhất", ACL visual contract đòi "mọi ink tier đạt WCAG AA".
     Bản mới chỉ đậm hơn 10%, giữ nguyên tỉ lệ ba kênh nên sắc ấm không đổi:
       mist 4,57 · xám 5,23 · cream 5,08 · trắng 5,47 — đạt AA cả bốn.
     Phân cấp thị giác vẫn rõ: --ds-ink-soft #3D3A34 cho 9,47 trên cùng nền mist.
     Bản chế độ tối (#8A8579 trên #1E1B16) cho 4,71 — đã đạt, KHÔNG đụng. */
  /* 04/09 — do lai CA HAI che do tren 8 nen thuc te (bg/cream/mist + 5 nen -soft).
     Ban cu #6c6963 (sang): 4,48-5,47 => TRUOT tren info-soft, va bon nen -soft khac chi
     cach nguong 0,07-0,29 nen rat de vo khi ai do chinh mot sac -soft.
     Ban cu #8A8579 (toi): 3,02-5,05 => TRUOT ca NAM nen -soft.
     Gia tri moi lay tu `--ds-acl-ink-meta` — von da duoc chot trong hop dong thi giac ACL va
     do dat 8/8 o ca hai che do (5,74-7,01 sang · 5,02-8,38 toi). Khong phat minh mau moi.
     Van thap hon `--ds-ink-soft` (#3D3A34 / #D4CFC3) nen thu bac chu chinh/phu giu nguyen. */
  --ds-ink-muted: #555C66;        /* tertiary / caption */
  --ds-hairline: rgba(11, 11, 13, 0.08);  /* subtle borders */

  /* States */
  /* #282: #D9553F làm CHỮ chỉ 3,95 trên trắng (193 tệp dùng làm chữ) và chữ trắng trên nút cũng 3,95.
     #C2412D: trắng 5,14 · trên --ds-cream 4,88 — đạt 4,5 ở cả hai vai. */
  --ds-alert: #C2412D;            /* error, danger */
  --ds-alert-soft: #FCE8E2;
  --ds-success: #6B8E5A;          /* success, confirmed */
  --ds-success-soft: #E4EEDD;
  --ds-warning: #E0A545;
  --ds-warning-soft: #FAEFD7;
  --ds-info: #2563EB;             /* informational — links, neutral status, finance/invest UI */
  --ds-info-hover: #1D4ED8;
  --ds-info-soft: #DBEAFE;
  --ds-info-fg: #FFFFFF;          /* text on info */
  --ds-accent: #7C3AED;           /* secondary categorical accent (violet) */
  --ds-accent-hover: #6D28D9;
  --ds-accent-soft: #EDE9FE;
  --ds-accent-fg: #FFFFFF;        /* text on accent */

  /* MỰC trạng thái — dùng cho CHỮ đặt trên nền -soft cùng tông.
     Vì sao cần: màu trạng thái thuần làm chữ trên nền -soft cùng tông đều FAIL WCAG AA. Đo trên
     prod 2026-08-24 tại dải lịch nc-sheet: warning/warning-soft 1,84:1 · alert/alert-soft 3,34:1 ·
     success/success-soft 3,11:1 · info/mist 4,24:1 — chữ thường cần 4,5:1. Nặng nhất lại là 3/4
     chip chú giải, tức đúng chỗ DẠY người dùng đọc màu.
     Công thức lấy từ chỗ đã đạt trong repo (.nextcore-ext-ncsheet__result-brief-tag--extend, đo
     5,86:1): trộn 50% màu trạng thái với ink. Dùng cho CHỮ; giữ token thuần cho viền/nền/chấm —
     thành phần phi-văn-bản chỉ cần 3:1 và cần giữ độ tươi để phân biệt trạng thái. */
  --ds-success-ink: color-mix(in srgb, var(--ds-success) 50%, var(--ds-ink));
  --ds-alert-ink:   color-mix(in srgb, var(--ds-alert)   50%, var(--ds-ink));
  --ds-warning-ink: color-mix(in srgb, var(--ds-warning) 50%, var(--ds-ink));
  --ds-info-ink:    color-mix(in srgb, var(--ds-info)    50%, var(--ds-ink));
  /* accent-ink thêm 03/09: accent/accent-soft đạt 4,80 ở chế độ SÁNG nên trước đây trông như
     không cần — nhưng ở chế độ TỐI nền -soft hoá tối mà --ds-accent giữ nguyên #7C3AED, tụt
     còn 2,53. Đo trên prod bằng canvas + WCAG 2.x. Bốn -ink kia theo var(--ds-ink) nên tự lật
     theo chế độ; accent thiếu mục này là lỗ duy nhất còn lại của bộ. */
  --ds-accent-ink:  color-mix(in srgb, var(--ds-accent)  50%, var(--ds-ink));

  /* Photography overlays */
  --ds-scrim-dark: linear-gradient(180deg, rgba(11, 11, 13,0) 0%, rgba(11, 11, 13,0.6) 100%);

  /* ============================================================
     VAI TRÒ — 14 token DUY NHẤT cho code tính năng (thêm 2026-08-31)
     ============================================================

     VÌ SAO CÓ KHỐI NÀY. Đo 31/08: 202 token nền tảng, 26.806 lượt dùng — hệ token LÀNH
     (chỉ 17 token chết). Nhưng song song với nó là **979 lượt utility màu Tailwind**
     (`bg-gray-50`, `text-slate-400`) và **4.813 hex** trong CSS. Ba hệ màu cùng lúc.

     Nguyên nhân KHÔNG phải người viết lười. Token hiện tại đặt tên theo CHẤT LIỆU —
     `ink`, `mist`, `cream`, `hairline`, `forest`. Ai cần "nền hàng bảng khi rê chuột"
     phải tự dịch từ chất liệu sang vai trò, giữa 202 lựa chọn. Không dịch được thì gõ
     `bg-gray-50`. Khối này làm sẵn phép dịch đó.

     LUẬT DÙNG:
       · CSS TÍNH NĂNG (`src/styles/{scope}/`, `app/**`) chỉ được dùng 14 token dưới đây.
       · 202 token nền tảng phía trên dành cho PRIMITIVE (`design-system-v2/`,
         `styles/ext-core.css`, `styles/acl.css`, `styles/components/`) — xem `css-architecture.md`.
       · Cần một màu chưa có vai trò ⇒ THÊM VAI TRÒ ở đây, không gõ hex vào trang.

     TÊN: cố ý KHÔNG dùng `--ds-text-1/2/3` cho màu chữ — `--ds-text-*` ĐÃ LÀ CỠ CHỮ
     (`--ds-text-sm` = 0.875rem). Hai nghĩa chung một tiền tố chính là thứ sinh ra nhầm lẫn
     mà khối này dựng ra để diệt. Màu chữ = `--ds-fg-*` (foreground).

     Mọi token ở đây PHẢI có bản chế độ tối ở khối `[data-theme]` cuối tệp.
     Test chặn: `src/__tests__/design/role-tokens.test.ts`.

     GIÁ TRỊ: trỏ về token nền tảng ĐÃ ĐO WCAG ở trên — không đặt màu mới, không đổi diện mạo. */

  /* Nền theo độ cao (0 = xa nhất, 3 = nổi nhất) */
  --ds-surface-0: var(--ds-cream);        /* nền trang */
  --ds-surface-1: var(--ds-bg);           /* thẻ, panel, ô nhập */
  --ds-surface-2: var(--ds-mist);         /* khối chìm, chip meta, hàng phụ */
  --ds-surface-3: var(--ds-bg);           /* nổi trên cùng — popover, modal (kèm elevation) */

  /* Chữ theo thứ bậc — cả ba đã đạt WCAG AA trên surface-0/1/2 */
  --ds-fg-1: var(--ds-ink);               /* tiêu đề, số liệu chính */
  --ds-fg-2: var(--ds-ink-soft);          /* nội dung thường */
  --ds-fg-3: var(--ds-ink-muted);         /* chú thích, nhãn phụ */
  --ds-fg-on-accent: var(--ds-primary-fg); /* chữ đặt trên nền nhấn */

  /* Viền */
  --ds-border-subtle: var(--ds-hairline);       /* ngăn cách nhẹ, mặc định */
  --ds-border-strong: rgba(11, 11, 13, 0.16);   /* viền thẻ có ranh giới rõ */

  /* Trạng thái tương tác — nền, KHÔNG dùng opacity làm mờ (ACL contract cấm) */
  --ds-state-hover: #F2F6FA;              /* rê chuột trên hàng/thẻ */
  --ds-state-selected: var(--ds-mist);    /* đang chọn */
  --ds-state-focus-ring: 0 0 0 3px rgba(2, 147, 218, 0.4);

  /* ============================================================
     TYPOGRAPHY — serif display + modern sans body
     ============================================================ */

  /* Font stacks — next/font injects --font-display and --font-sans; tokens chain fallbacks */
  --ds-font-display: var(--font-display), 'Fraunces', 'Playfair Display', Georgia, serif;
  --ds-font-body: var(--font-sans), 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --ds-font-mono: 'Geist Mono', 'JetBrains Mono', ui-monospace, monospace;

  /* Type scale — perfect fourth ratio 1.333 */
  --ds-text-xs: 0.75rem;          /* 12 — captions, meta */
  --ds-text-sm: 0.875rem;         /* 14 — small body */
  --ds-text-base: 1rem;           /* 16 — body default */
  --ds-text-lg: 1.125rem;         /* 18 — lead paragraph */
  --ds-text-xl: 1.333rem;         /* 21 — card title, subhead */
  --ds-text-2xl: 1.777rem;        /* 28 — section title */
  --ds-text-3xl: 2.369rem;        /* 38 — large display */
  --ds-text-4xl: 3.157rem;        /* 50 — hero on tablet */
  --ds-text-hero: clamp(2.5rem, 6vw, 5rem);  /* responsive hero */

  /* Fluid type scale — clamp(min@mobile, preferred, max@desktop).
     DÙNG cho heading/display để KHỎI phải chỉnh font-size ở từng breakpoint (hết "cliff").
     Body/label giữ scale cố định (--ds-text-*) cho ổn định đọc. */
  --ds-text-fluid-lg:  clamp(1rem,     0.95rem + 0.35vw, 1.125rem);  /* 16→18 */
  --ds-text-fluid-xl:  clamp(1.125rem, 1.02rem + 0.55vw, 1.333rem);  /* 18→21 card title */
  --ds-text-fluid-2xl: clamp(1.35rem,  1.12rem + 1.15vw, 1.777rem);  /* 22→28 section title */
  --ds-text-fluid-3xl: clamp(1.65rem,  1.25rem + 2.0vw,  2.369rem);  /* 26→38 large display */
  --ds-text-fluid-4xl: clamp(2.0rem,   1.45rem + 2.75vw, 3.157rem);  /* 32→50 hero-ish */

  /* Line heights */
  --ds-leading-tight: 1.1;        /* display */
  --ds-leading-snug: 1.25;        /* headings */
  --ds-leading-normal: 1.5;       /* body */
  --ds-leading-relaxed: 1.65;     /* long-form reading */

  /* Letter spacing */
  --ds-tracking-tight: -0.02em;   /* display */
  --ds-tracking-normal: 0;
  --ds-tracking-wide: 0.05em;     /* caps, labels */
  --ds-tracking-wider: 0.12em;    /* small caps labels */

  /* Font weights */
  --ds-weight-normal: 400;
  --ds-weight-medium: 500;
  --ds-weight-semibold: 600;
  --ds-weight-bold: 700;

  /* ============================================================
     BÍ DANH — token ĐANG ĐƯỢC DÙNG nhưng chưa từng được khai
     ============================================================
     Đo 2026-08-17: 34 tên `--ds-*` xuất hiện trong `var()` mà KHÔNG có ở đâu trong `src`.
     690 lượt dùng / 57 file. Trong đó 339 lượt KHÔNG có giá trị dự phòng ⇒ `var()` không giải
     được ⇒ cả khai báo hỏng tại lúc tính giá trị ⇒ thuộc tính rơi về kế thừa/khởi tạo.
     Nặng nhất: `--ds-text-md` 266 lượt không dự phòng ⇒ 266 khai báo `font-size` chết,
     chữ lấy cỡ của thẻ cha. Đây là lý do "chữ chỗ to chỗ nhỏ không đều".

     Vì sao gate không bắt: validator chỉ hỏi "có phải `var(--ds-*)` không", KHÔNG hỏi
     "token có tồn tại không". Hai file rule còn đang dạy token ma
     (canonical-design-enforcement Part 5 liệt kê `--ds-text-md`; acl-design-rule §3 nêu
     `--ds-ink-tint` làm ví dụ ĐÚNG).

     Nguyên tắc đặt giá trị: **lấy đúng giá trị dự phòng đang phổ biến nhất** để chỗ nào đang
     hiển thị đúng thì giữ nguyên; chỗ nào đang chết thì sống lại đúng ý tác giả.
     Đây là lớp VÁ, không phải mở rộng hệ token — dọn dần bằng quy tắc chạm-đâu-sửa-đó,
     đừng bồi thêm tên mới vào đây. */

  --ds-text-md: var(--ds-text-sm);      /* 14 — 266 lượt chết; tên trùng nghĩa với sm */
  --ds-text-2xs: var(--ds-text-xs);     /* 12 — KHÔNG hạ 11px: sàn chữ ACL là 12 */
  --ds-weight-regular: var(--ds-weight-normal);
  --ds-font-sans: var(--ds-font-body);  /* ⚠ đổi thật: 58 lượt đang rơi system-ui → nay Inter (đúng typography-rule T0) */
  --ds-motion-fast: 120ms;              /* 6 lượt trong nextcore-template, đều dự phòng 120ms */

  --ds-ink-tint: #DDE3EA;               /* viền ấm đặc — giữ đúng dự phòng phổ biến (81 lượt) */
  --ds-ink-secondary: var(--ds-ink-soft);
  --ds-ink-mute: var(--ds-ink-muted);
  --ds-gray-900: var(--ds-ink);
  --ds-white: #FFFFFF;
  --ds-border: var(--ds-hairline);

  --ds-surface: var(--ds-bg);
  --ds-bg-elevated: var(--ds-bg);
  --ds-bg-muted: #F2F5F8;               /* giữ đúng dự phòng, KHÔNG gộp vào --ds-mist (#F0EAE0) */

  --ds-primary-dark: #01669C;           /* giữ đúng dự phòng (15 lượt), đậm hơn --ds-primary-hover */
  --ds-primary-strong: var(--ds-primary-hover);
  --ds-primary-soft:   color-mix(in oklab, var(--ds-primary) 18%, white);
  /* Sac thuong hieu dat TREN LOP TOI (chu tren anh co scrim). --ds-primary (#0293DA) tren nen
     gan den chi ~3,4 nen khong dung lam chu o do; ban pha sang nay dat ~9. Ban ve TheoLoai.dc.html
     ghi #8AD8FF; color-mix cho dung vai tro do ma khong dua them hex vao he mau. */
  --ds-tren-scrim-nhan: color-mix(in oklab, var(--ds-primary) 50%, white);

  /* ═══ SAC NONG — CHI cho GIA va HANH DONG CHINH ═══════════════════════════════════════════
     Ban ve `Main.dc.html` (canvas "Chi tiet cho o", sep chot 10/09) dat mot sac nong canh he
     Jetblack + Candy Blue, va dat NO O DUNG HAI CHO: con so gia, va nut dat phong. Do la ket
     luan cua dot nghien cuu website Viet (mytour...): mot sac am DUY NHAT cho tien va hanh dong
     thi mat tim duoc gia ma khong phai doc; rai sac do ra cac cho khac la mat dau hieu.

     KHONG dung cho: nhan, vien, nen khoi, trang thai. Nhung viec do la cua Candy Blue.

     Do tuong phan (tinh trong sRGB, khong uoc luong):
       --ds-nong      tren trang    3,26  → CHI lam NEN, khong lam chu
       --ds-nong-ink  tren trang    4,88  → dat nguong 4,5 cho chu thuong. Dung cho GIA.
       --ds-nong-fg   tren --ds-nong 5,91 → chu tren nut nong
     ⚠ Ban ve ghi `color:#fff` tren nut nong = 3,26 → TRUOT AA cho chu 15px dam (nguong chu lon
     la 18,66px dam). Nen lay muc nay va giu mau nen: chinh ban ve cung dung muc dam tren nut
     Candy Blue (`.bk__cta2 .z{color:#04121A}`), nen day la sua mot cho khong nhat quan trong
     ban ve, khong phai lech y do thiet ke. */
  --ds-nong: #F2600C;
  --ds-nong-ink: #C24A08;
  --ds-nong-fg: #0B0B0D;
  --ds-primary-tint:   color-mix(in oklab, var(--ds-primary) 10%, white);
  --ds-primary-subtle: color-mix(in oklab, var(--ds-primary)  6%, white);
  --ds-terracotta: #0EA5E9;
  --ds-forest-deep: var(--ds-forest-hover);

  --ds-error:    var(--ds-alert);
  --ds-error-bg: var(--ds-alert-soft);
  --ds-alert-fg: #FFFFFF;
  --ds-success-bg: var(--ds-success-soft);
  --ds-success-hover: color-mix(in oklab, var(--ds-success) 85%, black);
  /* Hai bậc hover còn thiếu — thêm 31/08 khi đổi hex sang token. Không có chúng thì nút nền
     màu trạng thái MẤT PHẢN HỒI: `background:#10B981` và `:hover{background:#059669}` (cùng
     một họ, khác bậc) đều ánh xạ về `--ds-success`, tức rê chuột vào nút không đổi gì.
     Cùng công thức với --ds-success-hover ở dòng trên để ba họ hành xử giống nhau. */
  --ds-alert-hover:   color-mix(in oklab, var(--ds-alert)   85%, black);
  --ds-warning-hover: color-mix(in oklab, var(--ds-warning) 85%, black);
  --ds-success-soft-hover: color-mix(in oklab, var(--ds-success-soft) 88%, black);
  --ds-alert-soft-hover:   color-mix(in oklab, var(--ds-alert-soft)   88%, black);
  --ds-warning-tint: color-mix(in oklab, var(--ds-warning) 12%, white);

  --ds-success-border: color-mix(in oklab, var(--ds-success) 35%, white);
  --ds-alert-border:   color-mix(in oklab, var(--ds-alert)   35%, white);
  --ds-warning-border: color-mix(in oklab, var(--ds-warning) 35%, white);
  --ds-info-border:    color-mix(in oklab, var(--ds-info)    35%, white);

  --ds-radius-pill: 999px;

  /* ⚠ đổi thật + sửa lỗi tương phản: cả 8 lượt đều là `color` đè `background: var(--ds-primary)`.
     5 lượt đang dự phòng #fff → trắng trên nền tan #D4A574 chỉ ~1,9:1, TRƯỢT WCAG AA.
     3 lượt còn lại không dự phòng nên màu chữ đang rơi về kế thừa. Chuẩn hoá về mực đậm (~8,9:1). */
  --ds-on-primary: var(--ds-primary-fg);

  /* ============================================================
     SPACING — thang 4px (space-N = N × 4px)
     ============================================================
     🔴 SỬA 28/08: tiêu đề cũ ghi "8px base unit" — SAI, và sai ở đúng chỗ người ta
     đọc để tính toán. Sự thật nằm ngay dưới: `--ds-space-1: 0.25rem` = 4px, và mọi
     chú thích cuối dòng (4, 8, 12…) đều theo thang 4. Cùng con số sai này
     từng nằm trong `canonical-design-enforcement.md` và đã gây lỗi thật: chiều cao
     thanh công cụ trình xem ảnh nc-sheet tính theo `space-2 = 16px` nên chỗ chừa lệch
     gấp đôi (audit 260821). Tài liệu đã được đính chính hôm đó; tệp nguồn thì chưa,
     nên nó vẫn tiếp tục dạy sai cho người đọc mã — và cho cả trang NextCore Template
     vốn in tiêu đề nhóm ra thẳng từ đây.
     ============================================================ */

  --ds-space-px: 1px;
  --ds-space-0-5: 0.125rem;       /* 2 */
  --ds-space-1: 0.25rem;          /* 4 */
  --ds-space-2: 0.5rem;           /* 8 */
  --ds-space-3: 0.75rem;          /* 12 */
  --ds-space-4: 1rem;             /* 16 */
  --ds-space-5: 1.25rem;          /* 20 */
  --ds-space-6: 1.5rem;            /* 24 */
  --ds-space-8: 2rem;             /* 32 */
  --ds-space-10: 2.5rem;           /* 40 */
  --ds-space-12: 3rem;            /* 48 */
  --ds-space-16: 4rem;            /* 64 */
  --ds-space-20: 5rem;            /* 80 */
  --ds-space-24: 6rem;            /* 96 */
  --ds-space-32: 8rem;            /* 128 */
  --ds-space-40: 10rem;           /* 160 */

  /* Fluid spacing — co giãn theo viewport, dùng cho section gap/padding to
     để KHỎI khai lại padding ở từng breakpoint. */
  /* --ds-space-fluid-* khai ở khối FLUID phía dưới (một địa chỉ sửa). Bốn dòng cũ ở đây đã XOÁ
     24/08: chúng bị khối dưới đè nên là mã chết, mà comment lại ghi thang khác (12→16 thay vì
     12→24) nên ai đọc bản chết là lấy sai số. */

  /* Section padding defaults */
  --ds-section-y: clamp(4rem, 8vw, 8rem);          /* vertical section */
  --ds-section-x: clamp(1.5rem, 5vw, 4rem);        /* horizontal gutter */

  /* ============================================================
     RADII
     ============================================================ */

  --ds-radius-sm: 0.25rem;        /* 4 — inputs, small */
  --ds-radius: 0.5rem;            /* 8 — default */
  --ds-radius-md: 0.75rem;        /* 12 — cards */
  --ds-radius-lg: 1rem;           /* 16 — featured cards */
  --ds-radius-xl: 1.5rem;         /* 24 — hero cards */
  --ds-radius-2xl: 2rem;          /* 32 — decorative */
  --ds-radius-full: 9999px;       /* pill, avatar */

  /* ============================================================
     ACL VISUAL CONTRACT — single source for ALL dashboard list/card
     pages (nextcore-ext-acl-*). Doc: docs/acl-visual-contract.md.
     Density = compact data-dense. Text floor 12px. All ink tiers AA
     (≥4.5:1) on BOTH --ds-bg (#FFF) and --ds-cream. Card chrome warm
     (no cool grays #9ca3af/#f3f4f6 — those broke Warm Editorial + AA).
     ============================================================ */
  --ds-acl-card-radius: 10px;
  --ds-acl-card-pad-y: var(--ds-space-3);     /* 12 */
  --ds-acl-card-pad-x: var(--ds-space-4);     /* 16 */
  --ds-acl-card-gap: var(--ds-space-2);       /* 8  — gap between cards */
  --ds-acl-section-gap: var(--ds-space-3);    /* 12 — nhịp giữa các section trong detail */
  /* surfaces — warm, replace cool grays */
  --ds-acl-surface: var(--ds-bg);             /* card background */
  --ds-acl-surface-hover: #F2F6FA;            /* header hover (was #f9fafb) */
  --ds-acl-surface-sunken: #EDF1F6;           /* meta chip / muted block (was #f3f4f6) */
  /* borders — AA-visible, was near-invisible hairline 0.08 */
  --ds-acl-border: rgba(11, 11, 13, 0.16);
  --ds-acl-border-hover: rgba(11, 11, 13, 0.30);
  --ds-acl-border-dashed: rgba(11, 11, 13, 0.14);
  /* ink tiers — measured AA */
  --ds-acl-ink-title: var(--ds-ink);          /* #1A1814 — 16.9:1 */
  --ds-acl-ink-body: var(--ds-ink-soft);      /* #3D3A34 — 11.2:1 */
  --ds-acl-ink-meta: #555C66;                 /* meta/label — 7.0:1 white / 6.5:1 cream */
  /* type scale — compact (hard floor 12px) */
  --ds-acl-text-title: 0.875rem;              /* 14 */
  --ds-acl-text-body: 0.8125rem;              /* 13 */
  --ds-acl-text-meta: 0.75rem;                /* 12 — floor */
  --ds-acl-weight-title: 600;
  --ds-acl-weight-meta: 600;

  /* ============================================================
     SHADOWS — subtle, editorial
     ============================================================ */

  --ds-shadow-xs: 0 1px 2px rgba(11, 11, 13, 0.04);
  --ds-shadow-sm: 0 2px 4px rgba(11, 11, 13, 0.05);
  --ds-shadow: 0 4px 12px rgba(11, 11, 13, 0.06);
  --ds-shadow-md: 0 8px 24px rgba(11, 11, 13, 0.07);
  --ds-shadow-lg: 0 16px 40px rgba(11, 11, 13, 0.08);
  --ds-shadow-xl: 0 24px 56px rgba(11, 11, 13, 0.1);

  /* Vòng tiêu điểm bàn phím — HAI LỚP, và hai lớp là BẮT BUỘC chứ không phải trang trí.

     Đo prod 28/08 (canvas composite, không đoán): bản cũ `0 0 0 3px rgba(2, 147, 218,0.4)` cho
     tương phản **1,27–1,35** trên mọi nền sáng của hệ. Người dùng bàn phím thấy một quầng kem
     mờ — có tồn tại về mặt kỹ thuật, gần như vô hình về mặt sử dụng.

     Vì sao không thể dùng MỘT màu (đo cả bảng, không suy đoán):

       màu            trắng  cream  mist  #F9FAF9  forest  ink
       vàng 40% (cũ)   1,35   1,32  1,27    1,33    1,87  2,32
       vàng đặc        2,23   2,07  1,86    2,13    4,37  7,96
       mực vàng        5,83   5,41  4,87    5,57    1,67  3,04   ← hỏng trên nền rừng
       trắng           1,00   1,08  1,20    1,05    9,72 17,73   ← hỏng trên nền sáng

     Không màu đơn nào qua ngưỡng 3:1 ở CẢ HAI phía. Nên: lớp trong trắng + lớp ngoài mực vàng.
     Nền sáng thì lớp ngoài nổi (4,87–5,83); nền tối thì lớp trong nổi (9,72–17,73). Luôn có một
     lớp tương phản cao bất kể đặt ở đâu.

     Hai token này KHÔNG đổi theo chế độ tối (`--ds-bg` giữ #FFFFFF — xem chú giải khối dark
     "cards stay on --ds-bg"; `--ds-primary-ink` chỉ khai ở :root) nên vòng ổn định qua theme.

     ⚠ Đây là giá trị box-shadow HOÀN CHỈNH, không phải màu. Viết `box-shadow: 0 0 0 3px
     var(--ds-focus-ring)` là khai báo KHÔNG HỢP LỆ ⇒ trình duyệt bỏ cả dòng ⇒ mất sạch vòng tiêu
     điểm, im lặng. Đã có 2 chỗ mắc lỗi này trong account.css, sửa cùng lượt. */
  --ds-focus-ring: 0 0 0 2px var(--ds-bg), 0 0 0 4px var(--ds-primary-ink);

  /* ============================================================
     MOTION
     ============================================================ */

  --ds-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ds-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ds-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  /* Đường cong PHỔ BIẾN NHẤT trong chính mã này — đo 18/09/2026: `cubic-bezier(0.4,0,0.2,1)`
     xuất hiện 20 lượt (19 bản đủ số 0 + 1 bản viết tắt `.4,0,.2,1`), nhiều hơn cả ba token trên
     cộng lại (4+1+4). Nó là đường cong chuẩn của Material, và nó KHÔNG có token — nên mọi người
     gõ tay. Thêm vào đây để lần sau có chỗ trỏ tới. */
  --ds-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);

  --ds-duration-instant: 100ms;
  /* 🔴 GIÁ TRỊ THỰC TẾ DÙNG NHIỀU NHẤT, mà bảng token lại thiếu. Đo 18/09/2026 trên 1.288 khai
     báo `transition` trong `src/`:
         150ms — 498 lượt (45%)   ← không có token, phải gõ tay
         200ms — 348 lượt (32%)   = --ds-duration-fast
         300ms —  74 lượt ( 6%)
         120ms —  53 lượt ( 4%)   = --ds-motion-fast
     Hai giá trị đầu chiếm 77%. Đó là lời giải cho câu hỏi "vì sao chỉ 10,7% transition dùng
     token": không phải người viết lười, mà bảng token không có con số họ cần. Thêm `quick`
     đứng giữa `instant` (100) và `fast` (200). */
  --ds-duration-quick: 150ms;
  --ds-duration-fast: 200ms;
  --ds-duration: 400ms;
  --ds-duration-slow: 800ms;

  /* ============================================================
     ELEVATION — thang độ sâu 2 lớp (key + ambient), tông ấm.
     Dùng cho bề mặt nổi thay vì --ds-shadow đơn lẻ. Cao = nổi hơn.
     ============================================================ */
  --ds-elevation-0: none;
  --ds-elevation-1: 0 1px 2px rgba(11, 11, 13, 0.04), 0 1px 3px rgba(11, 11, 13, 0.06);
  --ds-elevation-2: 0 2px 4px rgba(11, 11, 13, 0.05), 0 4px 12px rgba(11, 11, 13, 0.08);
  --ds-elevation-3: 0 4px 8px rgba(11, 11, 13, 0.06), 0 12px 28px rgba(11, 11, 13, 0.10);
  --ds-elevation-4: 0 8px 16px rgba(11, 11, 13, 0.08), 0 24px 48px rgba(11, 11, 13, 0.12);
  --ds-elevation-5: 0 16px 32px rgba(11, 11, 13, 0.10), 0 40px 80px rgba(11, 11, 13, 0.16);

  /* ============================================================
     GLASS — frosted surface cho bề mặt NỔI (nav scroll, modal, popover,
     command bar, toast, bottom-sheet). KHÔNG phủ lên content card thường.
     ============================================================ */
  --ds-glass-bg: rgba(255, 255, 255, 0.72);
  --ds-glass-bg-strong: rgba(255, 255, 255, 0.86);
  --ds-glass-border: rgba(255, 255, 255, 0.55);
  --ds-glass-blur: 16px;
  --ds-glass-blur-strong: 24px;
  --ds-glass-shadow: 0 8px 32px rgba(11, 11, 13, 0.12), 0 2px 8px rgba(11, 11, 13, 0.08);

  /* VẬT LIỆU kính (thêm 2026-07-31). Kính "ra kính" nhờ 4 lớp, KHÔNG nhờ nhìn xuyên nhiều:
     (1) nền tint + (2) mờ nền/bão hoà + (3) cạnh sáng mép trên (specular) + (4) vành tối mép dưới
     (độ dày kính). Alpha nền phải CAO — hạ xuống 0.6 là --ds-ink-muted tụt dưới AA 4.5:1. */
  --ds-glass-bg-card: rgba(255, 255, 255, 0.82);  /* bề mặt NỘI DUNG (nhiều chữ nhỏ) */
  --ds-glass-sheen: inset 0 1px 0 rgba(255, 255, 255, 0.75);
  --ds-glass-rim: inset 0 -1px 0 rgba(11, 11, 13, 0.05);
  --ds-glass-blur-sm: 10px;   /* máy hẹp / danh sách dày: chi phí blur tăng theo bán kính */
  --ds-glass-sat: 1.4;
  --ds-glass-highlight: rgba(255, 255, 255, 0.35);  /* vệt sáng theo con trỏ */

  /* MESH — quầng sáng nền để kính có "vật" mà làm mờ. Nền phẳng thì kính vô hình.
     Alpha ≤0.14: đây là nền SAU thẻ kính, đậm hơn là kéo tương phản chữ xuống dưới AA. */
  --ds-mesh-warm: rgba(2, 147, 218, 0.14);
  --ds-mesh-forest: rgba(45, 74, 62, 0.1);
  --ds-mesh-warm-soft: rgba(2, 147, 218, 0.09);

  /* SCRIM — lớp che giữa ẢNH NỀN và chữ. Chữ trên ảnh phải đạt 4.5:1 (18pt+ hoặc
     14pt bold: 3:1); ảnh thì mỗi vùng một độ sáng nên KHÔNG thể đo 1 lần rồi tin.
     Scrim là cách duy nhất bảo đảm nền dưới chữ luôn nằm trong ngưỡng. */
  --ds-scrim-soft: linear-gradient(180deg, rgba(11, 11, 13, 0.15) 0%, rgba(11, 11, 13, 0.45) 100%);
  --ds-scrim-strong: linear-gradient(180deg, rgba(11, 11, 13, 0.35) 0%, rgba(11, 11, 13, 0.72) 100%);
  --ds-scrim-bottom: linear-gradient(180deg, rgba(11, 11, 13, 0) 38%, rgba(11, 11, 13, 0.78) 100%);
  --ds-scrim-side: linear-gradient(90deg, rgba(11, 11, 13, 0.7) 0%, rgba(11, 11, 13, 0.15) 58%, rgba(11, 11, 13, 0) 100%);
  --ds-scrim-light: linear-gradient(180deg, rgba(245, 248, 250, 0.82) 0%, rgba(245, 248, 250, 0.55) 100%);

  /* Scrim PHẲNG — nền mờ sau hộp thoại/lớp phủ. Khác năm cái trên: chúng là GRADIENT cho chữ
     đè ảnh, không cái nào dùng làm nền hộp thoại được.
     Vì sao là token chứ không viết tại chỗ: đo 29/08 có 183 lượt `rgba(0,0,0,…)` trong CSS,
     trong đó nền mờ hộp thoại lặp lại nguyên si (chat.css:357, booking.css:1014).
     Dùng đen ẤM `26,24,20` (chính là `--ds-ink`) chứ không phải `0,0,0`: đen thuần đặt cạnh
     bảng màu ấm của sản phẩm sẽ ngả xanh. */
  --ds-scrim-solid: rgba(11, 11, 13, 0.55);

  /* GRAIN — hạt nhiễu mịn. Gradient CSS thuần trông "phẳng số hoá"; một lớp hạt rất
     nhẹ là thứ tách bản in đẹp khỏi bản trông như mẫu template. Sinh bằng SVG inline,
     0 request mạng. Đừng vượt 0.06 nếu nền có chữ nhỏ. */
  --ds-grain-opacity: 0.035;
  --ds-grain-opacity-strong: 0.06;

  /* ============================================================
     FLUID SPACE — clamp(min@mobile, preferred, max@desktop).
     Dùng cho nhịp dọc section / gap lớn → hết chỉnh px theo breakpoint.
     ============================================================ */
  --ds-space-fluid-sm: clamp(0.75rem, 0.6rem + 0.75vw, 1.5rem);   /* 12→24 */
  --ds-space-fluid-md: clamp(1.5rem, 1.1rem + 2vw, 3rem);          /* 24→48 */
  --ds-space-fluid-lg: clamp(2.5rem, 1.8rem + 3.5vw, 6rem);        /* 40→96 */
  --ds-space-fluid-section: clamp(3rem, 2rem + 5vw, 8rem);         /* nhịp dọc section 48→128 */

  /* ============================================================
     LAYOUT
     ============================================================ */

  --ds-container-sm: 640px;
  --ds-container-md: 768px;
  --ds-container-lg: 1024px;
  --ds-container-xl: 1280px;
  --ds-container-2xl: 1440px;
  --ds-container-prose: 68ch;     /* readable content width */

  /* Z-index scale */
  --ds-z-base: 0;
  --ds-z-raised: 10;
  --ds-z-sticky: 100;
  --ds-z-dropdown: 200;
  --ds-z-header: 500;
  --ds-z-overlay: 800;
  --ds-z-modal: 900;
  --ds-z-toast: 1000;
}

/* ============================================================
   DARK MODE
   ============================================================

   TRẠNG THÁI 31/08 — ĐÃ VIẾT ĐỦ, CHƯA BAO GIỜ CHẠY.

   39 token tối bên dưới có sẵn từ lâu, gồm cả glass tối, elevation tối, ACL tối, và
   `--ds-ink-muted` (khi đó #8A8579) đã đo đạt 4,71:1 trên `#1E1B16` — ĐÚNG cho nền THÂN, nhưng
   04/09 đo lại trên 8 nền thực tế thì nó TRƯỢT cả năm nền `-soft` (3,02–3,92); nay là #B3AEA1,
   đạt 5,02–8,38. Nhưng chúng chỉ khớp khi
   `:root[data-theme="auto"]`, trong khi `src/contexts/ThemeContext.tsx:50` đặt CỨNG
   `data-theme="light"` và ghi "Dark mode has been removed from the website"
   (`setTheme`/`toggleTheme` là no-op). Tức CSS còn, JS đã gỡ ⇒ khối này là mã chết.

   VÌ SAO CHƯA BẬT LẠI NGAY (quyết định 31/08): 979 lượt utility màu Tailwind
   (`bg-white`, `text-gray-900`) KHÔNG đổi theo `data-theme`. Bật tối lúc này = chữ trắng
   trên nền trắng ở hàng trăm chỗ. Gần như chắc chắn đó chính là lý do dark mode bị gỡ
   thay vì được sửa.

   ĐIỀU KIỆN BẬT: utility màu về dưới ~100 lượt (baseline chỉ-đi-xuống, cùng công thức
   đã đưa native-select từ 146 → 10), rồi mới nối lại ThemeContext.

   Bổ sung 31/08: tách selector để `[data-theme="dark"]` bật được THỦ CÔNG, không phụ
   thuộc hệ điều hành — trước đây chỉ có nhánh `auto` nên không có cách nào thử. */

/* Bật thủ công — `data-theme="dark"` do người dùng chọn, không phụ thuộc hệ điều hành.
   
   🔴 NỘI DUNG KHỐI NÀY PHẢI GIỐNG HỆT khối `[data-theme="auto"]` trong `@media
   (prefers-color-scheme: dark)` ngay bên dưới. Test `role-tokens` ghim điều đó.
   
   Vì sao phải nói to: đến 31/08 khối này chỉ có 18 token còn khối "auto" có 46 — thiếu 28,
   trong đó có `--ds-ink`. Nghĩa là ai bật chế độ tối THỦ CÔNG sẽ nhận nền tối (surface đã
   đảo) nhưng chữ vẫn `#1A1814` (tối) ⇒ CHỮ TỐI TRÊN NỀN TỐI. Cùng lúc `--ds-glass-*` giữ
   trắng nên mọi bề mặt kính thành mảng trắng chói. Phép đo trên DOM hôm đó ra 42/133 phần
   tử fail tương phản — và nó đo đúng nhánh thiếu này, nên con số ấy nói về LỖ HỔNG NÀY chứ
   không phải về một hệ màu song song nào khác.
   
   CSS thuần không có cách chia sẻ một khối khai báo giữa selector thường và selector nằm
   trong @media, nên buộc phải lặp. Đổi ở đây thì PHẢI đổi ở khối kia cùng lượt. */
:root[data-theme="dark"] {

  /* Vai trò — bản tối, phải khớp danh sách ở khối VAI TRÒ đầu tệp */
  --ds-surface-0: #0B0B0D;
  --ds-surface-1: #16181D;
  --ds-surface-2: #1E2128;
  --ds-surface-3: #252A33;
  --ds-fg-1: #F5F8FA;
  --ds-fg-2: #C9D1DB;
  --ds-fg-3: #A3ACB9;
  --ds-fg-on-accent: #0B0B0D;
  --ds-border-subtle: rgba(245, 248, 250, 0.10);
  --ds-border-strong: rgba(245, 248, 250, 0.18);
  --ds-state-hover: #1E2128;
  --ds-state-selected: #252A33;
  --ds-state-focus-ring: 0 0 0 3px rgba(2, 147, 218, 0.5);

  /* Swap cream/ink but keep warm feel */
  --ds-cream: #0B0B0D;
  --ds-mist: #16181D;
  --ds-ink: #F5F8FA;
  --ds-ink-soft: #C9D1DB;
  --ds-ink-muted: #A3ACB9;
  /* Candy Blue TUOI chi song duoc tren nen den — do 04/09: #56C5FF tren #0B0B0D = 10,14 ·
     tren be mat #16181D = 9,16. Ban SANG dung #0293DA (tram hon) vi tren nen sang no con phai
     dat ranh gioi >=3:1 voi trang/kem (WCAG 1.4.11); rang buoc do bien mat o che do toi, nen
     day la cho DUY NHAT dung duoc sac tuoi nhat ma van du tuong phan. */
  --ds-primary: #56C5FF;
  --ds-primary-hover: #7DD3FC;
  --ds-primary-fg: #0B0B0D;   /* chu tren nut candy: 10,14 — KHONG dung trang (1,94) */
  /* #253: nền đậm GIỮ đậm ở chế độ tối — chữ trắng trên nó (xem khối sáng) */
  --ds-primary-deep: #0369A1;        /* chữ trắng 5,93 */
  --ds-primary-deep-hover: #075985;  /* chữ trắng 7,4 */
  /* xem chu giai o ban SANG: #8A8579 truot ca NAM nen -soft (3,02-3,92) */
  --ds-hairline: rgba(245, 248, 250, 0.1);

  /* Năm token nền tảng còn THIẾU bản tối — bổ sung 31/08, phát hiện khi đo trước lúc định
     bật lại chế độ tối. Không có chúng thì bật lên sẽ hỏng ngay ở chỗ dễ thấy nhất:
       · --ds-bg là nền THẺ và Ô NHẬP; khối tối cũ không khai nên nó giữ #FFFFFF ⇒ thẻ trắng
         chói giữa trang tối. Đặt bằng --ds-surface-1 để hai tầng không nói ngược nhau.
       · bốn --ds-*-soft là nền TRẠNG THÁI, vốn là pastel sáng (#FCE8E2, #E4EEDD…) — trên nền
         tối chúng thành mảng sáng chói, và chữ tối đặt lên lại đọc được, nên lỗi này không
         lộ ra bằng phép đo tương phản mà chỉ lộ ra khi nhìn.
     Sinh bằng color-mix thay vì gõ tay 4 giá trị: giữ đúng sắc của từng trạng thái, và tự
     theo nếu màu gốc đổi. Repo đã dùng color-mix cho các token -ink từ 24/08. */
  --ds-bg: #16181D;
  /* #282: --ds-alert sáng #C2412D trên nền tối chỉ 3,46 ⇒ sắc sáng hơn cho nền tối (6,10 trên #16181D ·
     5,54 trên --ds-surface-2), chữ trên nút đổi sang tối theo tiền lệ --ds-primary-fg (6,76).
     --ds-bg-muted gần trắng ⇒ bằng --ds-surface-2. --ds-forest (#16181D) TRÙNG --ds-surface-1 ở tối ⇒ khối
     Jetblack biến mất giữa thẻ; nâng lên --ds-surface-3 để vẫn là một bậc riêng (chữ --ds-forest-fg 13,5). */
  --ds-alert: #F0715A;
  --ds-alert-fg: #0B0B0D;
  --ds-bg-muted: #1E2128;
  --ds-forest: #252A33;
  --ds-forest-hover: #2E3440;
  --ds-alert-soft:   color-mix(in srgb, var(--ds-alert)   22%, #16181D);
  --ds-success-soft: color-mix(in srgb, var(--ds-success) 22%, #16181D);
  --ds-warning-soft: color-mix(in srgb, var(--ds-warning) 22%, #16181D);
  --ds-info-soft:    color-mix(in srgb, var(--ds-info)    22%, #16181D);
  /* #253 — `-tint`/`-subtle` ở khối sáng pha với WHITE: không khai lại ở đây là nền SÁNG trong chế độ tối
     (đo 30/09 ở CRM: thẻ hội thoại đang chọn chữ trắng trên nền rgb(246,252,255) = 1,03). */
  --ds-primary-tint:   color-mix(in oklab, var(--ds-primary) 18%, #16181D);
  /* #253: -soft cũng pha WHITE ở khối sáng ⇒ chip đang chọn ở Bàn giao ca nền sáng chữ #7DD3FC = 1,49 (đo 30/09) */
  --ds-primary-soft:   color-mix(in oklab, var(--ds-primary) 22%, #16181D);
  --ds-primary-subtle: color-mix(in oklab, var(--ds-primary) 12%, #16181D);
  /* 🔴 THÊM 02/09 — token thứ NĂM, bị bỏ sót khi viết khối này (chú thích ngay trên còn ghi
     "bốn --ds-*-soft"). `--ds-accent-soft` sinh sau bộ bốn kia nên không ai nhớ khai lại.
     Đo prod 02/09 ở /nextcore-automations/onboarding, chế độ tối: nền bước "Đối chiếu tài khoản
     khác" vẫn là #EDE9FE (tím nhạt của chế độ SÁNG, alpha 1) trong khi chữ đã đổi sang
     --ds-ink = #faf6f0 ⇒ tương phản **1,10:1**, chữ gần như vô hình. Không phải ca lẻ:
     67 lượt dùng --ds-accent-soft trên toàn site đều chịu cùng lỗi. */
  --ds-accent-soft:  color-mix(in srgb, var(--ds-accent)  22%, #16181D);
  /* `--ds-primary-ink` là biến thể ĐẬM của Dawn Tan, dựng cho nền SÁNG (#8a5b24, 5,83:1 trên
     kem). Ở chế độ tối vai trò của nó đảo — phải SÁNG hơn nền — nên giữ nguyên là hỏng: đo
     trên prod 31/08 thấy giá tiền trên thẻ chỗ ở chỉ 2,84:1, và nó lặp ở MỌI thẻ (11/33 phần
     tử fail của cả trang là cùng một lỗi này). Trang bán chỗ ở mà giá khó đọc.
     Chế độ tối dùng thẳng Dawn Tan: #D4A574 trên #1E1B16 cho 8,89 — số này đã đo khi nối
     `--ring`, ghi ở globals.css. */
  --ds-primary-ink: #7DD3FC;
  /* #326: `--ds-nong-ink` (#C24A08, giá tiền) chưa có bản tối ⇒ 3,62 trên #16181D, trượt ở MỌI giá
     phòng của trang chi tiết (đo prod 05/10, do-tuong-phan v11). #FF9A62 cho 8,4 trên #16181D. */
  --ds-nong-ink: #FF9A62;
  /* ACL contract — dark mirror (cards stay on --ds-bg) */
  --ds-acl-surface-hover: #1E2128;
  --ds-acl-surface-sunken: #16181D;
  --ds-acl-border: rgba(245, 248, 250, 0.18);
  --ds-acl-border-hover: rgba(245, 248, 250, 0.32);
  --ds-acl-border-dashed: rgba(245, 248, 250, 0.14);
  --ds-acl-ink-meta: #A3ACB9;

  /* Glass tối — nền mist trong mờ, viền sáng nhẹ */
  --ds-glass-bg: rgba(30, 27, 22, 0.72);
  --ds-glass-bg-strong: rgba(30, 27, 22, 0.88);
  --ds-glass-border: rgba(245, 248, 250, 0.12);
  --ds-glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.44), 0 2px 8px rgba(0, 0, 0, 0.3);
  /* Vật liệu kính tối: cạnh sáng yếu hơn (nền tối không phản chiếu mạnh như nền sáng) */
  --ds-glass-bg-card: rgba(30, 27, 22, 0.8);
  --ds-glass-sheen: inset 0 1px 0 rgba(245, 248, 250, 0.12);
  --ds-glass-rim: inset 0 -1px 0 rgba(0, 0, 0, 0.24);
  --ds-glass-highlight: rgba(245, 248, 250, 0.14);
  --ds-mesh-warm: rgba(2, 147, 218, 0.12);
  --ds-mesh-forest: rgba(45, 74, 62, 0.28);
  --ds-mesh-warm-soft: rgba(2, 147, 218, 0.08);

  /* Elevation tối — đổ bóng đậm hơn để nổi trên nền tối */
  --ds-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 3px rgba(0, 0, 0, 0.36);
  --ds-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.34), 0 4px 12px rgba(0, 0, 0, 0.4);
  --ds-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.38), 0 12px 28px rgba(0, 0, 0, 0.46);
  --ds-elevation-4: 0 8px 16px rgba(0, 0, 0, 0.42), 0 24px 48px rgba(0, 0, 0, 0.52);
  --ds-elevation-5: 0 16px 32px rgba(0, 0, 0, 0.46), 0 40px 80px rgba(0, 0, 0, 0.6);
}


@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    /* Vai trò — bản tối, phải khớp danh sách ở khối VAI TRÒ đầu tệp */
    --ds-surface-0: #0B0B0D;
    --ds-surface-1: #16181D;
    --ds-surface-2: #1E2128;
    --ds-surface-3: #252A33;
    --ds-fg-1: #F5F8FA;
    --ds-fg-2: #C9D1DB;
    --ds-fg-3: #A3ACB9;
    --ds-fg-on-accent: #0B0B0D;
    --ds-border-subtle: rgba(245, 248, 250, 0.10);
    --ds-border-strong: rgba(245, 248, 250, 0.18);
    --ds-state-hover: #1E2128;
    --ds-state-selected: #252A33;
    --ds-state-focus-ring: 0 0 0 3px rgba(2, 147, 218, 0.5);

    /* Swap cream/ink but keep warm feel */
    --ds-cream: #0B0B0D;
    --ds-mist: #16181D;
    --ds-ink: #F5F8FA;
    --ds-ink-soft: #C9D1DB;
    --ds-ink-muted: #A3ACB9;
  /* Candy Blue TUOI chi song duoc tren nen den — do 04/09: #56C5FF tren #0B0B0D = 10,14 ·
     tren be mat #16181D = 9,16. Ban SANG dung #0293DA (tram hon) vi tren nen sang no con phai
     dat ranh gioi >=3:1 voi trang/kem (WCAG 1.4.11); rang buoc do bien mat o che do toi, nen
     day la cho DUY NHAT dung duoc sac tuoi nhat ma van du tuong phan. */
  --ds-primary: #56C5FF;
  --ds-primary-hover: #7DD3FC;
  --ds-primary-fg: #0B0B0D;   /* chu tren nut candy: 10,14 — KHONG dung trang (1,94) */
  /* #253: nền đậm GIỮ đậm ở chế độ tối — chữ trắng trên nó (xem khối sáng) */
  --ds-primary-deep: #0369A1;        /* chữ trắng 5,93 */
  --ds-primary-deep-hover: #075985;  /* chữ trắng 7,4 */
  /* xem chu giai o ban SANG: #8A8579 truot ca NAM nen -soft (3,02-3,92) */
    --ds-hairline: rgba(245, 248, 250, 0.1);

    /* Năm token nền tảng còn THIẾU bản tối — bổ sung 31/08, phát hiện khi đo trước lúc định
       bật lại chế độ tối. Không có chúng thì bật lên sẽ hỏng ngay ở chỗ dễ thấy nhất:
         · --ds-bg là nền THẺ và Ô NHẬP; khối tối cũ không khai nên nó giữ #FFFFFF ⇒ thẻ trắng
           chói giữa trang tối. Đặt bằng --ds-surface-1 để hai tầng không nói ngược nhau.
         · bốn --ds-*-soft là nền TRẠNG THÁI, vốn là pastel sáng (#FCE8E2, #E4EEDD…) — trên nền
           tối chúng thành mảng sáng chói, và chữ tối đặt lên lại đọc được, nên lỗi này không
           lộ ra bằng phép đo tương phản mà chỉ lộ ra khi nhìn.
       Sinh bằng color-mix thay vì gõ tay 4 giá trị: giữ đúng sắc của từng trạng thái, và tự
       theo nếu màu gốc đổi. Repo đã dùng color-mix cho các token -ink từ 24/08. */
    --ds-bg: #16181D;
    /* #282: --ds-alert sáng #C2412D trên nền tối chỉ 3,46 ⇒ sắc sáng hơn cho nền tối (6,10 trên #16181D ·
       5,54 trên --ds-surface-2), chữ trên nút đổi sang tối theo tiền lệ --ds-primary-fg (6,76).
       --ds-bg-muted gần trắng ⇒ bằng --ds-surface-2. --ds-forest (#16181D) TRÙNG --ds-surface-1 ở tối ⇒ khối
       Jetblack biến mất giữa thẻ; nâng lên --ds-surface-3 để vẫn là một bậc riêng (chữ --ds-forest-fg 13,5). */
    --ds-alert: #F0715A;
    --ds-alert-fg: #0B0B0D;
    --ds-bg-muted: #1E2128;
    --ds-forest: #252A33;
    --ds-forest-hover: #2E3440;
    --ds-alert-soft:   color-mix(in srgb, var(--ds-alert)   22%, #16181D);
    --ds-success-soft: color-mix(in srgb, var(--ds-success) 22%, #16181D);
    --ds-warning-soft: color-mix(in srgb, var(--ds-warning) 22%, #16181D);
    --ds-info-soft:    color-mix(in srgb, var(--ds-info)    22%, #16181D);
    /* #253 — `-tint`/`-subtle` ở khối sáng pha với WHITE: không khai lại ở đây là nền SÁNG trong chế độ tối
       (đo 30/09 ở CRM: thẻ hội thoại đang chọn chữ trắng trên nền rgb(246,252,255) = 1,03). */
    --ds-primary-tint:   color-mix(in oklab, var(--ds-primary) 18%, #16181D);
    /* #253: -soft cũng pha WHITE ở khối sáng ⇒ chip đang chọn ở Bàn giao ca nền sáng chữ #7DD3FC = 1,49 (đo 30/09) */
    --ds-primary-soft:   color-mix(in oklab, var(--ds-primary) 22%, #16181D);
    --ds-primary-subtle: color-mix(in oklab, var(--ds-primary) 12%, #16181D);
    /* 🔴 THÊM 02/09 — token thứ NĂM, bị bỏ sót khi viết khối này (chú thích ngay trên còn ghi
       "bốn --ds-*-soft"). `--ds-accent-soft` sinh sau bộ bốn kia nên không ai nhớ khai lại.
       Đo prod 02/09 ở /nextcore-automations/onboarding, chế độ tối: nền bước "Đối chiếu tài khoản
       khác" vẫn là #EDE9FE (tím nhạt của chế độ SÁNG, alpha 1) trong khi chữ đã đổi sang
       --ds-ink = #faf6f0 ⇒ tương phản **1,10:1**, chữ gần như vô hình. Không phải ca lẻ:
       67 lượt dùng --ds-accent-soft trên toàn site đều chịu cùng lỗi. */
    --ds-accent-soft:  color-mix(in srgb, var(--ds-accent)  22%, #16181D);
  /* `--ds-primary-ink` là biến thể ĐẬM của Dawn Tan, dựng cho nền SÁNG (#8a5b24, 5,83:1 trên
     kem). Ở chế độ tối vai trò của nó đảo — phải SÁNG hơn nền — nên giữ nguyên là hỏng: đo
     trên prod 31/08 thấy giá tiền trên thẻ chỗ ở chỉ 2,84:1, và nó lặp ở MỌI thẻ (11/33 phần
     tử fail của cả trang là cùng một lỗi này). Trang bán chỗ ở mà giá khó đọc.
     Chế độ tối dùng thẳng Dawn Tan: #D4A574 trên #1E1B16 cho 8,89 — số này đã đo khi nối
     `--ring`, ghi ở globals.css. */
  --ds-primary-ink: #7DD3FC;
  /* #326: `--ds-nong-ink` (#C24A08, giá tiền) chưa có bản tối ⇒ 3,62 trên #16181D, trượt ở MỌI giá
     phòng của trang chi tiết (đo prod 05/10, do-tuong-phan v11). #FF9A62 cho 8,4 trên #16181D. */
  --ds-nong-ink: #FF9A62;
    /* ACL contract — dark mirror (cards stay on --ds-bg) */
    --ds-acl-surface-hover: #1E2128;
    --ds-acl-surface-sunken: #16181D;
    --ds-acl-border: rgba(245, 248, 250, 0.18);
    --ds-acl-border-hover: rgba(245, 248, 250, 0.32);
    --ds-acl-border-dashed: rgba(245, 248, 250, 0.14);
    --ds-acl-ink-meta: #A3ACB9;

    /* Glass tối — nền mist trong mờ, viền sáng nhẹ */
    --ds-glass-bg: rgba(30, 27, 22, 0.72);
    --ds-glass-bg-strong: rgba(30, 27, 22, 0.88);
    --ds-glass-border: rgba(245, 248, 250, 0.12);
    --ds-glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.44), 0 2px 8px rgba(0, 0, 0, 0.3);
    /* Vật liệu kính tối: cạnh sáng yếu hơn (nền tối không phản chiếu mạnh như nền sáng) */
    --ds-glass-bg-card: rgba(30, 27, 22, 0.8);
    --ds-glass-sheen: inset 0 1px 0 rgba(245, 248, 250, 0.12);
    --ds-glass-rim: inset 0 -1px 0 rgba(0, 0, 0, 0.24);
    --ds-glass-highlight: rgba(245, 248, 250, 0.14);
    --ds-mesh-warm: rgba(2, 147, 218, 0.12);
    --ds-mesh-forest: rgba(45, 74, 62, 0.28);
    --ds-mesh-warm-soft: rgba(2, 147, 218, 0.08);

    /* Elevation tối — đổ bóng đậm hơn để nổi trên nền tối */
    --ds-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 3px rgba(0, 0, 0, 0.36);
    --ds-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.34), 0 4px 12px rgba(0, 0, 0, 0.4);
    --ds-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.38), 0 12px 28px rgba(0, 0, 0, 0.46);
    --ds-elevation-4: 0 8px 16px rgba(0, 0, 0, 0.42), 0 24px 48px rgba(0, 0, 0, 0.52);
    --ds-elevation-5: 0 16px 32px rgba(0, 0, 0, 0.46), 0 40px 80px rgba(0, 0, 0, 0.6);
  }
}

/* ============================================================
   UTILITY CLASSES — intentionally minimal
   Prefer CSS vars + component styles over utility spam
   ============================================================ */

.ds-container {
  width: 100%;
  max-width: var(--ds-container-2xl);
  margin-inline: auto;
  padding-inline: var(--ds-section-x);
}

.ds-prose {
  max-width: var(--ds-container-prose);
  line-height: var(--ds-leading-relaxed);
  color: var(--ds-ink-soft);
}

.ds-display {
  font-family: var(--ds-font-display);
  letter-spacing: var(--ds-tracking-tight);
  line-height: var(--ds-leading-tight);
  color: var(--ds-ink);
}

.ds-eyebrow {
  font-size: var(--ds-text-xs);
  font-weight: var(--ds-weight-semibold);
  letter-spacing: var(--ds-tracking-wider);
  text-transform: uppercase;
  color: var(--ds-ink-muted);
}

/* ═══════════════════════════════════════════════════════════════════════════
   BO GÓC MƯỢT — "lisse" / squircle (superellipse, kiểu Apple/iOS) TOÀN SITE
   ═══════════════════════════════════════════════════════════════════════════
   CSS corner-shape (Baseline 2025, Chromium 139+): biến cung tròn của
   border-radius thành đường cong LIÊN TỤC (squircle) mượt hơn, sang hơn.
   - CHỈ tác động phần tử ĐÃ có border-radius (radius:0 → không đổi).
   - background/border/outline/box-shadow đều bám theo shape (không như clip-path).
   - Trình duyệt chưa hỗ trợ (Safari/Firefox 2026) BỎ QUA → giữ nguyên bo tròn
     thường (progressive enhancement, 0 rủi ro) — vì thế bọc trong @supports.

   RÀNG BUỘC: squircle làm HÌNH TRÒN (border-radius:50%) méo thành squircle.
   → reset về `round` cho phần tử tròn (avatar/chấm/vòng/spinner...). Danh sách
   reset để RỘNG: over-reset chỉ khiến phần tử giữ bo tròn thường (vô hại);
   under-reset mới làm tròn → squircle (cần tránh). Ảnh/thẻ chữ nhật bo góc
   KHÔNG nằm trong reset → vẫn hưởng squircle. */
@supports (corner-shape: squircle) {
  :where(*, *::before, *::after) {
    corner-shape: squircle;
  }
  /* Giữ TRÒN: phần tử hình tròn / chấm / vòng / hạt trang trí. */
  :where(
    [class*="avatar" i],
    [class*="dot" i],
    [class*="circle" i],
    [class*="orb" i],
    [class*="particle" i],
    [class*="ring" i],
    [class*="confetti" i],
    [class*="spinner" i],
    [class*="pulse" i],
    [class*="radio" i],
    [class*="thumb" i],
    [style*="border-radius: 50%"],
    [style*="border-radius:50%"]
  ) {
    corner-shape: round;
  }
}
