/* ═══════════════════════════════════════════════════════════════════
   Lãi suất 24h — art direction "quant-private-banking"
   (docs/ART-DIRECTION-2.md, chốt 10/08/2026 — thay hướng "so-tiet-kiem")

   Ẩn dụ sản phẩm: BÀN DỮ LIỆU của một private bank định lượng. Nền porcelain
   sáng; MỘT sân khấu dữ liệu tối (midnight navy) chiếm 20–30% trang — nơi câu
   trả lời đứng; cobalt là accent duy nhất của thương hiệu; emerald chỉ cho
   "đã đối chiếu" và biến động tích cực; amber/đỏ chỉ cho caveat và cảnh báo.

   Vì sao KHÔNG phải "tờ biểu công văn" nữa: chủ dự án bác 10/08/2026 — hướng
   cũ chủ động chống high-tech (bo góc 0, không bóng, không mặt tối) nên sản
   phẩm đọc như báo cáo hành chính. Vì sao vẫn KHÔNG phải terminal crypto:
   không neon, không ticker, không particle, không đếm số tự chạy — chuyển
   động chỉ được phép khi nó GIẢI THÍCH một thay đổi.

   Nguyên tắc dữ liệu giữ nguyên từ hướng cũ (chúng là sản phẩm, không phải
   trang trí): số khảo sát luôn mang caveat; ô trống là "—" không phải 0;
   chart chỉ dài bằng số ngày thật; trục cắt phải in mốc; cắt thì khai số cắt.
   ═══════════════════════════════════════════════════════════════════ */

@import url("/fonts.css");

/* ── 1. Token ─────────────────────────────────────────────────────── */
:root {
  color-scheme: dark;

  /* ═══ VOLT — nền tối toàn trang, terminal / data cockpit ═══════════
     Thay hướng "porcelain + một sân khấu tối" (giữ trong git). Tiền đề đảo
     ngược: TRANG là nền tối, các khối là bảng điều khiển ĐẶT TRÊN nó, và
     sân khấu cũ trở thành khối nổi bật nhất chứ không còn là ngoại lệ.

     Hai giá trị của prototype đã sửa vì trượt AA khi làm chữ trên #060A14:
       --tx4 #5F739B → 4,16:1  ⇒ dùng #687FAA (4,90:1)
       --ac1 #2E68FF → 4,28:1  ⇒ CHỈ dùng làm nền/gradient, KHÔNG làm chữ.
     Vì `--cobalt` đang là màu CHỮ ở hai chục chỗ trong file này, nó được
     trỏ vào cyan #3FE0FF (12,6:1) chứ không vào #2E68FF. Xanh đậm sống ở
     `--cobalt-deep`, chỉ dùng cho gradient và thanh. */

  --bg: #060A14;            /* nền trang */
  --surface: #090F1E;       /* bảng điều khiển — chìm hơn nền một bậc */
  --surface-2: #0A1122;
  --head: #0C1527;          /* hàng tiêu đề bảng */

  /* Sân khấu dữ liệu — nay là khối nổi bật nhất, không phải vùng tối duy nhất */
  --stage: #08101F;
  --stage-2: #0B1428;
  --stage-line: rgba(126, 160, 255, .16);
  --stage-mid: #0C2447;      /* chân giữa gradient sân khấu */
  --on-stage: #E9EFFD;
  --on-stage-2: #93A5C9;    /* 7,98:1 trên nền — ngưỡng chữ phụ */

  --ink: #E9EFFD;           /* 17,2:1 trên nền */
  --ink-2: #93A5C9;         /*  7,98:1 */
  --muted: #6F84AC;         /*  5,25:1 — sàn AA của hệ. Dưới mức này là
                                #5F739B (4,16:1) và nó trượt. */
  --faint: #687FAA;         /*  4,90:1 — nhãn mờ nhất được phép */

  --rule: rgba(126, 160, 255, .13);
  --rule-strong: rgba(126, 160, 255, .24);

  /* Accent — cyan là màu CHỮ, xanh đậm là màu NỀN. Không hoán đổi. */
  --cobalt: #3FE0FF;        /* 12,6:1 — accent chữ, viền, biểu tượng */
  --cobalt-strong: #9EF3FF; /* 15,8:1 */
  --cobalt-soft: rgba(47, 104, 255, .16);
  --cobalt-bright: #3FE0FF;
  --cobalt-deep: #2E68FF;   /* CHỈ nền và gradient — 4,28:1, không làm chữ */
  --on-accent: #04121F;     /* chữ đặt trên nền accent */

  --emerald: #3EF2A5;       /* 13,6:1 — "đã đối chiếu", biến động tăng */
  --emerald-soft: rgba(62, 242, 165, .10);
  --emerald-bright: #3EF2A5;

  --amber: #FFC24D;         /* 12,3:1 — CHỈ caveat và điều kiện */
  --amber-soft: rgba(255, 194, 77, .09);
  --warn: #FF5C7A;          /*  6,7:1 */
  --warn-soft: rgba(255, 92, 122, .10);

  --steel: #A9BEE6;         /* lớp niêm yết — tông thép, KHÔNG quầng sáng */
  --steel-line: #8FA6CE;

  /* Kênh RGB tách riêng để dựng quầng sáng bằng rgba(var(--x), α). */
  --acR: 63, 224, 255;      --cbR: 47, 104, 255;
  --lnR: 126, 160, 255;     --gdR: 94, 140, 255;
  --upR: 62, 242, 165;      --dnR: 255, 92, 122;
  --amR: 255, 194, 77;      --stR: 150, 175, 225;

  /* Cường độ quầng sáng và lưới — một chỗ chỉnh, không rải khắp file. */
  --ga: .49;                /* quầng mạnh: số hero, nút chính */
  --gb: .27;                /* quầng nhẹ: viền, badge, thanh */
  --gridA: .05;             /* độ mờ lưới kỹ thuật */

  --chip-bg: rgba(233, 240, 253, .14);   /* nền ô logo — VOLT §9 */
  /* Panel TRONG MỜ theo bản bàn giao — lưới kỹ thuật thấy mờ qua tấm, nên
     khối đọc ra "kính đặt trên bàn dữ liệu" chứ không phải thẻ đục. */
  /* ĐỤC, không trong mờ. Lưới phản ứng nằm ở z:0 dưới nội dung, nhưng mặt
     panel trong mờ thì lưới XUYÊN QUA — rê chuột vào thẻ là thấy vân lưới nổi
     lên giữa con số (lỗi chủ dự án bắt 13/08 chiều). Chiều sâu nay đến từ
     viền hairline + quầng khi rê, không đến từ độ trong. */
  --panel: #0A1120;
  --panel-2: #0B1424;
  --panel-hi: linear-gradient(180deg, #0D1730, #080E1C);
  --acGrad: linear-gradient(115deg, #2E68FF, #3FE0FF);
  --acGrad90: linear-gradient(90deg, #2E68FF, #3FE0FF);
  --heroGrad: linear-gradient(115deg, #5B8CFF 0%, #3FE0FF 58%, #9EF3FF 100%);
  --stGrad: linear-gradient(90deg, #5A7BC8, #A9BEE6);
  --bgFx:
    radial-gradient(900px 480px at 22% -8%, rgba(47, 104, 255, .20), transparent 62%),
    radial-gradient(760px 420px at 88% 4%, rgba(63, 224, 255, .10), transparent 60%),
    radial-gradient(1200px 700px at 50% 118%, rgba(9, 20, 48, .90), transparent 70%);

  --r-lg: 12px; --r: 10px; --r-sm: 7px;
  /* Trên nền tối, box-shadow gần như vô hình — chiều sâu đến từ viền hairline
     và quầng sáng. `--shadow-1` là một vệt sáng ở mép trên, không phải bóng đổ. */
  --shadow-1: inset 0 1px 0 rgba(233, 240, 253, .04);
  --shadow-2: 0 18px 44px -24px #000;

  --sans: "Be Vietnam Pro", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 72px;
  --gutter: clamp(16px, 4vw, 40px);
  --measure: 34rem;

  /* ── Alias tên biến của hướng cũ ──────────────────────────────────
     Template cũ còn tham chiếu var(--seal), var(--flag), var(--paper)… Trỏ
     chúng vào token mới để không trang nào vỡ trong lúc chuyển hệ; gỡ dần
     khi từng template được viết lại. */
  --paper: var(--bg);
  --seal: var(--cobalt);
  --seal-soft: var(--cobalt-soft);
  --seal-line: rgba(63, 224, 255, .38);   /* viền accent — hướng sáng dùng #B9C9F2 */
  --flag: var(--warn);
  --flag-soft: var(--warn-soft);
  --wash-2: #0C1527;                       /* nền cột đang sắp xếp */

  /* ── Chuyển động ────────────────────────────────────────────────────
     Kho này đặt token cho màu, khoảng cách, bo góc, bóng — riêng chuyển động
     thì 20 khai báo gõ tay 120/140/150ms và HAI cách viết cùng một đường
     cong (`.22,.7,.25,1` và `.22, .7, .25, 1`). Hệ quả đo được: tài liệu
     ART-DIRECTION mục 4 ghi "nền hàng hover 90ms · mở gập 120ms" trong khi
     mã chạy 120ms và 260ms — không ai sai, chỉ là không có một chỗ để đúng.

     `--ease-vao` là đường cong ease-out MẠNH: ease-out có sẵn của CSS quá
     yếu cho chuyển động cố ý (AUDIT.md mục 2). Màu dùng `ease` chứ không
     `linear` — đổi màu tuyến tính đọc ra máy móc. */
  --t-cham: 260ms;    /* mở khối gập lớn */
  --t-vua: 150ms;     /* xoay mũi tên, chuyển vị nhỏ */
  --t-nhanh: 120ms;   /* tooltip, đổi panel, nền hàng */
  --t-mau: 140ms;     /* đổi màu nền / chữ / viền */
  /* Nhấp nháy "ô này vừa đổi giá" — 500ms, CỐ Ý vượt trần 300ms của chuyển
     động giao diện. Trần đó dành cho vào/ra, thứ người dùng đang chờ. Đây là
     ngược lại: một dấu vết phải kịp lọt vào mắt người KHÔNG nhìn đúng chỗ đó,
     rồi tự biến mất. Ngắn hơn thì thành nháy giật; dài hơn thì thành trang trí. */
  --t-nhay: 500ms;
  --ease-vao: cubic-bezier(.23, 1, .32, 1);
  --ease-mo: cubic-bezier(.22, .7, .25, 1);

  /* Ký hiệu mũi tên / dấu tick vẽ bằng ĐÚNG hình học Lucide 0.462 (mask, tô
     bằng currentColor) chứ không phải glyph Unicode ▾ ↕ ✓. Lý do: một bộ
     icon duy nhất trên toàn giao diện — nét, bo đầu và tỉ lệ khớp với 15 icon
     inline; glyph Unicode đổi hình theo font hệ điều hành.
     High Contrast không dựng được mask → rơi về glyph, xem mục forced-colors. */
  --ic-chevron: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>');
  --ic-sort: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>');
  --ic-up: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7"/><path d="M12 19V5"/></svg>');
  --ic-down: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>');
  --ic-check: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>');
}

/* ═══ VOLT-light ══════════════════════════════════════════════════════
   Cùng cấu trúc, đảo lớp: nền porcelain-lam #EEF2F9, bảng điều khiển trắng,
   quầng sáng giảm 45%, lưới đậm hơn một chút vì trên nền sáng lưới mờ hơn.

   Bốn giá trị của prototype đã sửa vì trượt AA trên nền sáng (đo cả trên
   #EEF2F9 lẫn trên mặt thẻ trắng, lấy giá trị xấu hơn):
     ac2     #0A7FA6 → 4,07:1  ⇒ #086B8D (5,35:1)
     steelLn #7E92B8 → 2,80:1  ⇒ #586680 (5,16:1)
     up      #088052 → 4,43:1  ⇒ #07754B (5,12:1)
     amber   #96660D → 4,45:1  ⇒ #8A5D0B (5,12:1)

   Mặc định là TỐI: VOLT là bản sắc của sản phẩm, sáng là lựa chọn. Người đọc
   bấm công tắc thì lựa chọn được nhớ; không bấm thì luôn ra bản tối, kể cả
   khi hệ điều hành đang để sáng. */
:root[data-theme="light"] {
  color-scheme: light;

  --bg: #EEF2F9;
  --surface: #FFFFFF;
  --surface-2: #F5F8FD;
  --head: #E9EFF8;

  --stage: #FFFFFF;
  --stage-2: #F3F6FC;
  --stage-line: rgba(30, 70, 150, .18);
  --stage-mid: #F7FAFF;
  --on-stage: #0C1B38;
  --on-stage-2: #3E5379;

  --ink: #0C1B38;
  --ink-2: #3E5379;
  --muted: #4E608A;
  --faint: #5A6C92;

  --rule: rgba(30, 70, 150, .14);
  --rule-strong: rgba(30, 70, 150, .26);

  /* Đẩy bão hoà accent (review 13/08: "quá dịu, không tạo cảm giác live").
     #1D4FD7: 5,93:1 trên nền, 6,66:1 trên panel trắng — vẫn dư chuẩn AA. */
  --cobalt: #1D4FD7;
  --cobalt-strong: #16368F;
  --cobalt-soft: rgba(29, 79, 215, .09);
  --cobalt-bright: #1D4FD7;
  --cobalt-deep: #1D4FD7;
  --on-accent: #FFFFFF;

  --emerald: #07754B;
  --emerald-soft: rgba(7, 117, 75, .10);
  --emerald-bright: #07754B;

  /* #8A5D0B đạt 5,12:1 trên trắng nhưng chữ amber còn đứng TRÊN nền
     amber-soft (hộp "Nguồn báo", "Giới hạn dữ liệu") — nền pha ăn mất ~12%
     tỉ lệ, tụt xuống ~4,4 và axe bắt 22 nút khi bản sáng thành mặc định.
     #754F0A: 6,50 trên trắng → ~5,0 trên nền pha, có đệm. */
  --amber: #754F0A;
  --amber-soft: rgba(138, 93, 11, .10);
  --warn: #CB2350;
  --warn-soft: rgba(203, 35, 80, .09);

  /* 4,70:1 trên nền trang phủ --chip-bg — sửa 29/08/2026, trước là #54678E.
     Nhãn `.vc-lop` ở /lai-suat-vay/ là chữ 10px nên phải đạt 4,5:1, mà mức cũ
     chỉ được 4,48 — thiếu 0,02. Lỗi có sẵn từ lâu, chỉ lộ hôm nay khi lượt cào
     sinh dữ liệu lãi vay và trang đó được dựng lần đầu (120 → 122 trang).
     Chọn 4,70 chứ không phải 4,62 (mức vừa đủ) để còn biên: nền trang mà đổi
     một bậc là mức vừa đủ vỡ lại ngay, và lần sau chưa chắc có trang nào lộ ra
     cho cổng kiểm bắt được. */
  --steel: #516489;
  --steel-line: #586680;

  --acR: 29, 79, 215;       --cbR: 29, 79, 215;
  --lnR: 30, 70, 150;       --gdR: 30, 70, 150;
  --upR: 7, 117, 75;        --dnR: 203, 35, 80;
  --amR: 138, 93, 11;       --stR: 84, 103, 142;

  /* Quầng sáng trên nền sáng đọc ra vết bẩn nếu để nguyên cường độ. */
  --ga: .27; --gb: .15; --gridA: .065;

  --chip-bg: rgba(12, 27, 56, .06);
  --panel: #FFFFFF;
  --panel-2: #FBFCFE;
  --panel-hi: linear-gradient(180deg, #FFFFFF, #F3F6FC);
  --acGrad: linear-gradient(115deg, #1D4FD7, #086B8D);
  --acGrad90: linear-gradient(90deg, #1D4FD7, #086B8D);
  --heroGrad: linear-gradient(115deg, #16368F 0%, #0B5F94 58%, #086B8D 100%);
  --stGrad: linear-gradient(90deg, #93A7CC, #BCC9E3);
  --bgFx:
    radial-gradient(900px 480px at 22% -8%, rgba(29, 79, 215, .10), transparent 62%),
    radial-gradient(760px 420px at 88% 4%, rgba(8, 107, 141, .08), transparent 60%);

  --seal-line: rgba(8, 107, 141, .42);
  --wash-2: #EAF0FB;
  --shadow-1: 0 1px 2px rgba(12, 27, 56, .05);
  --shadow-2: 0 14px 34px -14px rgba(12, 27, 56, .20);
}

/* Một ô icon dựng bằng mask — dùng chung cho mọi ::after ký hiệu. */
.ic-mask {
  content: ""; display: inline-block; flex: none;
  background: currentColor;
  -webkit-mask: var(--ic) center / contain no-repeat;
  mask: var(--ic) center / contain no-repeat;
}

/* ── 2. Nền ───────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
[id] { scroll-margin-top: var(--s5); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  /* 1.7: dấu tiếng Việt chồng hai tầng (ế, ộ, ữ) — dòng chật là dấu dòng trên
     chạm chữ dòng dưới. */
  font: 400 16px/1.7 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ── Hai lớp nền VOLT ──────────────────────────────────────────────────
   Lưới kỹ thuật 52px và vệt sáng radial. Cả hai `position: fixed` nên KHÔNG
   cuộn theo và KHÔNG vẽ lại khi cuộn; `pointer-events: none` để không nuốt
   cú chạm nào. Dựng bằng ::before/::after của body chứ không thêm hai <div>
   rỗng vào mọi template — nền là việc của CSS.
   `--gridA: 0` là tắt lưới, không cần bỏ luật. */
body::before, body::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
}
body::before {
  background-image:
    linear-gradient(rgba(var(--gdR), var(--gridA)) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--gdR), var(--gridA)) 1px, transparent 1px);
  /* 44px, không phải 52px của prototype (chốt 13/08 chiều — "kẻ lưới nhỏ hơn
     một chút"): trùng luôn nhịp lưới 44px sẵn có của sân khấu cũ. Đổi số này
     là phải đổi CẢ .truc-luoi lẫn hằng O trong app.js — ba nơi một nhịp. */
  background-size: 44px 44px;
}
body::after { background: var(--bgFx); }
/* Nội dung đứng trên hai lớp nền. */
body > * { position: relative; z-index: 1; }

.wrap { max-width: 1200px; margin-inline: auto; padding-inline: var(--gutter); }
.wrap-narrow { max-width: 820px; margin-inline: auto; padding-inline: var(--gutter); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  user-select: none;
}
/* Đệm một khoảng trắng cứng hai đầu: position:absolute nuốt khoảng trắng
   quanh text ẩn, trình đọc màn hình đọc dính liền với chữ đứng cạnh
   (govuk-frontend helpers/_visually-hidden.scss). */
.sr-only::before, .sr-only::after { content: "\00a0"; }
.skip {
  position: absolute; left: -9999px; top: var(--s2); z-index: 100;
  background: var(--cobalt); color: var(--on-accent); padding: var(--s3) var(--s5);
  font-weight: 600; text-decoration: none; border-radius: var(--r-sm);
}
.skip:focus { left: var(--s3); }

a { color: var(--cobalt); text-underline-offset: 2px; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 2px; }
/* Trên sân khấu tối, cobalt chỉ ~2,5:1 — outline focus gần như tàng hình,
   trượt WCAG 1.4.11. Một màu focus cho mọi nền là sai (govuk _links.scss). */
.stage :focus-visible { outline-color: var(--cobalt-bright); }
/* Đích của skip link: nhận focus chương trình nhưng người dùng không tương
   tác với chính nó — không vẽ outline (govuk skip-link, w3c/wcag#1001). */
#main:focus { outline: none; }

/* Mọi con số dữ liệu: tabular để cột thẳng hàng. Số lớn dùng Be Vietnam Pro
   800, KHÔNG dùng mono — mono chỉ còn cho timestamp và mã nguồn. */
.num, td .rate, .kv b { font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

/* Icon Lucide inline — cỡ đi theo chữ, stroke 2px thống nhất. */
.li { width: 1em; height: 1em; vertical-align: -0.14em; flex: none; }
.tag .li { width: 12px; height: 12px; }
.head-time .li, .control .li { width: 13px; height: 13px; vertical-align: -2px; }
.delta-chip .li { width: 13px; height: 13px; }
.section-head .li { width: 20px; height: 20px; color: var(--cobalt); vertical-align: -3px; }
a .li { width: 12px; height: 12px; opacity: .7; }
.bottomnav a svg.li { width: 21px; height: 21px; stroke-width: 1.75; }

/* ── 3. Đầu trang ─────────────────────────────────────────────────── */
/* Thanh tiêu đề DÍNH ĐỈNH. `backdrop-filter` thay vì nền đục: lưới kỹ thuật
   và vệt sáng vẫn thấy mờ qua thanh, nên nó đọc ra một lớp kính đặt trên bàn
   dữ liệu chứ không phải một thanh chắn. Nền vẫn phải có màu (86%) — chỉ blur
   không thôi thì chữ chồng lên số phía dưới lúc cuộn. */
.site-head {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(8px);
  backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--rule);
}
/* Trình duyệt không có `color-mix` (Safari < 16.2) rơi về nền đục — mất phần
   kính, không mất khả năng đọc. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .site-head { background: var(--surface); }
}
.head-top {
  display: flex; align-items: center; gap: var(--s5);
  min-height: 60px; flex-wrap: wrap;
}
.logo {
  font-weight: 800; font-size: 20px; letter-spacing: -.03em;
  color: var(--ink); text-decoration: none; margin-right: auto;
}
.logo b { color: var(--cobalt); font-weight: 800; }
.logo { display: inline-flex; align-items: center; gap: 8px; }
.logo-mark {
  width: 26px; height: 26px; flex: none;
  background: var(--stage); border-radius: 7px; padding: 4px;
}
.logo-mark path {
  fill: none; stroke: var(--cobalt-bright); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Motif "rate pulse" — đường nhịp mờ ngăn các vùng lớn. Trang trí CÓ danh
   tính, không phải trang trí chung chung: cùng path với logo. */
.pulse-line { display: block; width: 120px; height: 16px; margin-top: var(--s5); opacity: .5; }
.pulse-line path { fill: none; stroke: var(--cobalt); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.stage .pulse-line path { stroke: var(--cobalt-bright); }
.site-head nav { display: flex; gap: var(--s1); flex-wrap: wrap; }
.site-head nav a {
  color: var(--ink-2); text-decoration: none; font-size: 15.5px; font-weight: 500;
  padding: var(--s2) var(--s3); border-radius: var(--r-sm);
  transition: background-color var(--t-mau) ease, color var(--t-mau) ease;
}
@media (hover: hover) and (pointer: fine) {
  .site-head nav a:hover { color: var(--cobalt); background: var(--cobalt-soft); }
}
.site-head nav a[aria-current="page"] { color: var(--cobalt); font-weight: 650; }
.site-head nav span { color: var(--muted); font-size: 15.5px; padding: var(--s2) var(--s3); cursor: default; }
.site-head nav span::after {
  content: "sắp có"; font: 600 12px var(--mono); letter-spacing: .06em;
  text-transform: uppercase; margin-left: 6px; color: var(--muted);
  border: 1px solid var(--rule-strong); padding: 1px 5px; border-radius: 999px;
}
.head-time { font: 500 12.5px var(--mono); color: var(--muted); white-space: nowrap; }

/* ── 3b. Thanh trạng thái VOLT ─────────────────────────────────────────
   Con trỏ nháy sau logo, chấm mạch sống, đồng hồ giờ VN, công tắc sáng/tối.
   Cả bốn đều là TRẠNG THÁI HỆ THỐNG, nên chúng đứng cùng nhau ở đầu trang và
   dùng mono — đây là chỗ mono có nghĩa thật, không phải để giả vẻ kỹ thuật. */
.head-sys { display: flex; align-items: center; gap: var(--s4); margin-left: auto; }
.head-clock {
  font: 500 12.5px var(--mono); letter-spacing: .12em; color: var(--muted);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Đồng hồ chỉ có nghĩa khi JS chạy; không có JS thì nó là ô rỗng nhấp nháy. */
.head-clock:empty { display: none; }
.head-live {
  display: inline-flex; align-items: center; gap: 7px;
  font: 500 12.5px var(--mono); letter-spacing: .12em; color: var(--emerald);
  white-space: nowrap;
}
/* Mốc lớp thị trường, đứng cạnh bản chốt (17/08). Tông COBALT chứ không phải
   emerald: hai mốc khác lớp thì phải khác màu, nếu không người đọc tưởng một
   mốc bị in hai lần. Cùng bảng màu lớp đang dùng khắp trang — thị trường là
   cobalt, niêm yết là thép. */
.head-tt {
  display: inline-flex; align-items: center;
  font: 500 12.5px var(--mono); letter-spacing: .12em; color: var(--cobalt-strong);
  white-space: nowrap;
}
.head-tt::before {
  content: "·"; color: var(--faint); margin: 0 9px 0 0; letter-spacing: 0;
}
/* Khung hẹp: đồng hồ đi trước, rồi tới mốc thị trường. Bản chốt là mốc cuối
   cùng được phép biến mất — nó là lời hứa kiểm chứng được của trang.
   Luật ẩn/hiện của mốc thị trường KHÔNG còn ở đây: nó đi theo ngân sách bề
   ngang của hàng đầu trang nên phải đứng cuối file, xem mục 49 (`@media
   (max-width: 1319px)`) và mục 50 (`@media (min-width: 1280px)`).

   19/08 — SỰ CỐ PHẢI GHI LẠI. Lượt 17/08 dời luật đi nhưng để lại dấu `}` mồ
   côi ngay tại đây. Ở cấp cao nhất của biểu định kiểu, một `}` lẻ KHÔNG bị bỏ
   qua: bộ phân tích đọc nó như phần mở đầu của một luật mới rồi nuốt tiếp mọi
   thứ cho tới dấu `{` kế tiếp — tức nuốt trọn cả khối `.nut-theme { … }` ngay
   dưới. Hậu quả nhìn thấy được là công tắc sáng/tối mất `appearance:none`,
   `border:0`, `background:none` nên trình duyệt vẽ lại nút mặc định của nó:
   một hộp xám vuông viền 2px bọc quanh viên nang — đúng "khung xấu" chủ dự án
   chụp được. Bài học: xoá một luật thì xoá cả cặp ngoặc của nó, và một lỗi cú
   pháp CSS không bao giờ chỉ hỏng đúng chỗ nó đứng. */
/* CÔNG TẮC mặt trời/mặt trăng (14/08: "chuyển thành công tắc mặt trăng/mặt
   trời dễ nhìn thấy, đậm lên"). Ba tầng đọc được ngay cả khi liếc: rãnh
   viền đậm 2px · hai biểu tượng đứng sẵn hai đầu · núm trượt đặc có bóng.
   Biểu tượng của phía ĐANG BẬT sáng lên, phía kia mờ đi — người dùng thấy
   ngay mình đang ở đâu và bấm sẽ sang đâu. */
.nut-theme {
  appearance: none; cursor: pointer; padding: 0; border: 0; background: none;
  line-height: 0; border-radius: 999px;
}
.nt-track {
  position: relative; display: inline-flex; align-items: center;
  gap: 4px; width: 66px; height: 32px; padding: 0 7px;
  justify-content: space-between; box-sizing: border-box;
  border-radius: 999px; border: 2px solid rgba(var(--cbR), .55);
  background: var(--cobalt-soft);
  box-shadow: 0 0 14px rgba(var(--cbR), .18), inset 0 1px 2px rgba(12, 27, 56, .10);
  transition: border-color var(--t-mau) ease, box-shadow var(--t-mau) ease;
}
.nt-ic { position: relative; z-index: 1; display: inline-flex; line-height: 0;
  transition: color var(--t-mau) ease, opacity var(--t-mau) ease; }
.nt-ic .lucide { width: 16px; height: 16px; stroke-width: 2.4; }
/* Núm trượt: 24px đặc, nằm dưới biểu tượng (z-index 0) nên biểu tượng của
   phía đang bật đọc được TRÊN nền núm. */
.nt-knob {
  position: absolute; z-index: 0; top: 50%; left: 3px;
  width: 24px; height: 24px; margin-top: -12px; border-radius: 50%;
  background: var(--acGrad);
  box-shadow: 0 2px 6px rgba(12, 27, 56, .35);
  transition: transform var(--t-vua) var(--ease-vao);
}
/* Sáng: núm ở bên MẶT TRỜI. Tối (aria-checked=true): núm trượt sang mặt trăng. */
.nut-theme[aria-checked="true"] .nt-knob { transform: translateX(32px); }
.nut-theme .nt-sun { color: var(--on-accent); }
.nut-theme .nt-moon { color: var(--muted); opacity: .75; }
.nut-theme[aria-checked="true"] .nt-sun { color: var(--muted); opacity: .75; }
.nut-theme[aria-checked="true"] .nt-moon { color: var(--on-accent); opacity: 1; }
@media (hover: hover) and (pointer: fine) {
  .nut-theme:hover .nt-track {
    border-color: var(--cobalt); box-shadow: 0 0 20px rgba(var(--cbR), .38);
  }
}
.nut-theme:focus-visible { outline: none; }
.nut-theme:focus-visible .nt-track {
  outline: 2px solid var(--cobalt); outline-offset: 2px;
}
/* Nút chỉ hiện khi JS dựng được — không có JS thì bấm vào không đổi gì. */
.nut-theme[hidden] { display: none; }

/* ── 3c. Dải biến động chạy ngang ─────────────────────────────────────
   Đây là ticker, thứ hướng cũ CẤM. Nó được nhận lại vì nội dung đổi: không
   phải chữ trang trí chạy vòng, mà là những lần điều chỉnh THẬT trên biểu
   chính thức trong hai lần đọc gần nhất — cùng dữ liệu với khối "Thay đổi
   gần nhất" phía dưới, chỉ khác chỗ đứng.

   Ba điều kiện để nó không thành đồ trang trí: dừng khi trỏ chuột vào, dừng
   hẳn với `prefers-reduced-motion`, và bản đầy đủ luôn có trong trang dưới
   dạng danh sách đọc được — dải này KHÔNG phải nơi duy nhất chứa thông tin. */
/* Dải biến động dính NGAY DƯỚI thanh tiêu đề. `top` không gõ cứng mà đọc từ
   biến — chiều cao thanh tiêu đề đổi theo bề rộng màn (nav xuống hàng), gõ
   một con số là dải hở một khe hoặc chồng lên thanh ở đúng những khung giữa.
   app.js đo thanh thật rồi ghi biến; chưa có JS thì rơi về 60px, đúng
   `min-height` khai ở `.head-top`. */
.ticker {
  position: sticky; top: var(--cao-dau, 60px); z-index: 29;
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--surface-2) 92%, transparent);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  overflow: hidden;
}
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .ticker { background: var(--surface-2); }
}
.ticker-track { display: flex; width: max-content; animation: ls-ticker 46s linear infinite; }
.ticker-track { animation-play-state: var(--play, running); }
@media (hover: hover) and (pointer: fine) {
  .ticker:hover .ticker-track { animation-play-state: paused; }
}
.ticker-set { display: flex; align-items: center; height: 36px; }
.ticker-set li {
  display: flex; align-items: center; gap: 9px; padding: 0 22px;
  font: 500 13px var(--mono); letter-spacing: .06em; white-space: nowrap;
  border-right: 1px solid var(--rule);
}
.ticker b { font-weight: 600; }
.ticker .up { color: var(--emerald); }
.ticker .down { color: var(--warn); }
.ticker .neu { color: var(--cobalt); }
.ticker span { color: var(--muted); }
/* Bản thứ hai chỉ để nối liền vòng chạy — trình đọc màn hình phải bỏ qua. */
.ticker-set[aria-hidden="true"] { pointer-events: none; }

/* ── 3d. Khung HUD góc ─────────────────────────────────────────────────
   VOLT §7: hai nét 14×14px ở góc trên-trái và dưới-phải, màu accent 70%. Đây
   là chi tiết làm khối đọc ra "màn hình thiết bị" thay vì "thẻ web" — rẻ hơn
   mọi hiệu ứng khác trong hệ và không tốn một byte JS.
   Chỉ gắn cho khối CÓ VIỀN và CÓ VỊ TRÍ: dán lên mọi thẻ thì nó thành hoa
   văn, mất hết ý nghĩa "đây là vùng đang đo". */
.hud { position: relative; }
.hud::before, .hud::after {
  content: ""; position: absolute; width: 14px; height: 14px; pointer-events: none;
}
.hud::before {
  top: -1px; left: -1px;
  border-top: 1px solid rgba(var(--acR), .7);
  border-left: 1px solid rgba(var(--acR), .7);
}
.hud::after {
  bottom: -1px; right: -1px;
  border-bottom: 1px solid rgba(var(--acR), .7);
  border-right: 1px solid rgba(var(--acR), .7);
}

/* ── 3e. Hệ quầng sáng ─────────────────────────────────────────────────
   VOLT §1. Luật phân lớp: THỊ TRƯỜNG có quầng cyan · NIÊM YẾT tông thép,
   KHÔNG quầng. Đây là chỗ quầng sáng mang thông tin chứ không phải trang trí
   — nhìn một cái là biết con số thuộc lớp nào mà không cần đọc nhãn. */
.btn { box-shadow: 0 0 26px rgba(var(--acR), var(--ga)); }
.logo b { text-shadow: 0 0 18px rgba(var(--acR), var(--gb)); }
.chips [aria-pressed="true"], .chips [aria-current="page"] {
  box-shadow: 0 0 14px rgba(var(--acR), var(--gb));
}
/* Tiền lãi — con số người đọc thật sự tới đây để lấy. */
.ck-lai b, .ck-money { text-shadow: 0 0 22px rgba(var(--acR), var(--gb)); }
/* Thanh xếp hạng lớp thị trường. Lớp niêm yết dùng `.r10-bar.ny` — không quầng. */
.r10-bar i { box-shadow: 0 0 16px rgba(var(--acR), var(--gb)); }
.r10-bar.ny i { background: var(--stGrad); box-shadow: none; }
.delta-chip.up { text-shadow: 0 0 12px rgba(var(--upR), var(--gb)); }
.delta-chip.down { text-shadow: 0 0 12px rgba(var(--dnR), var(--gb)); }
.hc-line { filter: drop-shadow(0 0 8px rgba(var(--acR), var(--gb))); }
/* Quầng sáng là hiệu ứng của MÀU. Ở High Contrast màu bị ép về hệ nên quầng
   chỉ còn là một vệt mờ vô nghĩa quanh chữ — bỏ hẳn. */
@media (forced-colors: active) {
  .btn, .logo b, .chips [aria-pressed="true"], .chips [aria-current="page"],
  .ck-lai b, .ck-money, .r10-bar i, .delta-chip.up, .delta-chip.down {
    box-shadow: none; text-shadow: none;
  }
  .hc-line { filter: none; }
}

/* ── 4. Sân khấu dữ liệu (hero cockpit) ───────────────────────────── */
/* MỘT tấm tối mỗi trang, bo lớn, nằm trong khung trang — không full-bleed.
   Lưới kẻ rất mờ tạo chất "định lượng"; KHÔNG texture nào khác. */
.stage {
  position: relative; margin-top: var(--s5);
  background:
    /* Lưới phải nói "đây là mặt đo", không phải "đây là hình nền". 2% là
       ngưỡng còn thấy được khi nghiêng màn hình mà không cạnh tranh với số. */
    linear-gradient(rgba(255,255,255,.02) 1px, transparent 1px) 0 0 / 100% 44px,
    linear-gradient(90deg, rgba(255,255,255,.02) 1px, transparent 1px) 0 0 / 44px 100%,
    linear-gradient(160deg, var(--stage) 0%, var(--stage-mid) 55%, var(--stage-2) 100%);
  border-radius: var(--r-lg); color: var(--on-stage);
  padding: clamp(24px, 3.4vw, 44px);
  box-shadow: var(--shadow-2);
}
.stage a { color: var(--cobalt-bright); }
.stage-grid {
  display: grid; gap: var(--s6);
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  align-items: start;
}
/* Kết quả đứng TRƯỚC trong DOM (mobile đọc từ trên xuống gặp câu trả lời
   trước); CHỈ desktop hoán vị bằng order — chữ trái, số phải. Đặt order
   không media query là mobile cũng bị hoán vị ngược lại — đúng lỗi đã đo
   được: ck_truoc_loc = false. */
@media (min-width: 901px) {
  .stage-lede { order: 1; }
  .stage-ans { order: 2; }
}
/* Motif pulse mờ chạy sát đáy sân khấu — nhận diện, không trang trí rời. */
.stage { overflow: hidden; }
.stage-pulse {
  position: absolute; left: 0; right: 0; bottom: -2px; width: 100%; height: 26px;
  margin: 0; opacity: .16; pointer-events: none;
}
/* Bộ điều khiển gập: desktop luôn mở và giấu nút gập; mobile là disclosure. */
.ctl-fold { border: 0; }
.ctl-fold > summary { list-style: none; cursor: pointer; display: none;
  font: 600 14px var(--sans); color: var(--cobalt-bright);
  padding: var(--s2) 0; }
.ctl-fold > summary::-webkit-details-marker { display: none; }
.ctl-fold > summary::after {
  content: ""; display: inline-block; width: 15px; height: 15px;
  margin-left: 4px; vertical-align: -3px; background: currentColor;
  -webkit-mask: var(--ic-chevron) center / contain no-repeat;
  mask: var(--ic-chevron) center / contain no-repeat;
  transition: transform var(--t-vua) var(--ease-vao);
}
.ctl-fold[open] > summary::after { transform: rotate(180deg); }

/* Sân khấu gọn cho trang kỳ hạn / ngân hàng / công cụ — CÙNG một component. */
.stage-slim { padding: clamp(20px, 2.6vw, 32px) clamp(24px, 3.4vw, 44px); }
.stage-slim h1 { font-size: clamp(24px, 3vw, 34px); }
.stage-slim .stage-grid { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); align-items: center; }
.ck-slim { padding: var(--s4) var(--s5); }
.ck-slim .ck-num { font-size: clamp(32px, 3.4vw, 44px); }
.stage .kicker {
  font: 600 12px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--on-stage-2); margin: 0 0 var(--s3);
}
.stage h1 {
  margin: 0 0 var(--s2); color: var(--on-stage);
  font-size: clamp(28px, 3.6vw, 42px); line-height: 1.12;
  font-weight: 800; letter-spacing: -.03em; text-wrap: balance;
}
.stage .sub { margin: 0 0 var(--s5); color: var(--on-stage-2); font-size: 16px; }

/* Bộ điều khiển trên nền tối */
.stage .control > span:first-of-type {
  font: 600 12.5px var(--mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--on-stage-2);
}
.stage .amount input {
  font: 800 26px/1.2 var(--sans); font-variant-numeric: tabular-nums;
  border: 0; border-bottom: 2px solid var(--cobalt-bright);
  background: transparent; color: var(--on-stage); padding: 2px 0; width: 13ch;
  letter-spacing: -.01em;
}
.stage .amount input::placeholder { font: 400 16px var(--sans); color: var(--on-stage-2); }
.stage .amount input:focus {
  outline: 2px solid var(--cobalt-bright); outline-offset: 3px;
  border-bottom-color: var(--on-stage);
}
.stage .amount > span { color: var(--on-stage-2); font-weight: 600; }
.stage .so-chu { color: var(--on-stage-2); }
.stage .chips a, .stage .chips button {
  background: var(--chip-bg); border-color: var(--stage-line);
  color: var(--on-stage);
}
@media (hover: hover) and (pointer: fine) {
  .stage .chips a:hover, .stage .chips button:hover {
    background: var(--cobalt-soft); color: var(--on-stage);
  }
}
.stage .chips [aria-current="page"], .stage .chips [aria-pressed="true"] {
  background: var(--cobalt-bright); border-color: var(--cobalt-bright);
  color: var(--stage); font-weight: 700;
}
.stage .loc-ghi { color: var(--on-stage-2); }
.stage .controls { border: 0; padding-block: 0; }

/* Thẻ kết quả — câu trả lời của trang */
.ck {
  background: var(--chip-bg); border: 1px solid var(--stage-line);
  border-radius: var(--r); padding: var(--s5);
}
.ck-k {
  font: 600 12.5px/1.4 var(--mono); letter-spacing: .12em;
  text-transform: uppercase; color: var(--on-stage-2); margin: 0 0 var(--s3);
}
.ck-who { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s2); }
.ck-who .mono-box { border-color: var(--stage-line); color: var(--on-stage-2); background: transparent; }
.ck-who a { color: var(--on-stage); font-weight: 650; font-size: 17px; text-decoration-color: var(--stage-line); }
/* Số dẫn đầu là VẬT THỂ CHÍNH của trang, không phải một dòng chữ to. Mono
   weight 800, tô bằng gradient hero và có quầng sáng — đây là chỗ duy nhất
   trên trang được phép tô gradient lên chữ.
   `color` vẫn khai màu đặc TRƯỚC `background-clip`: trình duyệt không dựng
   được clip thì rơi về màu đó chứ không mất chữ. */
.ck-num {
  font: 800 clamp(52px, 6vw, 88px)/.98 var(--mono); letter-spacing: -.035em;
  color: var(--on-stage); font-variant-numeric: tabular-nums;
  background: var(--heroGrad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 26px rgba(var(--acR), var(--ga)));
}
.ck-num i { font: 600 15px var(--mono); font-style: normal; letter-spacing: 0; color: var(--on-stage-2); margin-left: 6px; }
.ck-lai { display: block; margin-top: var(--s3); color: var(--emerald-bright); font-weight: 650; font-size: 16.5px; font-variant-numeric: tabular-nums; }
.ck-delta { display: block; margin-top: 2px; color: var(--on-stage-2); font-size: 14.5px; font-variant-numeric: tabular-nums; }
.ck-note { display: block; margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--stage-line); color: var(--on-stage-2); font-size: 13px; }

/* Top 5 trong sân khấu — thanh cobalt-bright trên nền tối */
.ck-bars { margin-top: var(--s4); display: grid; gap: 7px; }
.ck-bar { display: grid; grid-template-columns: 92px 1fr 52px; gap: var(--s3); align-items: center; font-size: 14px; }
.ck-bar .t { color: var(--on-stage-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ck-bar .b { height: 8px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; }
.ck-bar .b i { display: block; height: 100%; border-radius: 999px; background: var(--cobalt-bright); }
.ck-bar:first-child .b i { background: var(--acGrad90); }
.ck-bar .v { color: var(--on-stage); font-weight: 650; text-align: right; font-variant-numeric: tabular-nums; }

/* Caveat khảo sát trên sân khấu */
.ck.kshat { margin-top: var(--s4); }
.ck.kshat .ck-num { font-size: clamp(30px, 3vw, 38px); }
.ck-warn { display: block; margin-top: var(--s2); padding-left: var(--s2); border-left: 2px solid var(--amber); color: var(--amber); font-size: 13.5px; }

/* Con trỏ cho tooltip nghiệp vụ ([data-tip]) — dùng ở ô ngân hàng vừa
   đổi biểu trong bảng thị trường. */
[data-tip] { cursor: help; }

/* ── 5. Market pulse ──────────────────────────────────────────────── */
.pulse {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin-top: var(--s5);
}
.pulse-card {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); padding: var(--s4) var(--s5);
  box-shadow: var(--shadow-1);
  display: grid; grid-template-columns: 1fr auto; align-items: end; gap: var(--s2);
}
.pulse-card dt {
  grid-column: 1 / -1;
  font: 600 12.5px/1.4 var(--mono); letter-spacing: .11em;
  text-transform: uppercase; color: var(--muted);
}
.pulse-card dd { margin: 0; }
.pulse-num {
  font: 800 32px/1.05 var(--sans); letter-spacing: -.02em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.pulse-num i { font: 600 13px var(--mono); font-style: normal; color: var(--muted); letter-spacing: 0; margin-left: 4px; }
.pulse-sub { display: block; margin-top: 3px; font-size: 13px; color: var(--ink-2); }
.pulse-sub.caveat { color: var(--amber); }
/* min-width: 0 cho cả ô — sparkline 120px trong thẻ hẹp (tablet, 2 cột) phải
   co lại chứ không đẩy thẻ tràn ngang. */
.pulse-card dd { min-width: 0; }
.pulse-spark { justify-self: end; align-self: center; max-width: 100%; }
.pulse-spark svg { max-width: 100%; height: auto; display: block; }
.pulse-spark polyline { fill: none; stroke: var(--cobalt); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pulse-spark .dot { fill: var(--cobalt); }

/* ── 5b. Dot plot chung: khảo sát cạnh chính thức ─────────────────── */
/* Bảng chênh hai lớp — thay sơ đồ hai chấm (gỡ 12/08). Bốn cột bề rộng cố
   định; hàng tiêu đề dùng đúng khuôn lưới của hàng dữ liệu nên không có cách
   nào lệch. */
.chenh-list { margin: 0; padding: 0; list-style: none; }
/* 13/08 tối: mục 01 thành BẢNG ĐẦY ĐỦ mọi ngân hàng — bốn cột theo lời chủ
   dự án: Ngân hàng · Niêm yết · Thị trường · Ghi chú (điều kiện bậc tiền).
   Chip chênh nhập vào ô thị trường thay vì chiếm một cột riêng. */
.chenh-list li {
  display: grid; align-items: center; gap: var(--s2) var(--s4);
  grid-template-columns: minmax(0, 1fr) 108px 168px minmax(170px, 27%);
  padding: var(--s3) 0; border-bottom: 1px solid var(--rule);
}
.chenh-list li:last-child { border-bottom: 0; }
.chenh-head {
  font: 600 12px/1.3 var(--mono); letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); padding-bottom: var(--s2) !important;
}
.chenh-head span:nth-child(2), .chenh-head span:nth-child(3) { text-align: right; }
.chenh-who { min-width: 0; }
.chenh-ny, .chenh-ks { text-align: right; font-variant-numeric: tabular-nums; }
.chenh-ny { color: var(--ink-2); font-size: 16px; }
.chenh-ks b { font-weight: 800; font-size: 19px; color: var(--ink); }
.chenh-ny i, .chenh-ks i { font-style: normal; font-size: 12px; color: var(--muted); margin-left: 3px; }
.chenh-ks .delta-chip { margin-left: 7px; vertical-align: 2px; }
/* Chip kỳ hạn 6T/12T: con số thuộc kỳ nào phải đọc được ngay cạnh số —
   bảng nay trộn hai kỳ hạn theo luật "mức cao nhất trong 6 và 12 tháng"
   (chốt 13/08 tối). Bản thép cho niêm yết, bản accent cho thị trường. */
.chenh-ky {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  border-radius: 6px; font: 700 12px var(--mono); letter-spacing: .06em;
  border: 1px solid rgba(var(--stR), .5); color: var(--steel);
  vertical-align: 2px;
}
.chenh-ky.tt { border-color: rgba(var(--cbR), .55); color: var(--cobalt-strong); }
/* Ghi chú = điều kiện: bậc tiền amber (đúng vai màu của hệ), phần nhãn tin
   cậy để mực phụ. Hàng chưa có lớp thị trường thì cả ô là một câu giải thích. */
.chenh-ghi { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.chenh-ghi b { color: var(--amber); font-weight: 650; }
.chenh-ghi .na, .chenh-ny .na, .chenh-ks .na { font-size: 14px; color: var(--muted); }
@media (max-width: 760px) {
  /* li.chenh-head: `.chenh-list li` (0,1,1) đè `.chenh-head` (0,1,0) —
     display:none thua về ĐẶC HIỆU nên header vẫn hiện trên điện thoại
     (ảnh chủ dự án 23:17). Cùng bài học specificity với hover light. */
  .chenh-list li.chenh-head { display: none; }
}

.rank10 { margin: 0; padding: 0; list-style: none; counter-reset: r10; }
.rank10 li {
  counter-increment: r10;
  display: grid; align-items: center; gap: var(--s2) var(--s4);
  /* Cột tên có BỀ RỘNG CỐ ĐỊNH, không `auto`. Sparkline chỉ xuất hiện ở
     những hàng có đủ chuỗi 2 ngày, nên để `auto` thì mỗi hàng rộng một kiểu và
     thanh xếp hạng bắt đầu ở những vị trí khác nhau — mà thanh đó chỉ có nghĩa
     khi mọi hàng cùng một gốc. Đo 12/08: ba trong năm hàng có sparkline, ba
     thanh lệch nhau tới 130px. */
  grid-template-columns: 28px minmax(0, 268px) minmax(120px, 1fr) 96px 132px;
  /* MỌI cột đều có tên, kể cả cột số thứ tự. `.rank-ks` đặt lại vùng cho dòng
     thứ hai; nếu bảng vùng chỉ kê bốn tên trong khi lưới có năm rãnh thì tên
     bị lệch đi một rãnh và `.r10-who` rơi vào rãnh 28px — chữ tên ngân hàng
     xuống hàng từng từ một. Kê đủ năm tên là chốt lại phép ánh xạ đó. */
  grid-template-areas: "stt who bar rate lai";
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--rule);
  transition: background-color var(--t-mau) ease;
}
@media (hover: hover) and (pointer: fine) {
  .rank10 li:hover { background: var(--surface-2); }
}
.rank10 li:last-child { border-bottom: 0; }
.rank10 li::before {
  content: counter(r10); font: 700 14px var(--mono);
  color: var(--muted); text-align: right;
}
.rank10 li:nth-child(-n+3)::before { color: var(--cobalt); }
.r10-who { display: flex; align-items: center; gap: var(--s3); min-width: 0;
           justify-content: space-between; }
.r10-who .bank-name { white-space: nowrap; }
.r10-bar { height: 10px; border-radius: 999px; background: var(--cobalt-soft); overflow: hidden; }
.r10-bar i { display: block; height: 100%; border-radius: 999px; background: var(--cobalt); }
.rank10 li:first-child .r10-bar i { background: linear-gradient(90deg, var(--cobalt), var(--cobalt-bright)); }
.r10-rate {
  text-align: right; font: 800 21px/1.1 var(--sans);
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.r10-rate .fnote { font-size: 11.5px; }
.r10-lai { text-align: right; font-size: 13.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.r10-lai b { display: block; font-weight: 650; color: var(--ink); font-size: 14.5px; }
.r10-meta { grid-column: 2 / -1; font-size: 13px; color: var(--muted); }

.card {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); box-shadow: var(--shadow-1); overflow: hidden;
}
.card-head {
  display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s4) var(--s5); border-bottom: 1px solid var(--rule);
}
.card-head h3 { margin: 0; font-size: 16.5px; font-weight: 700; letter-spacing: -.01em; }
.card-head .sub { font-size: 13.5px; color: var(--muted); margin-left: auto; }
.card-foot { padding: var(--s3) var(--s5); border-top: 1px solid var(--rule); font-size: 14px; }
.btn-ghost {
  display: inline-block; padding: 9px 16px; border-radius: 999px;
  border: 1px solid var(--rule-strong); color: var(--cobalt);
  font-weight: 600; font-size: 14.5px; text-decoration: none; background: var(--surface);
  cursor: pointer; transition: border-color var(--t-nhanh) ease, background-color var(--t-nhanh) ease;
}
@media (hover: hover) and (pointer: fine) {
  .btn-ghost:hover { border-color: var(--cobalt); background: var(--cobalt-soft); }
}

/* ── 7. Khảo sát thị trường — dải thẻ ─────────────────────────────── */
.survey { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.sv-card {
  background: var(--surface); border: 1px solid var(--rule);
  border-left: 3px solid var(--amber); border-radius: var(--r-sm);
  padding: var(--s4); box-shadow: var(--shadow-1);
}
.sv-num { font: 800 26px/1.1 var(--sans); color: var(--ink); font-variant-numeric: tabular-nums; }
.sv-who { display: block; margin-top: 2px; font-weight: 650; font-size: 15.5px; }
.sv-meta { display: block; margin-top: 2px; font-size: 13px; color: var(--ink-2); }

/* ── 8. Biến động — line chart ────────────────────────────────────── */
.chart { width: 100%; height: auto; display: block; }
/* Tooltip của biểu đồ Plot: hộp TRẮNG chữ TRẮNG ở theme tối (chủ dự án chụp
   được 15/08). Plot chèn `:where(.plot-xxxx){--plot-background: white}` vào
   thẻ <style> BÊN TRONG SVG nó tự dựng, rồi tô hộp bằng đúng token đó, trong
   khi CHỮ trong hộp tô bằng `currentColor` — ở bản tối là mực sáng, nên đo
   được 1,15:1, không đọc nổi một chữ. `style:{background:"transparent"}` ở
   lời gọi Plot chỉ đặt thuộc tính `background`, không đặt token này.
   `:where()` có độ cụ thể 0 nên một selector lớp là đủ thắng.
   GIỮ LẠI qua lượt lùi giao diện 15/08: đây là bản vá LỖI ĐỌC ĐƯỢC, không
   thuộc đợt đổi bảng màu bị lùi. */
.chart { --plot-background: var(--panel); }
.chart g[aria-label="tip"] path { stroke: rgba(var(--lnR), .55); }
.chart .band { fill: var(--cobalt-soft); opacity: .55; }
.chart .line { fill: none; stroke: var(--cobalt); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.chart .dot { fill: var(--surface); stroke: var(--cobalt); stroke-width: 2; }
/* Ngày độ phủ thấp (<70% số ngân hàng của ngày phủ rộng nhất): điểm rỗng nét
   đứt. Ngày đó KHÔNG bị xoá — trung vị của 6 ngân hàng đứng ngang hàng trung
   vị của 30 ngân hàng mới là nói dối bằng hình; đánh dấu là đủ. */
.chart .dot.thua { fill: var(--bg); stroke-dasharray: 2 2.4; }
.chart-meta { display: flex; gap: var(--s4) var(--s5); flex-wrap: wrap; font-size: 13px; color: var(--muted); padding-top: var(--s3); }
.chart-note { font-size: 13.5px; color: var(--ink-2); }
/* (bố cục 5 cột cũ của khối biến động đã thay bằng nhật ký — mục 35;
   các luật delta-ky/delta-chao dùng chung khai ở đó) */
.delta-chip {
  font: 650 13.5px var(--sans); padding: 2px 9px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.delta-chip.up { color: var(--emerald); background: var(--emerald-soft); }
.delta-chip.down { color: var(--warn); background: var(--warn-soft); }
.delta-when { font: 500 12px var(--mono); color: var(--muted); }

/* ── 8b. Hình phụ trợ: barcode, gapvis, dev, slope, ck-truc ───────── */
.ck-truc { display: block; margin-top: var(--s2); font: 500 12.5px var(--mono); color: var(--on-stage-2); }

/* Barcode phân bố: mỗi ngân hàng một vạch 1px, chỗ trùng mức tự đậm lên;
   vạch trung vị cobalt đậm hơn. */
.barcode { position: relative; display: block; height: 14px; margin-top: var(--s2); }
.barcode::before { content: ""; position: absolute; inset: 6.5px 0 auto; height: 1px; background: var(--rule); }
.barcode i { position: absolute; top: 0; width: 1px; height: 14px; background: var(--ink); opacity: .4; }
.barcode b { position: absolute; top: -2px; width: 2.5px; height: 18px; background: var(--cobalt); }

/* Hai chấm khảo sát–chính thức: chấm mực = chính thức, chấm amber = khảo sát,
   đoạn nối là KHOẢNG — không in con số chênh. */
.gapvis { position: relative; display: block; height: 16px; margin-top: var(--s3); }
.gapvis::before { content: ""; position: absolute; inset: 7.5px 0 auto; height: 1px; background: var(--rule); }
.gapvis u { position: absolute; top: 7px; height: 2px; background: repeating-linear-gradient(90deg, var(--rule-strong) 0 4px, transparent 4px 8px); }
.gapvis i { position: absolute; top: 4px; width: 8px; height: 8px; border-radius: 999px; transform: translateX(-4px); }
.gapvis i.w { background: var(--ink); }
.gapvis i.k { background: var(--amber); }

/* Thanh lệch quanh trung vị (Diverging bar) — vạch giữa là trung vị. */
.dev { position: relative; display: block; height: 6px; margin-top: var(--s2); background: var(--head); border-radius: 999px; overflow: hidden; }
.dev::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 1.5px; background: var(--rule-strong); z-index: 1; }
.dev i { position: absolute; top: 0; bottom: 0; }
.dev i.up { left: 50%; background: var(--cobalt); border-radius: 0 999px 999px 0; }
.dev i.down { right: 50%; background: var(--muted); border-radius: 999px 0 0 999px; }


/* Panel tooltip do Floating UI định vị — flip/shift nên không bao giờ bị cắt
   ở mép nhìn như bản CSS. */
.tip-panel {
  position: absolute; top: 0; left: 0; z-index: 40; max-width: 280px;
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--rule-strong); border-radius: var(--r-sm);
  padding: 8px 11px; box-shadow: var(--shadow-2);
  font: 400 13.5px/1.5 var(--sans); opacity: 0;
  /* Tooltip ĐI RA TỪ chỗ nó giải thích, không hiện ra từ hư không.
     Bản trước chỉ mờ dần opacity — đúng thứ AUDIT.md mục 3 gọi là "pure-fade
     entrance with no initial transform": panel không nói được nó thuộc về ô
     nào, và ở bảng 38 dòng thì mỗi ô đều có một tooltip giống hệt.
     4px là đủ để mắt bắt được hướng mà không thành một cú trượt. */
  transform: translateY(-4px);
  transition: opacity var(--t-nhanh) ease, transform var(--t-nhanh) var(--ease-vao);
}
.tip-panel[data-cho="top"] { transform: translateY(4px); }
.tip-panel[data-cho="left"] { transform: translateX(4px); }
.tip-panel[data-cho="right"] { transform: translateX(-4px); }
.tip-panel[data-hien] { opacity: 1; transform: none; }
/* Người tắt chuyển động vẫn cần tooltip HIỆN RA — chỉ bỏ phần dịch chuyển,
   giữ phần mờ dần (mục 6: giảm chứ không phải về không). Luật `transition:
   none !important` ở khối reduced-motion đã lo phần thời lượng; chỗ này chỉ
   bảo đảm không có trạng thái nào kẹt ở vị trí lệch 4px. */
@media (prefers-reduced-motion: reduce) {
  .tip-panel { transform: none; }
}
/* Chart đã được Plot thay bản tương tác: nhãn điểm tĩnh máy chủ vẽ đè lên
   tooltip của Plot — ẩn phần meta tĩnh đi, dữ liệu vẫn trong HTML nguồn. */
[data-plot-xong] .chart-meta { display: none; }

/* ── 9. Section ───────────────────────────────────────────────────── */
.section { padding-block: var(--s7) 0; }
.section:last-of-type { padding-bottom: var(--s7); }
.section-head { margin-bottom: var(--s5); display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
/* Căn lề tiêu đề mục theo CỘT CỦA BẢNG bên dưới (chốt 17/08 — chủ dự án:
   "canh lề lại cho chuẩn chỉnh").
   Trước đó một mục có BA mép trái khác nhau, đo ở 1440: tiêu đề 100 · nội dung
   trong thẻ 125 · đoạn mô tả 510 — con số 510 không thẳng hàng với thứ gì, nó
   chỉ là chỗ chữ rơi xuống sau khi tiêu đề hết. Mắt đọc bảng thì bắt ngay ba
   mép so le đó.
   Sửa: mục nào có bảng thì tiêu đề và mô tả lùi vào ĐÚNG bằng đệm trong của
   thẻ, nên "01 BẢNG THỊ TRƯỜNG" thẳng cột "NGÂN HÀNG"; và đoạn mô tả thành
   một CỘT có bề rộng cố định theo cột dữ liệu chứ không trôi theo độ dài tiêu
   đề. Dùng `:has()` để chỉ áp cho mục thật sự có bảng — mục chỉ có văn xuôi
   thì lùi vào là thừa. */
.section:has(> .card > .chenh-list, > .card .chenh-list) > .section-head {
  padding-inline: var(--s5);
  display: grid;
  /* ĐÚNG lưới của `.chenh-list li` — không phải một lưới hai cột trông na ná.
     Nhờ vậy tiêu đề nằm trọn cột "Ngân hàng", còn đoạn mô tả bắt đầu đúng mép
     cột "Niêm yết". Sửa cột bảng mà quên chỗ này là lệch lại ngay, nên hai
     luật để cạnh nhau và ghi rõ ràng buộc. */
  grid-template-columns: minmax(0, 1fr) 108px 168px minmax(170px, 27%);
  align-items: start;
  column-gap: var(--s4);
}
.section:has(> .card > .chenh-list, > .card .chenh-list) > .section-head > h2 {
  grid-column: 1;
}
.section:has(> .card > .chenh-list, > .card .chenh-list) > .section-head > p {
  grid-column: 2 / -1; margin: 0;
}
@media (max-width: 900px) {
  .section:has(> .card > .chenh-list, > .card .chenh-list) > .section-head {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--s2);
    padding-inline: var(--s4);
  }
}
.section-head h2 {
  margin: 0; font-size: clamp(20px, 2.2vw, 26px); font-weight: 750; letter-spacing: -.025em;
}
.section-head h2 i {
  font: 700 12px/1 var(--mono); font-style: normal; color: var(--cobalt);
  letter-spacing: .04em; border: 1px solid var(--seal-line);
  padding: 5px 7px; border-radius: 7px; vertical-align: 3px; margin-right: var(--s2);
}
.section-head p { margin: 0; color: var(--ink-2); font-size: 15.5px; max-width: var(--measure); }

/* ── 10. Bảng ─────────────────────────────────────────────────────── */
/* Bảng nằm TRONG thẻ trắng; chỉ kẻ ngang; một đường dọc duy nhất đóng khung
   cột "Cao nhất". Bảng tính vẽ ô vì mọi ô ngang giá trị nhau — biểu của bàn
   dữ liệu chỉ kẻ để mắt trượt theo dòng. */
.tablewrap { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); box-shadow: var(--shadow-1); padding: var(--s4) var(--s5); }
.table-note { padding: 0 0 var(--s3); border-bottom: 1px solid var(--rule); font-size: 14px; color: var(--muted); }
.tfoot { margin: var(--s3) 0 0; font: 500 12.5px/1.6 var(--mono); color: var(--muted); }
.scroller { overflow-x: auto; overscroll-behavior-x: contain; }
table { border-collapse: collapse; width: 100%; }
caption { text-align: left; padding: var(--s3) 0; font-size: 14px; color: var(--muted); }
thead th {
  position: sticky; top: 0; z-index: 2; background: var(--surface);
  font: 600 12.5px/1.4 var(--mono); letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); text-align: right; padding: var(--s2) var(--s3);
  white-space: nowrap; border-bottom: 1.5px solid var(--ink);
}
thead th small {
  display: block; font: 400 11.5px var(--mono); letter-spacing: .04em;
  text-transform: none; color: var(--muted); margin-top: 2px;
}
thead th:first-child { text-align: left; }
thead th.on, td.on { background: var(--cobalt-soft); }
thead th.on { box-shadow: inset 0 -2px 0 var(--cobalt); }
td { padding: var(--s3); text-align: right; border-bottom: 1px solid var(--rule); vertical-align: baseline; }
td:first-child { text-align: left; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr td, tbody tr .stick { transition: background-color var(--t-nhanh) ease; }
@media (hover: hover) and (pointer: fine) {
  tbody tr:hover td { background: var(--surface-2); }
  tbody tr:hover td.on { background: rgba(47, 104, 255, .24); }
}

.stick { position: sticky; left: 0; background: var(--surface); z-index: 1;
         padding: var(--s3); text-align: left; font-weight: 400; }
@media (hover: hover) and (pointer: fine) {
  tbody tr:hover .stick { background: var(--surface-2); }
}

.bank { display: flex; align-items: flex-start; gap: var(--s2); }
.bank-id { min-width: 0; }
/* Loại hình và sparkline nằm CÙNG một dòng. Sparkline rộng 64px, mà dòng này
   thừa hưởng bề rộng co giãn của ô tên, nên không ghim thì nó rớt xuống dòng
   dưới và đứng mồ côi bên dưới chữ "Cổ phần" — thấy rõ ở hàng SHB. */
.gop .bank-meta { display: flex; align-items: center; gap: var(--s2); white-space: nowrap; }
/* Monogram trung tính — mã ngân hàng, một màu mực, KHÔNG logo, KHÔNG màu
   riêng từng bank (docs/logo-ngan-hang-va-ban-quyen.md; test khoá). */
.mono-box {
  flex: none; display: inline-grid; place-items: center;
  min-width: 30px; height: 20px; padding-inline: 3px;
  border: 1px solid var(--rule-strong); border-radius: 6px; color: var(--ink-2);
  font: 600 11.5px/1 var(--mono); letter-spacing: .06em; background: var(--surface);
}
.bank-meta .mono-box { height: 18px; min-width: 30px; margin-right: var(--s2); vertical-align: middle; }
.bank-name { font-weight: 650; font-size: 16px; color: var(--ink); }
.bank-name a { color: inherit; text-decoration: none; }
.bank-name a:hover { color: var(--cobalt); text-decoration: underline; }
.bank-meta { display: block; font-size: 13px; color: var(--muted); font-weight: 400; }

.rate { font-weight: 600; font-size: 16px; color: var(--ink); }

/* Dấu "đk": DẤU THỊ GIÁC, không phải control. Nó chỉ báo ô này còn điều kiện;
   nguyên văn nằm trong biên nhận của hàng (một <details> mỗi hàng). Trước đây
   mỗi dấu là một <button> có tooltip — 246 nút trên /so-sanh/, tức 246 lần bấm
   Tab. Bỏ tooltip CSS luôn: hai đường dẫn tới cùng một nội dung, đường kém hơn
   phải biến mất. */
.fnote {
  font: 600 11.5px var(--mono); color: var(--warn); vertical-align: super;
  margin-left: 1px; cursor: help; padding: 0 1px;
}
.rate.na { color: var(--muted); font-weight: 400; }
td.on .rate.na { color: var(--ink-2); }
.rate.top { box-shadow: inset 0 -3px 0 var(--cobalt); font-weight: 700; }
.cellnote { display: block; font: 400 12px/1.5 var(--mono); color: var(--muted); margin-top: 2px; }
td.on .cellnote { color: var(--ink-2); }

/* Dải chú giải */
.legend {
  margin: 0 0 var(--s3); padding-bottom: var(--s3);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s6);
  border-bottom: 1px solid var(--rule);
}
.legend > div { display: flex; align-items: baseline; gap: var(--s2); }
.legend dt {
  font: 600 11.5px var(--mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); white-space: nowrap;
}
.legend dd { margin: 0; font-size: 14px; color: var(--ink); white-space: nowrap; }

/* ── 11. Bảng gộp ─────────────────────────────────────────────────── */
.gop table { table-layout: auto; }
.gop thead th, .gop td { text-align: left; }
/* Ba cột SỐ canh phải, tiêu đề canh phải theo. Người đọc quét dọc một cột để
   so độ lớn; canh trái thì "10,50" và "9,00" lệch nhau đúng một chữ số và mắt
   phải đọc từng con số thay vì nhìn hình. Cột chữ (ngân hàng, nguồn, áp dụng)
   giữ canh trái. */
.gop thead th.c-cao, .gop thead th[data-xep="web"], .gop thead th.c-bao,
.gop td.c-cao, .gop td.c-web, .gop td.c-bao { text-align: right; }
.gop thead th.c-cao button, .gop thead th[data-xep="web"] button,
.gop thead th.c-bao button { justify-content: flex-end; width: 100%; }
.gop td.c-cao .cellnote, .gop td.c-web .cellnote, .gop td.c-bao .cellnote,
.gop thead th.c-cao small, .gop thead th[data-xep="web"] small,
.gop thead th.c-bao small { text-align: right; }
.gop td, .gop th { vertical-align: top; }
.gop td, .gop .stick { padding-block: var(--s4); }
.gop .c-no, .gop thead .c-no {
  width: 40px; text-align: right; padding-right: 0;
  font: 600 13px/1.35 var(--mono); color: var(--muted);
}
.gop .stick { min-width: 150px; }
.gop .group-sep td {
  background: var(--head); border-block: 1px solid var(--rule-strong);
  padding: var(--s3) var(--s4); font-size: 14px; color: var(--ink-2); box-shadow: none;
}
.gop .group-sep td b { color: var(--ink); font-weight: 650; }
.gcard-sep {
  background: var(--head); border-block: 1px solid var(--rule-strong);
  padding: var(--s3); font-size: 14px; color: var(--ink-2); list-style: none;
}
.gop thead th[data-xep] { padding: 0; }
.gop thead th[data-xep] button {
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  background: none; border: 0; cursor: pointer; width: 100%;
  text-align: inherit; padding: var(--s2) var(--s3) 0;
  display: flex; align-items: center; gap: 4px;
}
.gop thead th[data-xep] small { padding: 0 var(--s3) var(--s2); }
.gop thead th[data-xep] button:hover { color: var(--cobalt); }
/* Mũi tên nằm trong span aria-hidden BÊN TRONG nút — vẽ bằng ::after của
   chính nút thì nó lọt vào accessible name và trình đọc màn hình đọc
   "Ngân hàng ↕" (APG sortable-table). */
.gop thead th[data-xep] .sico::after {
  content: ""; display: inline-block; width: 12px; height: 12px;
  vertical-align: -2px; background: currentColor; opacity: .45;
  -webkit-mask: var(--ic-sort) center / contain no-repeat;
  mask: var(--ic-sort) center / contain no-repeat;
}
.gop thead th[aria-sort="descending"] .sico::after {
  opacity: 1; -webkit-mask-image: var(--ic-down); mask-image: var(--ic-down);
}
.gop thead th[aria-sort="ascending"] .sico::after {
  opacity: 1; -webkit-mask-image: var(--ic-up); mask-image: var(--ic-up);
}
.gop thead th[aria-sort]:not([aria-sort="none"]) button { color: var(--cobalt); }

.gop .c-cao { box-shadow: inset 1px 0 0 var(--seal-line), inset -1px 0 0 var(--seal-line); }
.gop thead .c-cao { box-shadow: inset 1px 0 0 var(--seal-line), inset -1px 0 0 var(--seal-line), inset 0 -1.5px 0 var(--cobalt); }
.gop thead th:nth-child(2) { width: 18%; }
.gop thead th:nth-child(3) { width: 15%; }
.gop thead th:nth-child(4) { width: 17%; }
.gop thead th:nth-child(5) { width: 14%; }
.gop thead th:nth-child(6) { width: 19%; }
.gop thead th:nth-child(7) { width: 17%; }
.gop .c-nhan .tag { white-space: nowrap; }
.gop .c-ad { font-size: 14.5px; color: var(--ink-2); }
.muc {
  display: block; font: 800 26px/1.1 var(--sans); letter-spacing: -.025em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.muc.lead { color: var(--cobalt); }
.muc.sm { font-size: 19px; }
.gop .rate.sub { font: 650 16px var(--sans); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.gop tr.r-top .c-no { color: var(--cobalt); font-weight: 700; font-size: 14px; }
/* Ngân hàng vừa điều chỉnh biểu: một vạch mực ở mép trái + một nhãn có số.
   KHÔNG dùng màu nền cả hàng — hàng đổi giá không phải hàng cảnh báo, và tô
   nền là mượn ngôn ngữ của lỗi. */
.gop tr.r-doi .stick { box-shadow: inset 3px 0 0 var(--cobalt); }
.r-doi-chip {
  display: inline-flex; align-items: center; gap: 3px; margin-top: 3px;
  font: 600 12.5px var(--mono); letter-spacing: .04em; text-transform: uppercase;
  color: var(--cobalt); background: var(--cobalt-soft);
  padding: 1px 6px 1px 4px; border-radius: 999px; cursor: help;
}
.r-doi-chip .li { width: 11px; height: 11px; }
/* Nháy MỘT lần khi hàng vào tầm mắt — Motion đặt biến này rồi gỡ ra. */
@keyframes doi-nhay { 0% { background: var(--cobalt-soft); } 100% { background: transparent; } }
.gop tr.r-doi[data-nhay] td, .gop tr.r-doi[data-nhay] .stick { animation: doi-nhay var(--t-nhay) var(--ease-vao); }
/* Thân cột đang xếp — mắt phải biết bảng đang xếp theo cột nào (uswds
   usa-table data-sort-active). Chú thích trên nền wash dùng --ink-2, không
   --muted (trượt AA trên nền này). */
.gop td[data-sort-active] { background: var(--wash-2); }
.gop td[data-sort-active] .cellnote { color: var(--ink-2); }
@media (hover: hover) and (pointer: fine) {
  .gop tbody tr:hover td, .gop tbody tr:hover .stick { background: var(--surface-2); }
}

.gop-cards { display: none; list-style: none; margin: 0; padding: 0; }
/* Trạng thái đóng ≤92px: hai dòng. Dòng 1 tên + mức, dòng 2 loại hình + nhãn
   nguồn, rồi một dòng mở chi tiết. Mức lãi đứng CÙNG dòng với tên chứ không
   xuống dòng riêng — đó là chỗ tiết kiệm được 60px mỗi thẻ. */
.gcard {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0 var(--s3); align-items: baseline;
  padding: var(--s2) var(--s3); border-bottom: 1px solid var(--rule);
  border-left: 3px solid transparent;
}
/* Nhãn nguồn ở thẻ đóng: một dòng, không xuống dòng. Nhãn dài nhất
   ("Khảo sát thị trường") là chỗ quyết định chiều cao của cả 38 thẻ. */
.gcard .nhan .tag { font-size: 12.5px; padding: 1px 6px; white-space: nowrap; }
.gcard .pos { grid-row: 1; align-self: baseline; }
.gcard .who { grid-row: 1; grid-column: 2; }
.gcard .cao { grid-row: 1; grid-column: 3; text-align: right; }
.gcard.r-top { border-left-color: var(--cobalt); }
.gcard.r-top .pos { color: var(--cobalt); font-weight: 700; }
.gcard .pos { font: 600 14px var(--mono); color: var(--muted); }
.gcard .who { min-width: 0; }
.gcard .apdung, .gcard .src { grid-column: 1 / -1; }
.gcard .nhan { grid-column: 2 / -1; }
.gcard .cao { margin-top: 0; }
.gcard .cao .muc { font-size: 22px; }
.gcard .who .bank-meta { font-size: 12.5px; }
/* Trạng thái ĐÓNG chỉ giữ: ai · bao nhiêu · nguồn nào. Mọi chú thích phụ
   ("còn N mức khác", "chưa có niêm yết đối chiếu", khu vực/số nguồn/giờ đọc)
   chỉ hiện khi thẻ mở — chúng là bằng chứng, không phải câu trả lời. */
.gcard .cao .cellnote, .gcard .nhan .cellnote { display: none; }
.gcard:has(.gc-more[open]) .cao .cellnote,
.gcard:has(.gc-more[open]) .nhan .cellnote { display: inline; }
.gcard .nhan { margin-top: 2px; }
.gcard .apdung { font-size: 14px; color: var(--ink-2); }
.gcard .nhan .cellnote { margin-left: var(--s1); }
.gcard .nhan .cellnote::before { content: "· "; }
.gcard .src { margin-top: var(--s2); font: 500 13.5px/1.7 var(--mono); color: var(--ink-2); }
.gcard .src b { font-weight: 600; color: var(--muted); }
.gcard .mono-box { display: none; }

/* Bộ lọc */
.loc { align-items: flex-end; }
.loc-ghi { flex-basis: 100%; margin: 0; min-height: 1.4em; font: 500 13.5px/1.4 var(--mono); color: var(--ink-2); }
.loc .amount input { font-size: 19px; width: 13ch; }
.loc .amount input::placeholder { font: 400 15px var(--sans); color: var(--muted); }
.amount input[aria-invalid="true"] { border-bottom-color: var(--warn); }
.loc-ghi.err { color: var(--warn); font-weight: 600; }
.stage .loc-ghi.err { color: var(--warn); }
.so-chu {
  display: block; min-height: 1.5em; margin-top: var(--s2);
  font: 500 13px/1.5 var(--mono); color: var(--ink-2); text-transform: none; letter-spacing: 0;
}

/* ── 12. Kỳ hạn khác ──────────────────────────────────────────────── */
.terms { margin: 0; padding: 0; list-style: none; }
.terms li {
  display: grid; align-items: baseline; gap: var(--s2) var(--s5);
  grid-template-columns: 84px 124px max-content max-content 1fr;
  padding: var(--s3) 0; border-bottom: 1px solid var(--rule);
  transition: background-color var(--t-mau) ease;
}
@media (hover: hover) and (pointer: fine) {
  .terms li:hover { background: var(--surface-2); }
}
.terms li:last-child { border-bottom: 0; }
.terms .t-di { justify-self: end; }
.t-ky { font: 800 21px/1 var(--sans); letter-spacing: -.03em; color: var(--ink); }
.t-ky i { font: 500 12px var(--mono); font-style: normal; color: var(--muted); margin-left: 5px; }
.t-muc { font: 800 21px/1 var(--sans); letter-spacing: -.03em; color: var(--cobalt); font-variant-numeric: tabular-nums; }
.t-ai { font-size: 16px; font-weight: 650; }
.t-di a { font: 500 14px var(--sans); white-space: nowrap; }
/* Ngân hàng không có trang riêng: chữ trơn màu phụ, không giả làm nút. */
.t-di .t-trong { font: 400 14px var(--sans); color: var(--muted); white-space: nowrap; }
@media (max-width: 760px) {
  .terms li { grid-template-columns: 78px 1fr; }
  .t-ai, .t-nhan, .t-di { grid-column: 2 / -1; }
  .t-nhan, .t-di { margin-top: 2px; }
}

/* ── 13. Khối gập ─────────────────────────────────────────────────── */
.fold { border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); box-shadow: var(--shadow-1); overflow: hidden; }
.fold > summary {
  cursor: pointer; list-style: none; display: flex; gap: var(--s3);
  align-items: baseline; padding: var(--s3) var(--s5); background: var(--head);
  border-bottom: 1px solid var(--rule);
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after {
  content: ""; width: 17px; height: 17px; flex: none; margin-left: auto;
  align-self: center; background: var(--cobalt);
  -webkit-mask: var(--ic-chevron) center / contain no-repeat;
  mask: var(--ic-chevron) center / contain no-repeat;
  transition: transform var(--t-vua) var(--ease-vao);
}
.fold[open] > summary::after { transform: rotate(180deg); }
.fold > summary:hover .fold-k { text-decoration: underline; }
/* 700/12px + mực đậm hơn (13/08 tối: "hiển thị khá mờ nhạt và khó đọc") —
   summary là NÚT MỞ của cả khối, không phải chú thích được phép chìm. */
.fold-k { font: 700 13px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--cobalt-strong); }
.fold-n { font-size: 15px; font-weight: 500; color: var(--ink-2); }
.fold > *:not(summary) { margin: var(--s4) var(--s5); }
.fold .tablewrap { border: 0; box-shadow: none; padding: 0; }
.fold .sub-block { border-top: 3px double var(--rule-strong); padding-top: var(--s4); }

/* ── 14. Biên nhận, nhãn ──────────────────────────────────────────── */
.receipt { border: 0; padding: 0; margin: 0; }
.receipt summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center;
  /* 12,5px sans, không phải 11,5px mono. Đây là nút MỞ NGUỒN — thứ chứng minh
     mọi con số trên trang, và là chỗ dự án khác biệt nhất. Ở 11,5px mono nó
     đọc như chú thích kỹ thuật ai cũng lướt qua. */
  gap: 5px; font: 500 13.5px var(--sans); color: var(--muted);
}
.receipt summary::-webkit-details-marker { display: none; }
.receipt summary:hover { color: var(--cobalt); }
.receipt[open] summary { color: var(--cobalt); }
.mark { width: 9px; height: 9px; flex: none; border: 1.5px solid var(--muted); border-radius: 3px; }
.mark.done { background: var(--emerald); border-color: var(--emerald);
  display: inline-grid; place-items: center; }
/* Dấu tick thật, không chỉ màu: High Contrast xoá nền thì trạng thái vẫn còn
   (mục forced-colors trả nó về glyph vì mask không dựng được ở chế độ đó). */
.mark.done::after {
  content: ""; width: 7px; height: 7px; background: var(--on-accent);
  -webkit-mask: var(--ic-check) center / contain no-repeat;
  mask: var(--ic-check) center / contain no-repeat;
}
.receipt-body {
  margin-top: var(--s2); padding: var(--s3); background: var(--surface-2);
  border: 1px solid var(--rule); border-radius: var(--r-sm); font-size: 14px; text-align: left;
}
.receipt-body dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px var(--s3); }
.receipt-body dt { font: 500 12px var(--mono); color: var(--muted); white-space: nowrap; }
.receipt-body dd { margin: 0; color: var(--ink-2); overflow-wrap: anywhere; }

.tag {
  display: inline-block; font: 600 12px var(--sans); letter-spacing: .01em;
  padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--rule-strong); color: var(--ink-2); background: var(--surface);
}
.tag-seal { color: var(--cobalt); background: var(--cobalt-soft); border-color: var(--seal-line); }
.tag-flag { color: var(--warn); background: var(--warn-soft); border-color: currentColor; }
.tag-ok { color: var(--emerald); background: var(--emerald-soft); border-color: #9AD8C2; }

/* ── 15. Ba sự thật (trang kỳ hạn) ────────────────────────────────── */
.facts {
  margin: var(--s6) 0 0; display: grid; gap: var(--s4);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.fact {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); box-shadow: var(--shadow-1); padding: var(--s4) var(--s5);
}
.fact dt {
  font: 600 12.5px/1.5 var(--mono); letter-spacing: .11em;
  text-transform: uppercase; color: var(--muted);
}
.fact dd { margin: var(--s2) 0 0; }
.fact-n {
  display: block; color: var(--cobalt);
  font: 800 clamp(30px, 3.4vw, 40px)/1.05 var(--sans);
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.fact-n i { font: 600 13.5px var(--mono); font-style: normal; letter-spacing: 0; color: var(--ink-2); margin-left: 6px; }
.fact-who { display: block; margin-top: var(--s2); font-size: 16px; font-weight: 650; color: var(--ink); }
.fact-who a { color: inherit; text-decoration-color: var(--seal-line); }
.fact-sub { display: block; margin-top: 3px; font: 500 12.5px/1.5 var(--mono); color: var(--muted); }
.fact-warn {
  display: block; margin-top: var(--s3); padding-left: var(--s2);
  border-left: 2px solid var(--amber); font-size: 13.5px; color: var(--amber);
}
@media (max-width: 760px) { .facts { grid-template-columns: 1fr; } }

/* ── 16. Nguồn và phương pháp (drawer) ────────────────────────────── */
.method { border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); box-shadow: var(--shadow-1); overflow: hidden; }
.method > summary {
  cursor: pointer; list-style: none; display: flex; align-items: baseline;
  gap: var(--s3); padding: var(--s3) var(--s5);
}
.method > summary::-webkit-details-marker { display: none; }
.method > summary::after {
  content: ""; width: 17px; height: 17px; flex: none; margin-left: auto;
  align-self: center; background: var(--cobalt);
  -webkit-mask: var(--ic-chevron) center / contain no-repeat;
  mask: var(--ic-chevron) center / contain no-repeat;
  transition: transform var(--t-vua) var(--ease-vao);
}
.method[open] > summary::after { transform: rotate(180deg); }
.method-k { font: 600 12.5px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--cobalt); }
.method-n { font-size: 14px; color: var(--muted); }
.method-body { padding: var(--s4) var(--s5) var(--s5); border-top: 1px solid var(--rule); }

.declare { border: 0; }
.declare-head {
  font: 600 12.5px/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); padding-bottom: var(--s3);
}
.declare dl { margin: 0; }
.declare div {
  display: grid; grid-template-columns: 128px 1fr; gap: var(--s4);
  padding: var(--s3) 0; border-top: 1px solid var(--rule);
}
.declare dt {
  font: 600 12.5px/1.6 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
}
.declare dd { margin: 0; font-size: 15px; color: var(--ink-2); }
.declare dd b { color: var(--ink); font-weight: 650; }
.declare .missing dd { color: var(--warn); }

/* ── 17. Văn bản, nhận định, quảng cáo ────────────────────────────── */
.prose { max-width: var(--measure); }
/* Canh đều hai bên cho văn xuôi dài — và CHỈ cho văn xuôi dài.
   Tiếng Việt không ngắt từ được (không có từ điển hyphenation cho vi trong
   trình duyệt), nên canh đều trên cột hẹp sẽ giãn khoảng trắng thành những
   "dòng sông" trắng chạy dọc đoạn. Điều kiện an toàn: cột đủ rộng (~70 ký tự
   mỗi dòng ở --measure) và màn hình từ 768px. Dưới ngưỡng đó giữ canh trái.
   `text-wrap: pretty` để trình duyệt tránh dòng cuối trơ một từ. */
@media (min-width: 768px) {
  .prose > p, .method-body > p, .seo-body > p, .reading > p:not(.rd-k) {
    text-align: justify; text-justify: inter-word;
    hyphens: none; text-wrap: pretty;
  }
  /* Câu ngắn thì canh đều chỉ làm nó trông vỡ — một dòng rưỡi không có đủ
     khoảng trắng để phân phối. */
  .prose > p:first-child:last-child { text-align: left; }
}
/* Ô chú thích, ghi chú nguồn, caption: luôn canh trái. Chúng là nhãn, không
   phải văn xuôi — canh đều làm chúng trông như đoạn văn bị cắt. */
.cellnote, .fold-n, .method-n, .sp-s, .kicker, .scope-note { text-align: left; }

/* ── Bài phân tích: bố cục toà soạn ───────────────────────────────────
   Cột chữ 62–70 ký tự + đường bằng chứng 280px. Đường bằng chứng KHÔNG phải
   trang trí: mỗi phần chỉ đứng được nếu nguồn của nó nằm ngay cạnh, đọc được
   mà không phải rời chỗ đang đọc. */
.article { padding-block: var(--s6) var(--s8); }
.art-main { max-width: 68ch; }
.art-sec { margin: var(--s7) 0 0; }
.art-sec h2 {
  display: flex; align-items: baseline; gap: var(--s3);
  font-size: 24px; font-weight: 750; letter-spacing: -.024em;
  margin: 0 0 var(--s4); padding-bottom: var(--s3);
  border-bottom: 1px solid var(--rule);
}
.art-sec h2 i {
  font: 600 12px var(--mono); font-style: normal; letter-spacing: .08em;
  color: var(--cobalt); background: var(--cobalt-soft);
  padding: 3px 7px; border-radius: 6px; flex: none;
}

/* Dữ kiện: danh sách, mỗi dòng một con số, đọc lướt được. */
.dukien { list-style: none; margin: 0 0 var(--s4); padding: 0; }
.dukien li {
  position: relative; padding: var(--s2) 0 var(--s2) var(--s5);
  border-bottom: 1px solid var(--rule); font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.dukien li::before {
  content: ""; position: absolute; left: 0; top: 15px;
  width: 10px; height: 2px; background: var(--cobalt);
}
.dukien li:last-child { border-bottom: 0; }

/* Diễn giải: văn xuôi, có nhãn — người đọc phải biết chỗ nào là suy luận. */
.reading { margin: var(--s4) 0; }
.rd-k {
  font: 650 14px var(--sans); letter-spacing: 0; text-transform: none;
  color: var(--muted); margin: 0 0 var(--s2);
}
.reading p + p { margin-top: var(--s3); }
.reading > p:not(.rd-k) { color: var(--ink-2); }

/* Giới hạn: khung riêng, màu caveat. Không phải cảnh báo lỗi — là chỗ bài
   tự nói ra nó chưa biết gì. */
.limits {
  margin: var(--s4) 0 0; padding: var(--s3) var(--s4);
  background: var(--amber-soft); border-radius: var(--r-sm);
  border-left: 3px solid var(--amber); font-size: 15px; color: var(--ink-2);
}
.lim-k {
  display: flex; align-items: center; gap: 6px; margin: 0 0 var(--s2);
  font: 700 14px var(--sans); color: var(--amber);
}
.lim-k .li { width: 13px; height: 13px; }
.limits p + p { margin-top: var(--s2); }

/* Bốn con số của bản — hộp tóm tắt, tối đa 4 dòng. */
.keyfind {
  margin: var(--s5) 0; padding: var(--s4) var(--s5);
  background: var(--surface); border-radius: var(--r);
  box-shadow: var(--shadow-1);
}
.kf-h {
  display: flex; align-items: center; gap: 6px; margin: 0 0 var(--s3);
  font: 700 14.5px var(--sans); color: var(--cobalt);
}
.kf-h .li { width: 14px; height: 14px; }
.keyfind ul { margin: 0; padding: 0; list-style: none; }
.keyfind li {
  padding: var(--s2) 0; border-top: 1px solid var(--rule);
  font-size: 16px; font-variant-numeric: tabular-nums; color: var(--ink);
}

/* Byline: hàng dữ kiện xuất bản. Mono cho nhãn, sans cho giá trị. */
.byline {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  padding: var(--s3) 0; border-block: 1px solid var(--rule);
  font-size: 14.5px; color: var(--ink-2);
}
.byline i {
  display: block; font: 600 12px var(--mono); font-style: normal;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}

.rail { margin: var(--s4) 0 0; }
.rail-k {
  font: 650 13.5px var(--sans); letter-spacing: 0; text-transform: none;
  color: var(--muted); margin: 0 0 var(--s2);
}
.rail-item {
  padding: var(--s2) 0 var(--s2) var(--s3); margin-bottom: var(--s2);
  border-left: 2px solid var(--rule);
}
.ri-t { margin: 0; font-size: 14px; font-weight: 650; color: var(--ink); }
.ri-n { margin: 0; font: 700 16px var(--sans); font-variant-numeric: tabular-nums; color: var(--cobalt); }
.ri-s { margin: 0; font-size: 12.5px; color: var(--muted); }
.ri-s .li { width: 11px; height: 11px; vertical-align: -1px; }

@media (min-width: 1060px) {
  /* Hai cột: chữ và bằng chứng. Rail nằm NGANG phần của nó, không dồn cuối
     bài — nguồn phải ở cạnh câu mà nó chống đỡ. */
  .art-main { max-width: none; display: grid; column-gap: var(--s7);
              grid-template-columns: minmax(0, 68ch) 280px; }
  /* `.tu-dong` phải được KHAI cột. Không khai thì lưới tự đặt nó vào cột 2
     (cột bằng chứng, rộng 280px) — hộp chú thích byline bị bóp thành một cột
     hẹp nổi lơ lửng bên phải, và nó đẩy khối "bốn con số" xuống, chừa lại một
     khoảng trống 100px giữa hai khối liền nhau. Đo 12/08 trên trang thật. */
  .byline, .keyfind, .tu-dong, .art-main > .lede, .scope-note { grid-column: 1; }
  .art-sec {
    grid-column: 1 / -1; display: grid; column-gap: var(--s7);
    grid-template-columns: minmax(0, 68ch) 280px;
  }
  .art-sec > h2 { grid-column: 1 / -1; }
  .art-sec > .dukien, .art-sec > .reading, .art-sec > .limits { grid-column: 1; }
  .art-sec > .rail { grid-column: 2; grid-row: 2 / span 3; margin-top: 0; }
}
.prose h2 { margin: var(--s6) 0 var(--s3); font-size: 21px; font-weight: 750; letter-spacing: -.024em; }
.prose h3 { margin: var(--s5) 0 var(--s2); font-size: 17px; font-weight: 650; }
.prose p, .prose li { color: var(--ink-2); }
.prose b { color: var(--ink); }
.prose ul { padding-left: var(--s5); }
.prose li { margin: var(--s2) 0; }

.notes { margin: var(--s6) 0 0; padding: 0; list-style: none; display: grid; gap: 0; border-top: 1px solid var(--rule); }
.notes::before {
  content: "Nhận định"; display: block; padding: var(--s3) 0;
  font: 600 12.5px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}
.notes li {
  padding: var(--s3) 0 var(--s3) var(--s6); border-bottom: 1px solid var(--rule);
  /* Mực chính, không phải mực phụ: bốn câu này là PHÁT HIỆN của trang,
     để --ink-2 thì thứ đáng đọc nhất lại nhạt nhất khối (13/08 tối). */
  font-size: 16px; color: var(--ink); position: relative;
}
.notes li::before {
  content: counter(list-item, decimal-leading-zero);
  position: absolute; left: 0; top: var(--s3);
  font: 600 13px var(--mono); color: var(--cobalt);
}

/* Vị trí đối tác — một thẻ thuộc hệ, KHÔNG placeholder nét đứt. */
.sponsor {
  margin-block: var(--s7); display: flex; align-items: center; gap: var(--s5);
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); box-shadow: var(--shadow-1);
  padding: var(--s4) var(--s5); flex-wrap: wrap;
}
.sp-k {
  font: 600 12px var(--mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--cobalt); border: 1px solid var(--seal-line); border-radius: 999px;
  padding: 3px 10px; background: var(--cobalt-soft);
}
.sp-body { flex: 1; min-width: 220px; }
.sp-t { margin: 0; font-weight: 650; font-size: 16px; }
.sp-s { margin: 2px 0 0; font-size: 13.5px; color: var(--muted); max-width: 60ch; }

.ad { margin-block: var(--s7); padding: var(--s3) 0; }
.ad::before {
  content: "Được tài trợ"; display: block; font: 600 12.5px var(--mono);
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
  margin-bottom: var(--s2);
}
.ad .slot {
  min-height: 90px; display: grid; place-items: center; text-align: center;
  color: var(--muted); font-size: 14px; background: var(--surface);
  border: 1px dashed var(--rule-strong); border-radius: var(--r); padding: var(--s4);
}

/* ── 18. Bộ điều khiển chung ──────────────────────────────────────── */
.controls {
  display: flex; gap: var(--s5); flex-wrap: wrap; align-items: flex-end;
  padding-block: var(--s4); border-block: 1px solid var(--rule);
}
.control { display: grid; gap: var(--s2); }
.control > span:first-of-type {
  font: 600 12.5px var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-2);
}
.chips { display: flex; flex-wrap: wrap; gap: 6px; text-transform: none; }
.chips a, .chips button {
  font: 500 15px var(--sans); padding: 7px 14px; background: var(--surface);
  border: 1px solid var(--rule-strong); border-radius: 999px; cursor: pointer;
  color: var(--ink-2); text-decoration: none; white-space: nowrap;
  transition: background-color var(--t-mau) ease, color var(--t-mau) ease, border-color var(--t-mau) ease;
}
@media (hover: hover) and (pointer: fine) {
  .chips a:hover, .chips button:hover { background: var(--cobalt-soft); color: var(--cobalt); border-color: var(--seal-line); }
}
.chips [aria-current="page"], .chips [aria-pressed="true"] {
  background: var(--cobalt); border-color: var(--cobalt); color: var(--on-accent); font-weight: 600;
}
.amount { display: flex; align-items: baseline; gap: var(--s2); }
.amount input {
  font: 800 22px var(--sans); font-variant-numeric: tabular-nums;
  border: 0; border-bottom: 2px solid var(--ink); background: transparent;
  padding: 2px 0; width: 15ch; color: var(--ink);
}
.amount input:focus {
  outline: 2px solid var(--cobalt); outline-offset: 3px;
  border-bottom-color: var(--cobalt);
}
.amount span { font-weight: 600; color: var(--ink-2); }

/* ── 19. Thang đo trang kỳ hạn ────────────────────────────────────── */
.scale-axis { position: relative; height: 30px; border-bottom: 1px solid var(--rule-strong); margin-bottom: var(--s2); overflow: hidden; }
.scale-axis span { position: absolute; bottom: 3px; transform: translateX(-50%); font: 500 12.5px var(--mono); color: var(--muted); }
.scale-axis span::after { content: ""; position: absolute; left: 50%; bottom: -4px; width: 1px; height: 4px; background: var(--rule-strong); }
.scale-axis .median { color: var(--cobalt); font-weight: 600; }
.scale-axis .median::after { background: var(--cobalt); height: 7px; bottom: -7px; }
.scale { position: relative; height: 22px; }
.scale::before { content: ""; position: absolute; left: 0; right: 0; top: 10px; height: 1px; background: var(--rule); }
.scale i { position: absolute; top: 2px; width: 3px; height: 18px; background: var(--ink); transform: translateX(-1px); border-radius: 2px; }
.scale i.lead { background: var(--cobalt); width: 4px; }
/* Khoảng tới mức dẫn đầu — dot plot của FT là chấm + KHOẢNG, không chỉ chấm
   (visual-vocabulary: Dot plot). Gạch đứt cobalt nhạt, KHÔNG đỏ: khoảng cách
   là dữ liệu, không phải cảnh báo. left/width đã render sẵn từ máy chủ. */
.scale u {
  position: absolute; top: 9.5px; height: 3px; text-decoration: none;
  background: repeating-linear-gradient(90deg, var(--seal-line) 0 4px, transparent 4px 8px);
}

/* ── 20. CTA, chân trang, bottom nav ──────────────────────────────── */
.cta h2 { margin: 0 0 var(--s2); font-size: clamp(21px, 2.4vw, 28px); font-weight: 750; letter-spacing: -.028em; }
.cta p { margin: 0 0 var(--s5); color: var(--ink-2); max-width: var(--measure); }
.btn {
  display: inline-block; background: var(--acGrad); color: var(--on-accent);
  padding: var(--s3) var(--s6); font-weight: 600; text-decoration: none;
  border-radius: 999px; transition: background-color var(--t-nhanh) ease;
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover { filter: brightness(1.12); color: var(--on-accent); }
}

/* Chân trang có SỨC NẶNG (13/08 chiều: "khá mờ nhạt"): nền đổi bậc so với
   thân trang, viền trên dày 2px màu accent nhạt, tiêu đề cột đậm hơn. Đây là
   chỗ đặt tuyên bố độc lập — thứ định vị sản phẩm, không phải phần thừa. */
.site-foot {
  border-top: 2px solid rgba(var(--acR), .28);
  background: var(--panel-2); margin-top: var(--s8);
  box-shadow: inset 0 1px 0 rgba(var(--acR), .10);
}
.site-foot .foot-col strong { font-size: 17px; letter-spacing: -.02em; color: var(--ink); }
.foot-col h3 { color: var(--cobalt-strong); }
.foot-col a { color: var(--ink-2); font-weight: 500; }
.legal .stamp { color: var(--muted); }
.foot-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: var(--s6); padding-block: var(--s6); }
.foot-grid p { margin: var(--s2) 0 0; color: var(--muted); font-size: 15px; max-width: 40ch; }
.foot-col h3 { margin: 0 0 var(--s3); font: 600 12.5px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.foot-col nav { display: grid; gap: var(--s2); }
.foot-col a { color: var(--ink-2); font-size: 15.5px; text-decoration: none; }
.foot-col a:hover { color: var(--cobalt); text-decoration: underline; }
/* Địa chỉ liên hệ: tách khỏi khối link bằng một khoảng thở, và giữ nguyên
   gạch chân — nó là thứ người ta ĐI TÌM, không phải một link điều hướng nữa
   trong danh sách. `word-break` vì địa chỉ dài không được đẩy tràn cột ở 390px. */
.foot-lienhe { margin-top: var(--s3) !important; font-size: 14.5px; }
.foot-lienhe a { text-decoration: underline; word-break: break-word; }
.legal { border-top: 1px solid var(--rule); padding-block: var(--s4) var(--s6); }
.legal p { margin: 0; font-size: 14px; color: var(--muted); max-width: 80ch; }
.legal .stamp { margin-top: var(--s2); font: 500 13px var(--mono); }

/* Bottom nav — chỉ điện thoại. 4 tab, icon stroke, tab đang chọn cobalt. */
.bottomnav {
  display: none; position: fixed; inset: auto 0 0 0; z-index: 30;
  background: var(--surface); border-top: 1px solid var(--rule);
  padding: 6px max(env(safe-area-inset-left), 8px)
           max(env(safe-area-inset-bottom), 6px) max(env(safe-area-inset-right), 8px);
  box-shadow: 0 -8px 24px -16px rgba(15, 23, 41, .25);
}
.bottomnav a {
  flex: 1; display: grid; justify-items: center; gap: 2px;
  padding: 5px 2px; color: var(--muted); text-decoration: none;
  font: 500 12px/1.2 var(--sans); border-radius: var(--r-sm);
}
.bottomnav a svg { width: 21px; height: 21px; stroke: currentColor; fill: none; }
.bottomnav a[aria-current="page"] { color: var(--cobalt); font-weight: 650; }

/* ── 21. Chuyển động ──────────────────────────────────────────────── */
/* Danh sách đóng — chuyển động chỉ khi GIẢI THÍCH một thay đổi:
   1. Mở biên nhận/khối gập (120ms). 2. FLIP khi xếp lại hàng (app.js, 260ms).
   3. Mờ chồng khi đổi kỳ hạn (view transition). 4. Nền hàng khi trỏ (90ms).
   5. Số ở thẻ kết quả đổi giá trị: nhấp nháy MỘT lần rồi tắt.
   6. VOLT: nháy con trỏ, mạch sống, ticker, vẽ đường, hiện dòng so le.
   KHÔNG particle, KHÔNG hover-lift. */

/* ── 21a. Chuyển động chạy vô hạn — công tắc `--play` ──────────────────
   Bốn hiệu ứng dưới đây chạy mãi (con trỏ nháy, mạch sống, ticker, skeleton).
   Luật `animation-duration: .001ms` của khối reduced-motion KHÔNG dừng được
   chúng — nó chỉ làm chúng chạy nhanh hơn, tức nháy loạn. Cách đúng là
   `animation-play-state: paused`, và gom vào MỘT biến để chỗ nào cũng theo. */
@keyframes ls-blink { 0%, 52% { opacity: 1; } 53%, 100% { opacity: 0; } }
@keyframes ls-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--upR), .55); }
  70%  { box-shadow: 0 0 0 8px rgba(var(--upR), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--upR), 0); }
}
@keyframes ls-ticker { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }
@keyframes ls-shimmer { 0% { background-position: -460px 0; } 100% { background-position: 460px 0; } }
@keyframes ls-dash { to { stroke-dashoffset: 0; } }
@keyframes ls-fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.ls-caret {
  display: inline-block; width: 9px; height: 17px; background: var(--cobalt);
  box-shadow: 0 0 12px rgba(var(--acR), var(--ga));
  animation: ls-blink 1.1s step-end infinite;
  animation-play-state: var(--play, running);
}
.ls-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--emerald); flex: none;
  animation: ls-pulse 1.8s ease-out infinite;
  animation-play-state: var(--play, running);
}
/* Dòng hiện lên so le — chỉ khi khối lọt vào tầm mắt, không lặp. */
.ls-vao { animation: ls-fade-up .5s both; animation-play-state: var(--play, running); }

.receipt-body { animation: mo var(--t-nhanh) var(--ease-vao); }
/* Accordion 260ms trong dải 240–320ms của quy chuẩn chuyển động. */
.fold[open] > *:not(summary), .method[open] .method-body, .ctl-fold[open] .controls { animation: mo var(--t-cham) var(--ease-mo); }
@keyframes mo { from { opacity: 0; transform: translateY(-3px); } }

@keyframes so-doi { 0% { background: rgba(110, 151, 255, .28); } 100% { background: transparent; } }
.so-vua-doi { animation: so-doi var(--t-nhay) var(--ease-vao); border-radius: 6px; }

@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) {
  animation-duration: .18s; animation-timing-function: var(--ease-mo);
}

/* ── 21c. Phản hồi khi NHẤN ────────────────────────────────────────────
   Trước lượt này, `:active` xuất hiện ĐÚNG 0 lần trong cả kho: mọi affordance
   nằm ở `:hover`, thứ không tồn tại lúc ngón tay chạm. Người dùng cảm ứng —
   kênh chính của trang này — chạm chip "1 tỷ" và không có gì báo máy đã nhận,
   suốt quãng chờ tới lúc số tính lại.

   Một luật `transition` gộp cho mọi control: khai riêng lẻ thì mỗi luật sau
   sẽ ghi đè nguyên cả shorthand của luật trước và xoá mất phần màu. */
.chips a, .chips button, .btn, .btn-ghost, .nut-nho, .mo-ngan,
.bottomnav a, .ck2-tabs [role="tab"], .gop thead th[data-xep] button, .seg button {
  transition:
    background-color var(--t-mau) ease,
    color var(--t-mau) ease,
    border-color var(--t-mau) ease,
    box-shadow var(--t-mau) ease,
    transform var(--t-vua) var(--ease-vao);
}
.chips a:active, .chips button:active, .btn:active, .btn-ghost:active,
.nut-nho:active, .mo-ngan:active, .ck2-tabs [role="tab"]:active,
.gop thead th[data-xep] button:active, .seg button:active,
.nut-theme:active .nt-track { transform: translateY(1px) scale(.97); }
/* Nút điều hướng đáy rộng gần một phần tư màn — thu sâu hơn thì đọc ra giả. */
.bottomnav a:active { transform: scale(.96); }
/* Hàng rộng KHÔNG thu nhỏ: co một dải ngang cả màn hình đọc ra lỗi dựng hình.
   Chúng báo bằng nền, thứ vốn đã có transition. */
.fold > summary:active, .method > summary:active, .receipt summary:active,
.rank10 li:active, .terms li:active { background: var(--surface-2); }

/* ── 21d. Hover chỉ dành cho con trỏ thật ──────────────────────────────
   30 luật `:hover` tô nền, không luật nào có cổng. Trên cảm ứng `:hover`
   DÍNH LẠI sau cú chạm: hàng vừa chạm giữ nền cho tới khi chạm chỗ khác, và
   đọc ra "hàng này đang được chọn". Khối `(pointer: coarse)` sẵn có chỉ chỉnh
   kích thước chạm, không đụng tới màu. */
   Từng luật được bọc TẠI CHỖ bằng `@media (hover: hover) and (pointer: fine)`
   — xem các khối ở mục tương ứng. Không gom về đây và cũng không dùng
   `revert-layer`: file này không khai `@layer` nào, nên `revert-layer` sẽ trả
   về style mặc định của trình duyệt chứ không về luật gốc. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition: none !important; }
  /* `.001ms` KHÔNG dừng được animation vô hạn — nó chỉ làm nháy loạn. Phải
     `paused`, và biến này là chỗ duy nhất khai điều đó. */
  :root { --play: paused; }
  @view-transition { navigation: none; }
  html { scroll-behavior: auto; }
  /* Bỏ phần dịch chuyển khi nhấn, GIỮ phần đổi nền: giảm chứ không về không. */
  .chips a:active, .chips button:active, .btn:active, .btn-ghost:active,
  .nut-nho:active, .mo-ngan:active, .ck2-tabs [role="tab"]:active,
  .bottomnav a:active, .seg button:active { transform: none; opacity: .72; }
}

/* ── 21b. Lớp kế thừa — trang kỳ hạn/ngân hàng/công cụ ────────────── */
/* Các template chưa viết lại theo hướng mới vẫn dùng lede-block/kicker/
   scope-note. Giữ chúng sống trong hệ token mới; gỡ khi từng trang được
   chuyển sang sân khấu. */
.lede-block { padding-block: var(--s6) var(--s5); }
.lede-block h1, main > .wrap > h1 {
  margin: 0 0 var(--s3);
  font-size: clamp(28px, 3.8vw, 44px); line-height: 1.12;
  font-weight: 800; letter-spacing: -.03em; text-wrap: balance; max-width: 22ch;
}
.kicker {
  font: 600 12px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-2); margin: 0 0 var(--s3);
}
.lede { margin: 0; max-width: var(--measure); font-size: clamp(16px, 1.5vw, 18px); color: var(--ink-2); }
.lede b { color: var(--ink); font-weight: 600; }
.scope-note {
  margin: var(--s4) 0 0; padding: var(--s3) var(--s4);
  background: var(--amber-soft); border-left: 3px solid var(--amber);
  border-radius: var(--r-sm);
  max-width: var(--measure); font-size: 15px; color: var(--ink-2);
}
.scope-note b { color: var(--amber); font-weight: 650; }
@media (min-width: 901px) {
  .lede-block:has(> .scope-note) {
    display: grid; column-gap: var(--s8); align-items: start;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  }
  .lede-block:has(> .scope-note) > .kicker { grid-area: 1 / 1 / 2 / -1; }
  .lede-block:has(> .scope-note) > h1 { grid-area: 2 / 1 / 3 / 2; max-width: 15ch; }
  .lede-block:has(> .scope-note) > .lede { grid-area: 3 / 1 / 4 / 2; }
  .lede-block:has(> .scope-note) > .scope-note { grid-area: 2 / 2 / 4 / 3; margin-top: 6px; align-self: start; }
  .lede-block:has(> .scope-note) > .facts { grid-area: 4 / 1 / 5 / -1; }

  /* Trang nhận định: tiêu đề đã nằm trong sân khấu dữ liệu phía trên, khối
     này chỉ còn lede và MỘT ô phạm vi. Quy tắc riêng vì lưới chung ở trên gán
     hàng cứng theo bố cục có kicker + h1. */
  .nd-lede { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); }
  .nd-lede > .lede { grid-area: 1 / 1 / 2 / 2; }
  .nd-lede > .scope-note { grid-area: 1 / 2 / 2 / 3; margin: 0; }
}

/* ── 22. Màn hình nhỏ ─────────────────────────────────────────────── */
.ranklist { display: none; }
/* Trừ khi nó là nội dung DUY NHẤT của mục — xem chú thích ở so-sanh.html.
   Desktop có chỗ rộng hơn nên hàng dãn ra thành ba cột thật thay vì xếp dọc. */
.ranklist-luon { display: block; }
@media (min-width: 901px) {
  /* Ô nào vào chỗ nấy, khai bằng VÙNG chứ không để lưới tự rải. Hàng có bảy
     phần tử; một lưới bốn cột không khai vùng sẽ đẩy ba phần tử thừa xuống các
     hàng ngầm ở những cột khác nhau tuỳ hàng đó có `cond` hay không — nên mười
     hàng lệch mười kiểu. */
  .ranklist-luon .rankrow {
    grid-template-columns: 34px minmax(0, 1fr) 92px 186px 196px;
    grid-template-areas:
      "pos who  rate lai    behind"
      "pos cond cond cond   cond"
      "pos ev   ev   ev     ev";
    align-items: center; gap: var(--s2) var(--s4);
  }
  .ranklist-luon .rankrow .pos { grid-area: pos; align-self: start; padding-top: 10px; }
  .ranklist-luon .rankrow .who { grid-area: who; }
  .ranklist-luon .rankrow .rate { grid-area: rate; text-align: right; }
  .ranklist-luon .rankrow .lai { grid-area: lai; text-align: right; }
  .ranklist-luon .rankrow .behind { grid-area: behind; text-align: right; }
  .ranklist-luon .rankrow .cond { grid-area: cond; }
  .ranklist-luon .rankrow .ev { grid-area: ev; }
}
.rankrow {
  display: grid; grid-template-columns: auto 1fr auto; gap: var(--s2) var(--s3);
  padding: var(--s4) 0; border-bottom: 1px solid var(--rule); align-items: baseline;
}
.rankrow .pos { font: 600 14px var(--mono); color: var(--ink-2); }
.rankrow .rate { font-size: 21px; }
.rankrow .who { min-width: 0; }
/* Điều kiện là ĐIỀU KIỆN, không phải cảnh báo. `--warn` (đỏ) khiến mọi hàng có
   ràng buộc đọc như một lỗi hệ thống — trên nền tối thì càng gắt. Luật màu của
   dự án đã tách sẵn hai vai: amber cho caveat và điều kiện, đỏ cho cảnh báo. */
.rankrow .cond { grid-column: 2 / -1; font-size: 14px; color: var(--amber); }
.rankrow .ev { grid-column: 2 / -1; }
/* 13,5px sans cho CHỮ, mono chỉ cho SỐ. Cả cụm để mono 12,5px thì "kém 0,1
   điểm · 1 triệu đồng mỗi tỷ" đọc như dòng log — mono giãn chữ cái nên ở cỡ
   nhỏ nó vừa dài hơn vừa khó đọc hơn sans cùng cỡ. */
.rankrow .behind, .rankrow .lai {
  grid-column: 2 / -1; font: 500 14.5px var(--sans); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.rankrow .lai b { font-weight: 700; color: var(--ink); }
.rankrow .bank-meta, .rankrow .receipt summary { color: var(--ink-2); }

@media (min-width: 901px) {
  .gop .scroller { overflow-x: visible; }
}
@media (max-width: 900px) {
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .declare div { grid-template-columns: 1fr; gap: var(--s1); }
  .matrix { display: none; }
  .ranklist { display: block; }
  .gop { display: none; }
  .gop-cards { display: block; }
  .stage-grid { grid-template-columns: 1fr; }
  /* Phải nhắc lại với ĐỦ độ cụ thể: `.stage-slim .stage-grid` ở phần trên là
     hai lớp, luật một lớp ở đây không thắng được dù nằm sau. Hậu quả đo ở
     390px: hero trang kỳ hạn vẫn hai cột 186px + 124px, nhãn "Chính thức cao
     nhất · 6 tháng" vỡ ba dòng, "35.500.000 đ tiền lãi / 1 tỷ" vỡ ba dòng bỏ
     lại chữ "tỷ" mồ côi. Hai khối cùng đòi được đọc trước thì không khối nào
     được đọc. */
  .stage-slim .stage-grid { grid-template-columns: 1fr; gap: var(--s4); }
  /* Khối kết quả thành DẢI NGANG: logo, mức, tiền lãi trên một hàng đọc được
     thay vì một cột hẹp bẻ chữ. */
  .stage-slim .stage-ans { display: flex; flex-wrap: wrap; align-items: baseline;
                           gap: var(--s2) var(--s4); }
  .stage-slim .stage-ans > * { min-width: 0; }
  .rank10 li { grid-template-columns: 24px auto 1fr 84px; }
  .r10-lai { display: none; }
}
/* Kích thước chạm — USWDS đặt 48px để vượt mốc WCAG 44px
   (uswds-core/src/styles/variables/size-touch-target.scss). Áp theo THIẾT BỊ
   (pointer: coarse) chứ không theo bề rộng: tablet ngang 1024px vẫn là ngón
   tay. Không áp cho .fnote (dấu "đk" trong dòng chữ — phóng nó là vỡ dòng);
   thay vào đó nới vùng chạm bằng ::before phủ quanh nút. */
@media (pointer: coarse) {
  .chips a, .chips button { min-height: 44px; padding-block: 10px; }
  .fold > summary, .method > summary { min-height: 48px; align-items: center; }
  .receipt summary { min-height: 44px; align-items: center; display: inline-flex; }
  .bottomnav a { min-height: 48px; }
}

@media (max-width: 640px) {
  /* 76px cho bottom nav + 54px cho dải kênh nổi nằm ngay trên nó. Nới ở đây
     là cách DUY NHẤT bảo đảm phần CUỐI nội dung không nằm dưới dải — phần
     giữa trang thì mọi phần tử cố định đều lướt qua, đó là bản chất của
     `position: fixed`, không phải lỗi cấu hình. */
  body { font-size: 16px; padding-bottom: 130px; }
  .bottomnav { display: flex; }
  .foot-grid { grid-template-columns: 1fr; }
  .head-top { min-height: 52px; }
  /* KHÔNG nav cuộn ngang — điều hướng cấp một nằm ở bottom nav. */
  .site-head nav { display: none; }
  .head-time { display: none; }
  .stage { margin-inline: calc(var(--gutter) * -1 + 8px); border-radius: var(--r); padding: var(--s5) var(--s4); }
  .controls { gap: var(--s4); }
  .control { width: 100%; }
  .chips { width: 100%; flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding-bottom: 2px; }
  .chips::-webkit-scrollbar { display: none; }
  .chips a, .chips button { flex: none; scroll-snap-align: start; }
  .ck-num { font-size: 44px; }
  .ctl-fold > summary { display: block; }
  .stage .ck { padding: var(--s4); }
  /* Fade mép phải cho dãy chip cuộn — chỉ báo còn nội dung phía sau. */
  .chips-cuon {
    -webkit-mask-image: linear-gradient(90deg, #000 86%, transparent);
            mask-image: linear-gradient(90deg, #000 86%, transparent);
  }
  .fold > *:not(summary) { margin-inline: var(--s3); }
  .gcard { padding-inline: 0; padding-left: var(--s3); }
  .rank10 li { padding-inline: var(--s2); }
  .btn { display: block; text-align: center; }
}
/* Windows High Contrast xoá màu nền: chip đang chọn, thanh xếp hạng và vạch
   thang đo biến mất nếu chỉ truyền trạng thái bằng nền (govuk warning-text
   _mixin.scss; uswds usa-button). */
@media (forced-colors: active) {
  .r10-bar i, .ck-bar .b i, .scale i, .dev i, .barcode i {
    forced-color-adjust: none; background: CanvasText;
  }
  /* Chữ tô gradient qua `background-clip` BIẾN MẤT hoàn toàn ở chế độ này —
     nền bị ép về Canvas nên phần clip không còn gì để lộ ra, và
     `-webkit-text-fill-color: transparent` giữ nguyên. Trả số về màu hệ. */
  .ck-num {
    background: none; -webkit-text-fill-color: CanvasText; color: CanvasText;
    filter: none;
  }
  .chips [aria-pressed="true"], .chips [aria-current="page"] {
    outline: 2px solid; outline-offset: -3px;
  }
  .delta-chip { border: 1px solid ButtonText; }
  /* mask-image không dựng ở High Contrast (nền bị ép về Canvas) → icon biến
     mất. Trả về glyph Unicode: xấu hơn nhưng còn nhìn thấy. */
  .ctl-fold > summary::after, .fold > summary::after, .method > summary::after,
  .gop thead th[data-xep] .sico::after, .mark.done::after {
    -webkit-mask: none; mask: none; background: none;
    width: auto; height: auto; color: CanvasText;
  }
  .ctl-fold > summary::after, .fold > summary::after,
  .method > summary::after { content: "▾"; }
  .gop thead th[data-xep] .sico::after { content: "↕"; }
  .gop thead th[aria-sort="descending"] .sico::after { content: "↓"; }
  .gop thead th[aria-sort="ascending"] .sico::after { content: "↑"; }
  .mark.done::after { content: "✓"; font-size: 8px; line-height: 1; }
}

@media print {
  .ad, .site-head nav, .controls, .receipt, .bottomnav { display: none; }
  body { background: #fff; font-size: 11pt; }
  .stage { background: #fff; color: #000; box-shadow: none; border: 1px solid #999; }
}

/* ── Theme Tabulator theo token — không dùng giao diện mặc định ───── */
#matrix-grid .tabulator {
  font-family: var(--sans); font-size: 15px; background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--r); overflow: hidden;
}
#matrix-grid .tabulator .tabulator-header {
  background: var(--surface); border-bottom: 1.5px solid var(--ink);
  font: 600 12.5px var(--mono); letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
}
#matrix-grid .tabulator .tabulator-col { background: var(--surface); border-right: 0; }
#matrix-grid .tabulator .tabulator-col .tabulator-col-content { padding: 8px 10px; }
#matrix-grid .tabulator .tabulator-header-filter input {
  font: 400 14px var(--sans); border: 1px solid var(--rule-strong);
  border-radius: 7px; padding: 3px 8px; width: 100%;
}
#matrix-grid .tabulator-row {
  border-bottom: 1px solid var(--rule); background: var(--surface);
  transition: background-color var(--t-nhanh) ease;
}
@media (hover: hover) and (pointer: fine) {
  #matrix-grid .tabulator-row:hover { background: var(--surface-2); }
}
#matrix-grid .tabulator-row .tabulator-cell {
  padding: 10px; border-right: 0; font-variant-numeric: tabular-nums;
}
#matrix-grid .tabulator-row .tabulator-cell.tabulator-frozen {
  border-right: 1px solid var(--rule-strong); background: inherit;
}
#matrix-grid .tabulator-col.tabulator-frozen { border-right: 1px solid var(--rule-strong); }
#matrix-grid .t-kind { display: block; font-size: 12.5px; color: var(--muted); }
#matrix-grid a { color: var(--ink); font-weight: 650; text-decoration: none; }
#matrix-grid a:hover { color: var(--cobalt); text-decoration: underline; }
#matrix-grid .tabulator-col.tabulator-sortable[aria-sort="ascending"] .tabulator-col-content,
#matrix-grid .tabulator-col.tabulator-sortable[aria-sort="descending"] .tabulator-col-content { color: var(--cobalt); }

/* ── Thẻ công cụ và thẻ bài phân tích trên trang chủ ─────────────────
   Hai khối cuối của trang chủ là LỐI ĐI, không phải dữ liệu. Chúng phải trông
   khác các khối bảng biểu phía trên, nếu không người đọc cuộn qua mà không
   nhận ra trang còn gì nữa. */
.toolcard, .artcard { padding: var(--s5) var(--s6); }
.tc-t, .ac-k {
  display: flex; align-items: center; gap: 7px; margin: 0 0 var(--s2);
  font: 650 12px var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--cobalt);
}
.tc-t { font-size: 17px; letter-spacing: -.01em; text-transform: none;
        font-family: var(--sans); font-weight: 700; color: var(--ink); }
.tc-t .li, .ac-k .li { width: 16px; height: 16px; color: var(--cobalt); }
.tc-s { margin: 0 0 var(--s4); color: var(--ink-2); font-size: 15.5px; max-width: 62ch; }

.artcard { display: block; text-decoration: none; color: inherit;
           border-left: 3px solid var(--cobalt); }
@media (hover: hover) and (pointer: fine) {
  .artcard:hover { background: var(--surface-2); }
}
.ac-t {
  margin: 0 0 var(--s2); font: 750 21px/1.3 var(--sans);
  letter-spacing: -.024em; color: var(--ink); max-width: 30ch;
}
.ac-s { margin: 0 0 var(--s3); color: var(--ink-2); font-size: 15.5px; max-width: 62ch; }
.ac-key { margin: 0 0 var(--s3); padding: 0; list-style: none; }
.ac-key li {
  padding: var(--s2) 0; border-top: 1px solid var(--rule);
  font-size: 14.5px; color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.ac-go { font: 600 14.5px var(--sans); color: var(--cobalt); }

/* Logo ngân hàng khi ĐÃ có file (mặc định là monogram — xem logo/README.md).
   Khung cố định để 38 logo tỉ lệ khác nhau không làm cột trái nhấp nhô, và
   nền trắng để logo nền trong suốt không chìm vào nền xám. */
.bank-logo {
  /* 40px chứ không phải 28px (chốt 12/08, nới thêm lần hai theo phản hồi chủ
     dự án cùng ngày). Ở 28px, biểu tượng đứng cạnh chữ 15px đọc thành một chấm
     màu — không nhận ra được ngân hàng. Đệm hạ từ 3px xuống 2px: viền và đệm
     ăn mất 8px mỗi chiều, nên một ô 36px chỉ còn 28px là hình thật; nới ô lên
     40px và bóp đệm lại cho biểu tượng thật sự to hơn, không phải cái khung to
     hơn. Mọi tệp logo từ 12/08 là BIỂU TƯỢNG đã cắt riêng, không còn là lockup
     có sẵn chữ, nên phóng to mới có nghĩa. */
  width: 40px; height: 40px; flex: none;
  /* VOLT §9: ô vuông bo NHẸ, nền chip, ảnh CẮT SÁT — không đĩa trắng, không
     bo tròn. Nền trắng của hướng cũ tồn tại để logo nền trong suốt không chìm
     vào nền xám; trên nền tối nó thành 38 ô trắng chói dọc cột trái, kéo mắt
     khỏi con số. `cover` + đệm 0 cho biểu tượng thật sự chạm mép ô. */
  /* Ô vuông bo nhẹ 8px, nền chip — bỏ đĩa trắng của hướng cũ, thứ trên nền
     tối thành 38 ô chói dọc cột trái và kéo mắt khỏi con số.

     `contain` chứ KHÔNG `cover` như prototype: logo dự án đã được xén sát
     biểu tượng và chuẩn hoá 512px (bàn giao 12/08), nên `cover` sẽ cắt tiếp
     một lần nữa — mất chóp chữ V của Vikki, mất vành ngoài của Sacombank.
     `contain` + đệm 3px giữ trọn hình, và đó mới là "sắc nét".

     `image-rendering` để mặc định: logo là PNG 512px thu về 40px, trình duyệt
     lấy mẫu mượt mới nét; ép `pixelated` ở tỉ lệ này là răng cưa. */
  object-fit: contain; background: var(--chip-bg);
  border: 1px solid rgba(var(--lnR), .25); border-radius: 8px;
  padding: 3px; margin-right: var(--s2); overflow: hidden;
}
/* Ô 28px trong dải biến động và chip hero — bo 6px theo spec. */
.delta-who .bank-logo, .ck-who .bank-logo { width: 28px; height: 28px; border-radius: 6px; }
/* Tên ngân hàng MANG màu thương hiệu — chốt 12/08, giữ nguyên qua đợt đổi nền.
   Template gắn hai biến cho cùng một sắc: `--mau-bank` đã tối đi cho nền sáng,
   `--mau-bank-toi` đã sáng lên cho nền VOLT. Cả hai kéo tới 5,5:1 ở build.py.

   Bản trước tôi bỏ hẳn màu vì giữ nguyên màu nền-sáng trên nền tối làm axe đỏ
   92 nút. Bỏ màu chữa được axe nhưng mất một phần bản sắc đã chốt — hai biến
   thì giữ được cả hai. */
.bank-name { color: var(--mau-bank-toi, var(--ink)); }
:root[data-theme="light"] .bank-name { color: var(--mau-bank, var(--ink)); }
.bank-name a { color: inherit; }
.stage .bank-logo, .ck .bank-logo { border-color: var(--stage-line); }
/* Câu tuyên bố độc lập: đậm hơn phần miễn trừ vì nó là định vị, không phải
   chú thích pháp lý. */
.legal .doc-lap { color: var(--ink-2); font-weight: 500; margin-bottom: var(--s3); }
.legal .doc-lap b { color: var(--ink); }
/* Hai mốc thời gian trên header: mốc số đổi đậm hơn mốc đọc lại. */
/* Hai mốc thời gian trên header. Quy tắc này nằm SAU media query ẩn header
   time trên mobile, nên tuyệt đối không được khai `display` — khai là nó bật
   lại phần đã cố ý ẩn và đẩy header tràn ngang ở 390px. */
@media (min-width: 861px) {
  .head-time { display: inline-flex; align-items: baseline; gap: var(--s3); }
}
.head-time .ht-check { color: var(--muted); }
/* Nhãn "bản dựng tự động": in khi chưa gán biên tập viên. Không phải cảnh báo
   — là một khai báo, nên dùng nền trung tính chứ không dùng amber. */
.tu-dong {
  display: flex; align-items: center; gap: 7px; margin: var(--s3) 0 0;
  padding: var(--s2) var(--s3); background: var(--surface-2);
  border: 1px solid var(--rule); border-radius: var(--r-sm);
  font-size: 14px; color: var(--ink-2);
}
.tu-dong .li { width: 14px; height: 14px; flex: none; color: var(--muted); }

/* ── Thẻ ngân hàng trên điện thoại: trạng thái đóng ≤92px ────────────
   Ba thứ ở trạng thái đóng: ai · bao nhiêu · nguồn nào. Điều kiện, mức web,
   mức báo và giờ đọc nằm sau một disclosure. Trước đây thẻ mở sẵn cao trung
   bình 198px và 38 ngân hàng là 7.500px chỉ riêng danh sách. */
.gc-more { grid-column: 1 / -1; margin-top: 0; }
.gc-more > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center;
  gap: 5px; font: 600 12.5px var(--sans); color: var(--cobalt);
  padding: 4px 0; min-height: 28px;
}
.gc-more > summary::-webkit-details-marker { display: none; }
.gc-more > summary::after {
  content: ""; width: 13px; height: 13px; background: currentColor;
  -webkit-mask: var(--ic-chevron) center / contain no-repeat;
  mask: var(--ic-chevron) center / contain no-repeat;
  transition: transform var(--t-vua) var(--ease-vao);
}
.gc-more[open] > summary::after { transform: rotate(180deg); }
.gc-body { display: grid; gap: var(--s2); padding-bottom: var(--s2); }

/* ── Ngăn kéo bằng chứng từng hàng ───────────────────────────────────
   Thay đường đi qua tooltip (review Codex §6.2). Một nút mỗi hàng, một ngăn
   kéo mỗi hàng, mở được bằng chuột · chạm · bàn phím. Render MỞ ở máy chủ và
   để JS đóng lại: không có JS thì bằng chứng vẫn tới được. */
.c-mo { width: 40px; padding-left: 0 !important; }
.mo-ngan {
  display: inline-grid; place-items: center; width: 30px; height: 30px;
  background: none; border: 1px solid var(--rule); border-radius: 8px;
  color: var(--muted); cursor: pointer;
  transition: background-color var(--t-mau) ease, color var(--t-mau) ease, border-color var(--t-mau) ease;
}
@media (hover: hover) and (pointer: fine) {
  .mo-ngan:hover { color: var(--cobalt); border-color: var(--seal-line); background: var(--cobalt-soft); }
}
.mo-ngan .li { width: 15px; height: 15px; transition: transform var(--t-vua) var(--ease-vao); }
.mo-ngan[aria-expanded="true"] .li { transform: rotate(180deg); }

.hang-mo > td { padding: 0 !important; background: var(--surface-2); border-bottom: 1px solid var(--rule); }
.hang-mo[hidden] { display: none; }
.ngan {
  display: grid; gap: var(--s4) var(--s6); padding: var(--s4) var(--s5);
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  border-left: 3px solid var(--cobalt);
}
.ngan-k {
  margin: 0 0 var(--s2); font: 650 13px var(--sans); color: var(--muted);
}
.ngan-dl { margin: 0; display: grid; gap: 2px; }
.ngan-dl > div { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: var(--s3); }
.ngan-dl dt {
  font: 600 12px var(--mono); letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); padding-top: 2px;
}
.ngan-dl dd { margin: 0; font-size: 14.5px; color: var(--ink-2); }
.ngan-dl .li { width: 12px; height: 12px; vertical-align: -1px; }
.ngan-bac ul { margin: 0; padding: 0; list-style: none; }
.ngan-bac li { font-size: 14px; color: var(--ink-2); padding: 2px 0; }
.ngan-bac b { color: var(--ink); font-variant-numeric: tabular-nums; }
.ngan-dk { grid-column: 1 / -1; font-size: 14.5px; color: var(--ink-2); }
.ngan-dk p { margin: 0 0 var(--s2); }
.ngan-canh { color: var(--warn); }
.ngan-di { grid-column: 1 / -1; margin: 0; font-size: 14.5px; }

@media (max-width: 900px) {
  .ngan { grid-template-columns: 1fr; }
  .ngan-dl > div { grid-template-columns: 1fr; gap: 0; }
}
.ngan-ht { grid-column: 1 / -1; margin: 0; font-size: 14.5px; color: var(--ink-2); }
.ngan-ht b { font-variant-numeric: tabular-nums; color: var(--ink); }
.ngan-ht .li { width: 14px; height: 14px; vertical-align: -2px; color: var(--muted); }

/* ── Khoảng lãi phải nằm MỘT DÒNG ────────────────────────────────────
   Đo ở 1280px: 27 trong 68 ô khoảng lãi vỡ hai dòng ("5,50–9,50",
   "8,46–9,50"). Một khoảng bị bẻ đôi đọc thành hai con số rời, và cột số
   mất thẳng hàng nên mắt không quét dọc được nữa — đúng thứ một bảng so
   sánh tồn tại để làm.
   `nowrap` một mình chưa đủ vì cột vẫn co được; cần cả bề rộng tối thiểu
   đủ chứa "00,00–00,00". Dùng ch để bám theo cỡ chữ thật. */
.rate, .muc, td .rate, .gop .rate {
  white-space: nowrap;
}
.gop td .rate, .gop th .rate, table .rate, table .muc {
  min-width: 11ch;
}
/* Số lãi suất luôn dùng chữ số đều bề ngang để cột thẳng hàng. */
.rate, .muc, .ck-num { font-variant-numeric: tabular-nums; }

/* ── Thẻ mức được chào trong hero (ngôn ngữ Tremor) ──────────────────
   Thẻ SÁNG trên nền navy. Bản trước là card tối trên nền tối cùng cường độ
   nên hero đọc thành một khối phẳng — "có màu nhưng không có nhịp".
   Nhãn nhỏ viết hoa → số lớn → huy hiệu chênh lệch, đúng mẫu KPI của Tremor. */
.mq {
  background: var(--stage-2); color: var(--ink); border-radius: var(--r);
  padding: var(--s4) var(--s5); border: 1px solid var(--stage-line);
  box-shadow: var(--shadow-1);
}
/* Thẻ này SÁNG nhưng nằm trong `.stage`, mà `.stage a` đặt màu cobalt-bright —
   màu dành cho chữ trên nền navy. Trên nền trắng nó chỉ đạt ~2,4:1: axe bắt
   `color-contrast` mức serious ở tên ngân hàng của 11 trang. Trả link trong
   thẻ về cobalt đậm (6,6:1 trên nền sáng). */
.stage .mq a { color: var(--cobalt); }
@media (hover: hover) and (pointer: fine) {
  .stage .mq a:hover { color: var(--cobalt-strong); }
}
.mq-k { margin: 0; font: 600 12px/1.3 var(--mono); letter-spacing: .1em;
        text-transform: uppercase; color: var(--muted); }
.mq-who { margin: var(--s2) 0 0; display: flex; align-items: center; gap: var(--s2);
          font-size: 17px; font-weight: 650; }
.mq-num { margin: var(--s1) 0 0; display: flex; align-items: baseline; flex-wrap: wrap;
          gap: var(--s2); font-size: clamp(38px, 5vw, 52px); font-weight: 800;
          letter-spacing: -.03em; color: var(--amber);
          font-variant-numeric: tabular-nums; }
.mq-num i { font: 600 16px/1 inherit; font-style: normal; color: var(--muted); }
/* Mức được chào là một DẢI, không phải một con số — hạ một cấp cỡ chữ để cả
   cụm "7,90–9,43 %/năm" còn nằm trên một dòng. */
.mq-num.dai { font-size: clamp(28px, 3.4vw, 38px); }
/* Huy hiệu chênh lệch — pill nhỏ, không phải một dòng chữ nữa. */
.delta { font: 700 13px/1 var(--mono); padding: 4px 8px; border-radius: 999px;
         letter-spacing: .02em; white-space: nowrap; }
.delta.up { background: var(--emerald-soft); color: var(--emerald); }
/* Điều kiện: lưới nhãn–giá trị, đọc quét được, không phải câu văn. */
.mq-dk { margin: var(--s3) 0 0; display: grid; grid-template-columns: auto 1fr;
         gap: 3px var(--s3); font-size: 14px; }
.mq-dk dt { color: var(--muted); }
.mq-dk dd { margin: 0; font-weight: 600; }
.mq-ny { margin: var(--s3) 0 0; padding-top: var(--s3); border-top: 1px solid var(--rule);
         font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.mq-ny b { color: var(--cobalt); font-size: 17px; font-weight: 800; }
.mq-ny i { font-style: normal; font-size: 12px; }
.mq-cav { margin: var(--s2) 0 0; font-size: 13px; line-height: 1.45;
          color: var(--amber); display: flex; gap: 6px; align-items: flex-start; }
.mq-cav svg { flex: none; width: 14px; height: 14px; margin-top: 2px; }

/* ── Thẻ trả lời hai tab ────────────────────────────────────────────
   Hai LỚP NGUỒN, hai tab — không trộn vào một thẻ. Tab đứng đầu thẻ như một
   segmented control: nhãn ngắn, gạch chân cobalt cho tab đang mở. Trạng thái
   phải đọc được KHÔNG CẦN màu (gạch chân + đậm chữ), vì "đang chọn" mà chỉ
   khác mỗi sắc độ là thứ người mù màu không thấy. */
/* Tab hai lớp ở TRANG CÔNG CỤ: cùng hình thức với thẻ trả lời hai lớp, nhưng
   đứng một mình trên đầu vùng điều khiển nên cần đường kẻ dưới và câu nói rõ
   lớp đang chọn — người dùng vừa đổi nghĩa của cả bảng bên dưới. */
.lop2 { margin-bottom: var(--s5); }
.lop2-tabs { border-bottom: 1px solid var(--rule); }
.lop2-noi { margin: var(--s3) 0 0; color: var(--muted); font-size: 15px; max-width: 62ch; }

.ck2-tabs {
  display: flex; gap: var(--s4); margin: 0 0 var(--s4);
  border-bottom: 1px solid var(--rule);
}
.ck2-tabs [role="tab"] {
  appearance: none; background: none; border: 0; cursor: pointer;
  padding: 0 0 var(--s3); margin-bottom: -1px;
  font: 600 14px/1.2 var(--sans); color: var(--muted);
  border-bottom: 2px solid transparent;
}
.ck2-tabs [role="tab"]:hover { color: var(--ink-2); }
.ck2-tabs [role="tab"][aria-selected="true"] {
  color: var(--ink); font-weight: 700; border-bottom-color: var(--cobalt);
}
.ck2 [role="tabpanel"]:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 4px; }
/* Đổi tab là đổi NỘI DUNG trong cùng một khung thẻ — không phải mở một thứ
   mới. Bản đầu bật/tắt `hidden` nên hai lớp số tráo nhau trong đúng một khung
   hình: mắt không kịp thấy cái gì vừa thay cái gì, và ở một thẻ mà cả hai tab
   đều in "%/năm" cỡ lớn thì rất dễ tưởng con số vừa tự đổi.
   Mờ vào 120ms + nhích 4px: đủ để nói "đây là một lớp khác", không đủ để phải
   chờ. Gạch chân của tab tự trượt theo vì nó là border-color có transition.

   `[data-vua]` chứ không phải `:not([hidden])`: cờ đó do JS gắn khi NGƯỜI DÙNG
   bấm tab. Bám vào `:not([hidden])` thì panel mặc định tự chạy một lượt ngay
   lúc tải trang — đúng thứ ranh giới của dự án cấm: chuyển động là phản hồi
   cho một hành động, không phải màn chào. */
.ck2 [role="tabpanel"][data-vua] {
  animation: ck2-vao var(--t-nhanh) var(--ease-vao);
}
@keyframes ck2-vao { from { opacity: 0; transform: translateY(4px); } }
/* Số của lớp niêm yết mang màu cobalt — cùng quy ước với `.mq-ny b`: cobalt là
   "đã đối chiếu được với trang ngân hàng". Lớp được chào giữ màu mực. */
.mq-num.ny { color: var(--cobalt); }
.mq-kenh { font: 500 13px var(--sans); color: var(--muted); }
/* Tiền lãi: to hơn chữ thường một cấp, tabular để đổi số không giật cột.
   KHÔNG dùng emerald — token dành riêng cho "đã đối chiếu" và biến động tăng;
   tiền lãi không phải cả hai. */
.mq-lai { margin: var(--s3) 0 0; font-size: 14px; color: var(--muted); }
.mq-lai b { font-size: 19px; font-weight: 800; color: var(--ink);
            font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.mq-delta { margin: 2px 0 0; font-size: 13.5px; color: var(--muted);
            font-variant-numeric: tabular-nums; }
.mq-delta b { color: var(--ink-2); font-weight: 700; }
/* Điều kiện của phép tính, đứng NGAY DƯỚI con số nó nói về — không phải chú
   thích cuối thẻ. Amber vì đây đúng là caveat (ART-DIRECTION-2 mục 2). */
.ck-if { margin: 2px 0 0; font-size: 13px; line-height: 1.4; color: var(--amber); }

@media (max-width: 640px) {
  .ck2-tabs { gap: var(--s3); }
  .ck2-tabs [role="tab"] { font-size: 13.5px; }
}

/* Logo cạnh H1 trên trang của một ngân hàng — canh theo đường chân chữ. */
.h1-logo { display: inline-flex; vertical-align: -.12em; margin-right: .4em; }
.h1-logo img, .h1-logo .mono-box { width: .9em; height: .9em; border-radius: .18em; }

/* ── Sửa theo ảnh chủ dự án 11/08 và finding của improve-ui ──────────
   1. Logo canh giữa THEO DÒNG CHỮ, không nhảy lên cao hơn tên. */
.bank-name { display: inline-flex; align-items: center; gap: .45em; }
.bank-name img.bank-logo, .bank-name .mono-box { flex: none; vertical-align: middle; }

/* 2. FINDING 1 — `ART-DIRECTION-2.md:31` ràng buộc `--amber` CHỈ dùng cho
      caveat, điều kiện, cảnh báo. Con số 9,50% là SỐ CHÍNH của trang, không
      phải caveat; để nó amber làm hỏng chính hệ thống tín hiệu — khi amber vừa
      là "số chính" vừa là "cảnh báo" thì người đọc mất căn cứ phân biệt.
      Trả số chính về mực, giữ amber cho đúng dòng caveat bên dưới. */
.mq-num { color: var(--ink); }

/* 3. FINDING 2 — `ART-DIRECTION-2.md:30` ràng buộc `--emerald` CHỈ cho
      "đã đối chiếu" và biến động tích cực. "+2,4 điểm" là KHOẢNG CHÊNH giữa
      hai lớp nguồn, không phải biến động, và #0A6B3D là mã tự chế không nằm
      trong bảng token. Dùng nền cobalt nhạt — đúng accent thương hiệu. */
.delta.up { background: var(--cobalt-soft); color: var(--cobalt-strong); }

/* Ô lãi suất trong bảng tính lãi: số và dòng điều kiện xếp DỌC, cùng canh
   phải. Bản trước để hai thứ trôi tự do trong một ô nên dòng "đk: …" lệch ra
   giữa hai cột — thấy rõ trong ảnh chủ dự án gửi 11/08. */
td.calc-rate { text-align: right; }
td.calc-rate .num { font-size: 15px; color: var(--muted); display: block; }
td.calc-rate .cellnote { display: block; margin-top: 2px; text-align: right;
                         max-width: 22ch; margin-left: auto; }

/* ── Trang lịch sử: lưới biểu đồ theo kỳ hạn ─────────────────────────
   Bốn biểu đồ nhỏ đọc theo cặp thì so được với nhau; xếp một cột dọc thì
   người đọc phải nhớ hình trước để so với hình sau. */
.lich-su-luoi {
  display: grid; gap: var(--s4);
  /* HAI cột cố định, không `auto-fit`. Có bốn kỳ hạn: `auto-fit` ở khung 1280
     xếp thành ba cột và bỏ hình thứ tư đứng một mình chiếm 1/3 hàng dưới —
     một ô mồ côi rộng bằng hai ô trống. Hai cột cho 2×2 kín, và mỗi hình rộng
     hơn nên đường 4 ngày đọc được rõ hơn. */
  grid-template-columns: 1fr 1fr;
}
@media (max-width: 700px) { .lich-su-luoi { grid-template-columns: 1fr; } }

/* ── Ô tìm ngân hàng và thanh mức tối thiểu ──────────────────────────
   Cùng khuôn `.control` với ô số tiền, nên không sinh ra một ngôn ngữ thứ hai
   cho cùng một cụm điều khiển. */
.amount-range { display: flex; align-items: center; gap: var(--s3); }
.amount-range input[type="range"] { flex: 1; min-width: 120px; accent-color: var(--cobalt); }
.amount-range output { font: 600 14px var(--mono); color: var(--ink-2); white-space: nowrap; }
.stage .amount-range output { color: var(--on-stage-2); }
/* Nút nhỏ dùng chung — KHÔNG mượn `.mo-ngan`: lớp đó nghĩa là "nút mở ngăn
   kéo bằng chứng của một hàng", và có một test đếm đúng một nút mỗi hàng để
   giữ luật "một điểm dừng bàn phím mỗi hàng". Mượn lớp là phá cái đếm đó. */
.nut-nho {
  background: none; border: 1px solid var(--rule); border-radius: 8px;
  padding: 3px 10px; font: 600 13.5px var(--sans); color: var(--muted);
  cursor: pointer; transition: background-color var(--t-mau) ease,
    color var(--t-mau) ease, border-color var(--t-mau) ease;
}
@media (hover: hover) and (pointer: fine) {
  .nut-nho:hover { color: var(--cobalt); border-color: var(--seal-line); background: var(--cobalt-soft); }
}
.stage .nut-nho { color: var(--on-stage-2); border-color: var(--stage-line); }
@media (hover: hover) and (pointer: fine) {
  .stage .nut-nho:hover { color: var(--on-stage); background: var(--cobalt-soft); }
}

.loc-dem {
  grid-column: 1 / -1; margin: var(--s2) 0 0; display: flex; gap: var(--s3);
  align-items: center; flex-wrap: wrap; font-size: 14px; color: var(--ink-2);
}
/* Bản dán lặp đã gỡ. Khối `.nut-nho` ngay bên trên bị chép lại nguyên văn ở
   đây, và cụm `.stage` mở đầu khối bị chú thích nuốt vào — CSS bỏ chú thích
   nên bộ chọn thành `.stage .nut-nho`, còn dòng cuối khối MẤT tiền tố và trở
   thành `.loc-dem` trần, tô `--on-stage-2` (#9DB1D6 — token của nền tối) lên
   MỌI `.loc-dem`. Ở `/so-sanh/` khối lọc nằm ngoài sân khấu, trên nền
   porcelain: 2,0:1, trượt WCAG 1.4.3.

   Vì sao cổng axe 56 trang không bắt: `<span id="loc-dem">` rỗng trong HTML
   máy chủ, JS chỉ ghi số dòng bị lọc vào sau khi người dùng gõ — axe không
   chấm tương phản của nút văn bản rỗng. */
.stage .loc-dem { color: var(--on-stage-2); }
/* Hàng bị lọc ẩn bằng thuộc tính `hidden`; bảng cần display đúng kiểu ô. */
tr[hidden], li[hidden] { display: none; }

/* Top 5 lớp khảo sát: thêm một dòng mốc đối chiếu dưới mỗi hàng. */
.rank-ks li { grid-template-areas: "stt who bar rate lai" "ny ny ny ny ny"; }
.r10-ny {
  /* Bắt đầu từ cột TÊN, canh bằng vùng lưới chứ không bằng `padding-left` gõ
     tay theo bề rộng logo — logo đổi cỡ là con số đệm đó sai ngay. */
  grid-area: ny; grid-column: who / -1;
  font-size: 13.5px; color: var(--muted); margin-top: 2px;
}
.r10-ny b { color: var(--cobalt); font-weight: 700; }

/* ── Sparkline 7 ngày cạnh tên ngân hàng ─────────────────────────────
   Hướng đọc được KHÔNG CHỈ bằng màu: mũi tên nhỏ đi kèm, và nhãn đầy đủ nằm
   trong aria-label. Chuỗi phẳng dùng màu mực nhạt — đứng yên không phải tin
   xấu cũng không phải tin tốt. */
.spark { display: inline-flex; align-items: center; gap: 3px; vertical-align: -5px; }
.spark svg { display: block; overflow: visible; }
.spark polyline {
  fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  stroke: var(--muted);
}
.spark i { font: 700 9px/1 var(--sans); font-style: normal; color: var(--muted); }
.spark.up polyline, .spark.up i { stroke: var(--emerald); color: var(--emerald); }
.spark.down polyline, .spark.down i { stroke: var(--warn); color: var(--warn); }
.stage .spark.up polyline, .stage .spark.up i { stroke: var(--emerald-bright); color: var(--emerald-bright); }
@media (max-width: 700px) { .spark svg { width: 48px; } }

/* ── Hai hình biến động đứng cạnh nhau ───────────────────────────────
   Lớp khảo sát và lớp niêm yết, mỗi lớp một thang riêng nên KHÔNG dùng chung
   trục — hai hình chỉ chia nhau chiều ngang, không chia nhau ý nghĩa. Màu
   đường theo đúng quy ước hai lớp của toàn trang: amber là mức được chào,
   cobalt là mức niêm yết. */
.hai-hinh { display: grid; gap: var(--s4); grid-template-columns: 1fr 1fr; }
@media (max-width: 860px) { .hai-hinh { grid-template-columns: 1fr; } }
.chart-chao .line { stroke: var(--amber); }
.chart-chao .dot { fill: var(--amber); }
.chart-chao .band { fill: var(--amber-soft); }

/* Vạch soi cùng ngày giữa hai hình biến động. Mảnh và nhạt — nó là công cụ
   ĐỐI CHIẾU, không phải một lớp dữ liệu; đậm hơn đường số liệu là sai vai. */
.vach-soi { stroke: var(--ink-2); stroke-width: 1; stroke-dasharray: 3 3; opacity: .55; pointer-events: none; }

/* Đường cong kỳ hạn trong hero — hình dựng từ chính số của trang, không phải
   hoạ tiết. Hai kỳ hạn có thẻ ở trên được đánh dấu chấm to kèm số, để mắt nối
   được thẻ với vị trí của nó trên đường. */
.hero-cong { margin: var(--s4) 0 0; }
.hero-cong figcaption {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: baseline;
  font: 600 12px/1.3 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--on-stage-2); margin-bottom: var(--s3);
}
.hero-cong figcaption span { text-transform: none; letter-spacing: 0; font-weight: 500; opacity: .8; }
.hero-cong svg { display: block; width: 100%; height: 116px; overflow: visible; }
.hc-line { fill: none; stroke: var(--cobalt-bright); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.hc-dot { fill: var(--stage); stroke: var(--cobalt-bright); stroke-width: 2; }
.hc-dot.on { fill: #fff; stroke: #fff; }
.hc-lb { fill: var(--on-stage); font: 800 14px var(--sans); }
.hc-t { fill: var(--on-stage-2); font: 500 12px var(--mono); }
@media (max-width: 900px) { .hero-cong svg { height: 92px; } }

/* Hai đường cong chồng nhau — hình chữ ký của sản phẩm. Amber là lớp thị
   trường (cùng quy ước màu với toàn trang), cobalt là lớp niêm yết; vùng tô
   giữa hai đường là KHOẢNG CÁCH, thứ duy nhất hình này tồn tại để nói. */
.hai-cong { padding: var(--s5); }
.hc-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s4);
  margin-bottom: var(--s4); font-size: 14px;
}
.hc-leg { display: inline-flex; align-items: center; gap: 6px; font-weight: 650; }
.hc-leg i { width: 14px; height: 3px; border-radius: 2px; }
.hc-leg.ks i { background: var(--amber); }
.hc-leg.ny i { background: var(--cobalt); }
.hc-truc { margin-left: auto; color: var(--muted); font-size: 13px; }
.hai-cong svg { display: block; width: 100%; height: auto; overflow: visible; }
.hc2-band { fill: var(--amber-soft); opacity: .85; }
.hc2-ks { fill: none; stroke: var(--amber); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.hc2-ny { fill: none; stroke: var(--cobalt); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.hc2-dks { fill: #fff; stroke: var(--amber); stroke-width: 2; }
.hc2-dny { fill: #fff; stroke: var(--cobalt); stroke-width: 2; }
.hc2-t { fill: var(--muted); font: 500 12px var(--mono); }
@media (max-width: 700px) { .hc-truc { margin-left: 0; width: 100%; } }

/* ── Nhịp thị giác giữa các khối ─────────────────────────────────────
   Trước 12/08 mọi khối là "tiêu đề + thẻ trắng trên nền xám" — năm khối
   giống hệt nhau, nên mắt không có mốc nào để bám và cả trang đọc thành một
   dải đều. Khối chẵn lùi xuống một dải nền chìm, tràn hết bề ngang: nó không
   thêm chữ nào, chỉ cho mắt biết "đây là một chuyện khác".

   `--bg-chim` đủ nhạt để chữ vẫn đạt tương phản AA và thẻ trắng bên trong vẫn
   nổi lên — đây là nền, không phải một lớp thông tin. */
.sec-chim {
  position: relative; padding-top: var(--s6); padding-bottom: var(--s6);
}
.sec-chim::before {
  content: ""; position: absolute; inset: 0 50%; z-index: -1;
  width: 100vw; margin-left: -50vw;
  background: var(--head); border-block: 1px solid var(--rule);
}

/* Ví dụ tiền lãi ở khối giới thiệu công cụ — bốn dòng số, cùng khuôn lưới nên
   con số thẳng cột và so được bằng mắt. */
.vd-list { margin: 0 0 var(--s4); padding: 0; list-style: none; }
.vd-list li {
  display: grid; align-items: baseline; gap: var(--s2) var(--s3);
  grid-template-columns: 132px 18px minmax(0, 1fr) auto;
  padding: var(--s3) 0; border-bottom: 1px solid var(--rule);
}
.vd-list li:first-child { padding-top: 0; }
.vd-list li:last-child { border-bottom: 0; }
.vd-dk { font-weight: 650; font-variant-numeric: tabular-nums; }
.vd-mui { color: var(--muted); }
.vd-lai { font-variant-numeric: tabular-nums; }
.vd-lai b { font-weight: 800; font-size: 19px; color: var(--cobalt); }
.vd-ai { color: var(--muted); font-size: 13.5px; text-align: right; }
@media (max-width: 640px) {
  .vd-list li { grid-template-columns: 1fr auto; }
  .vd-mui { display: none; }
  .vd-ai { grid-column: 1 / -1; text-align: left; }
}

/* Bốn con số của bản nhận định — lưới số lớn, không phải bốn dòng văn xuôi. */
.kf-luoi { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--rule); }
.kf-o { background: var(--surface); padding: var(--s4); }
.kf-so { margin: 0; display: flex; align-items: baseline; gap: 5px; }
.kf-so b {
  font: 800 clamp(26px, 3vw, 34px)/1 var(--sans); letter-spacing: -.03em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.kf-so i { font-style: normal; font-size: 14px; font-weight: 600; color: var(--muted); }
.kf-chu { margin: var(--s2) 0 0; font-size: 14px; color: var(--ink-2); line-height: 1.45; }
@media (max-width: 560px) { .kf-luoi { grid-template-columns: 1fr; } }

/* Thẻ bài phân tích ở trang chủ: chữ bên trái, hai con số bên phải. */
.artcard { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: var(--s5); }
.ac-so { display: grid; gap: var(--s3); align-content: center;
         border-left: 1px solid var(--rule); padding-left: var(--s5); }
/* Số và ĐƠN VỊ trên cùng một đường chân chữ. `display:block` ở số đẩy đơn vị
   xuống dòng riêng, và "%/năm" đứng một mình dưới "6,10" đọc như một dòng dữ
   liệu thứ hai chứ không như đơn vị của con số ngay trên. */
.ac-so > div { display: block; }
.ac-so b {
  font: 800 30px/1 var(--sans); letter-spacing: -.03em;
  color: var(--cobalt); font-variant-numeric: tabular-nums;
}
.ac-so i { font-style: normal; font-size: 13px; font-weight: 600; color: var(--muted); margin-left: 4px; }
.ac-so span { display: block; margin-top: 4px; font-size: 13.5px; color: var(--ink-2); line-height: 1.4; }
@media (max-width: 800px) {
  .artcard { grid-template-columns: 1fr; }
  .ac-so { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: var(--s4); }
}

/* Ba lớp nguồn ở trang phương pháp — ba dải cạnh nhau, đậm dần từ trái sang
   phải theo đúng thứ bậc tin cậy. Màu đi theo quy ước hai lớp của toàn trang:
   cobalt cho niêm yết, amber cho thị trường, mực cho nguồn báo ở giữa. */
.lop3 { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--s4);
        grid-template-columns: repeat(3, 1fr); }
.lop3 li {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); padding: var(--s4) var(--s5) var(--s5);
}
.l3-k { margin: 0; display: flex; align-items: center; gap: var(--s2);
        font-weight: 750; font-size: 17px; letter-spacing: -.02em; }
.l3-k i {
  font: 600 12px var(--mono); font-style: normal; letter-spacing: .08em;
  color: var(--cobalt); background: var(--cobalt-soft); padding: 3px 7px; border-radius: 6px;
}
.l3-so { margin: var(--s3) 0 0; color: var(--muted); font-size: 14px; }
.l3-so b { font: 800 26px/1 var(--sans); color: var(--ink); letter-spacing: -.03em;
           font-variant-numeric: tabular-nums; margin-right: 5px; }
.l3-thanh { margin: var(--s3) 0 0; height: 6px; border-radius: 999px; background: var(--surface-2);
            border: 1px solid var(--rule); overflow: hidden; }
.l3-thanh span { display: block; height: 100%; background: var(--cobalt); }
.lop3 li:nth-child(2) .l3-thanh span { background: var(--ink-2); }
.lop3 li:nth-child(3) .l3-thanh span { background: var(--amber); }
.lop3 li:nth-child(3) .l3-k i { color: var(--amber); background: var(--amber-soft); }
.l3-tin { margin: var(--s3) 0 0; font-size: 14.5px; color: var(--ink-2); line-height: 1.5; }
.l3-nguon { margin: var(--s2) 0 0; font-size: 13.5px; color: var(--muted); line-height: 1.5; }
@media (max-width: 860px) { .lop3 { grid-template-columns: 1fr; } }

/* Lối đi tiếp ở trang 404 — danh sách link, không phải một trang chủ thu nhỏ. */
.err-loi { margin: var(--s3) 0 0; padding: 0; list-style: none; }
.err-loi li { padding: var(--s3) 0; border-bottom: 1px solid var(--rule); font-size: 16px; color: var(--muted); }
.err-loi li:last-child { border-bottom: 0; }
.err-loi a { font-weight: 650; color: var(--ink); text-decoration: none; }
.err-loi a:hover { color: var(--cobalt); text-decoration: underline; }

/* ═══ 23. Hero VOLT ══════════════════════════════════════════════════════
   Hai cột: bên trái là câu trả lời (chip → số → ngân hàng → tính tiền), bên
   phải là bốn thẻ chỉ số. Tỉ lệ 1fr / 384px theo bản bàn giao. */
.stage-volt {
  display: grid; grid-template-columns: minmax(0, 1fr) 384px;
  gap: clamp(20px, 3vw, 44px); align-items: start;
}
.stage-volt .stage-ans-2 { grid-column: 1 / -1; }

/* Hàng điều khiển: nhãn · chip kỳ hạn · công tắc lớp (đẩy sang phải) */
.hero-ctl {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: var(--s5);
}
.hero-ctl-k {
  font: 600 12px var(--mono); letter-spacing: .22em; text-transform: uppercase;
  color: var(--muted);
}
.ky-chips a, .ky-chips button {
  font: 500 13.5px var(--mono); letter-spacing: .06em; padding: 7px 13px;
  border-radius: var(--r-sm);
}
/* Kỳ hạn CHƯA có dữ liệu ở trang chủ là link sang trang riêng của nó — mờ hơn
   nút thật để phân biệt, nhưng KHÔNG `disabled`: nó vẫn đi được. */
.ky-chips a { opacity: .62; }

/* Công tắc hai lớp — một khối liền, không phải hai nút rời. */
.seg {
  margin-left: auto; display: flex; border: 1px solid var(--rule-strong);
  border-radius: var(--r-sm); overflow: hidden;
}
.seg button {
  appearance: none; cursor: pointer; border: 0; background: transparent;
  font: 500 12.5px var(--mono); letter-spacing: .1em; padding: 8px 14px;
  color: var(--ink-2);
}
.seg button[aria-pressed="true"] {
  background: var(--acGrad); color: var(--on-accent); font-weight: 600;
}
/* Lớp niêm yết là tông THÉP, không quầng sáng — luật phân lớp của VOLT. */
.seg button[data-lop="ny"][aria-pressed="true"] {
  background: var(--steel); color: var(--stage); box-shadow: none;
}

/* H1 đứng ở chỗ dòng nhãn của prototype: nhỏ, mono, in hoa giãn chữ. Nó là
   TIÊU ĐỀ về mặt ngữ nghĩa và là NHÃN về mặt thị giác — cùng một dòng phục vụ
   cả máy tìm kiếm lẫn mắt người. */
.hero-nhan {
  margin: 0 0 var(--s2); font: 600 12.5px/1.6 var(--mono);
  letter-spacing: .2em; text-transform: uppercase; color: var(--muted);
}
.hero-nhan span { color: var(--cobalt); }

.hero-so { margin: 0 0 var(--s3); display: flex; align-items: baseline; gap: 14px; }
.hero-dv { font: 500 21px var(--mono); color: var(--ink-2); }

.hero-who {
  margin: 0 0 var(--s3); display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
/* Viên nang nằm trên TỪNG tên chứ không bọc cả cụm: hero có thể mang nhiều
   ngân hàng ĐỒNG HẠNG (13/08 tối — "hiển thị đủ thẻ, không ưu tiên ai"),
   mỗi bank một thẻ riêng thì mới đọc được là mấy cái tên ngang nhau. */
.hero-bank { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.hero-bank .bank-name {
  font-size: 16px; font-weight: 700;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 6px 14px 6px 7px; border: 1px solid var(--rule-strong);
  border-radius: 999px; background: var(--surface-2);
}
.hero-badge {
  font: 600 12.5px var(--mono); letter-spacing: .16em; text-transform: uppercase;
  padding: 6px 11px; border-radius: 999px;
}
.hero-badge.tt {
  color: var(--cobalt); border: 1px solid var(--seal-line);
  background: var(--cobalt-soft); box-shadow: 0 0 16px rgba(var(--acR), var(--gb));
}
.hero-badge.ny {
  color: var(--steel); border: 1px solid rgba(var(--stR), .4);
  background: rgba(var(--stR), .06); box-shadow: none;
}
.hero-sosanh { margin: 0 0 var(--s4); font-size: 15px; color: var(--ink-2); }
.hero-sosanh b { color: var(--ink); }
.hero-sosanh .gap { color: var(--emerald); }

/* Dải HUD — câu hỏi và câu trả lời trong MỘT dòng chữ, không phải một form. */
.hero-tinh {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 16px 18px; border: 1px solid var(--rule);
  border-radius: var(--r); background: var(--stage-2);
  font-size: 16px; color: var(--ink-2);
}
.hero-lai {
  font: 600 clamp(26px, 3vw, 38px) var(--mono); color: var(--cobalt-strong);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.hero-dv-d { font: 500 18px var(--mono); color: var(--ink-2); }
.hero-chan {
  margin: 10px 0 0; font: 500 12px var(--mono); letter-spacing: .06em;
  color: var(--faint);
}

/* Bốn thẻ chỉ số — lưới 2×2 bên phải. */
.hero-kpi { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.kpi {
  padding: 16px; border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--surface-2);
}
.kpi-k {
  margin: 0 0 10px; font: 600 12px var(--mono); letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted);
  /* KHÔNG justify: nhãn in hoa hai chữ mà xuống dòng là bị kéo giãn thành
     "BIÊN     ĐỘ" (lộ khi nâng cỡ chữ 14/08) — luật justify toàn cục dành
     cho văn xuôi, không dành cho nhãn. */
  text-align: left;
}
.kpi-v {
  margin: 0; font: 600 30px var(--mono); color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.kpi-v i { font: 500 14px var(--mono); font-style: normal; color: var(--ink-2); margin-left: 5px; }
.kpi-v.ok { color: var(--emerald); text-shadow: 0 0 16px rgba(var(--upR), var(--gb)); }
.kpi-s { margin: 6px 0 0; font-size: 13px; color: var(--ink-2); }

/* Vùng dữ liệu sáng lên khi trỏ vào — VOLT §5, nền `rgba(acR,.045)`. Chỉ con
   trỏ thật; trên cảm ứng nền này sẽ dính lại sau cú chạm. */
@media (hover: hover) and (pointer: fine) {
  .kpi, .hero-tinh { transition: background-color var(--t-mau) ease, border-color var(--t-mau) ease; }
  .kpi:hover, .hero-tinh:hover {
    background: rgba(var(--acR), .045); border-color: var(--seal-line);
  }
}

@media (max-width: 1000px) {
  /* minmax(0,1fr) chứ KHÔNG phải 1fr trần: `1fr` = minmax(auto,1fr), min
     auto ăn min-content của hàng chip cuộn ngang (741px) → track nở 741px
     trong khung 358px và Chrome mobile nở luôn layout viewport — chính là
     "vỡ toàn bộ" trên iPhone 13/08. Desktop đã dùng minmax(0,1fr) từ đầu;
     bản mobile thiếu đúng một chữ. */
  .stage-volt { grid-template-columns: minmax(0, 1fr); }
  .hero-kpi { grid-template-columns: 1fr 1fr; }
  .seg { margin-left: 0; }
}
@media (max-width: 560px) {
  .hero-kpi { grid-template-columns: 1fr; }
  .hero-so { gap: 8px; }
}

/* ── 23b. Gỡ hai luật kế thừa đụng vào hero mới ────────────────────────
   1. `.stage-ans { order: 2 }` (mục 22) sinh ra để đảo thứ tự cho bố cục HAI
      THẺ: kết quả đứng trước bộ lọc trong DOM cho mobile, desktop đảo lại.
      Hero VOLT không còn cặp đó — cột trái là câu trả lời, cột phải là chỉ số,
      và DOM đã đúng thứ tự đọc. Để nguyên `order` thì hai cột hoán chỗ.
   2. `.stage h1` khai cỡ chữ khổng lồ cho tít cũ. H1 nay là DÒNG NHÃN mono
      nhỏ, nên phải khai lại với đủ độ cụ thể — không thì nó ăn cỡ 58px. */
.stage-volt .stage-ans { order: 0; grid-column: 1; }
.stage-volt .hero-kpi { order: 0; grid-column: 2; }
.stage-volt .stage-ans-2 { order: 1; }
.stage .hero-nhan {
  font: 600 12.5px/1.6 var(--mono); letter-spacing: .2em;
  text-transform: uppercase; color: var(--muted);
  margin: 0 0 var(--s2); max-width: none;
}
.stage .hero-nhan span { color: var(--cobalt); }
@media (max-width: 1000px) {
  .stage-volt .stage-ans, .stage-volt .hero-kpi { grid-column: 1; }
}

/* ═══ 24. Thanh trạng thái VOLT — đúng bản bàn giao ══════════════════════
   Một hàng 46px: logo · nav mono in hoa · công tắc + mốc + đồng hồ bên phải.
   Bản trước là hai hàng vì mốc "bản chốt" và "kiểm tra gần nhất" đứng cạnh
   nhau; mốc thứ hai nay xuống dòng nhãn của hero nên một hàng đủ chỗ. */
.head-top { min-height: 46px; gap: 16px 24px; padding-block: 8px; }
.logo { font-size: 17px; letter-spacing: .01em; margin-right: 8px; }
/* `24h` là viên gradient, không phải chữ tô màu — chữ ký của VOLT. */
.logo b {
  font: 600 16px var(--mono); padding: 2px 8px; border-radius: 6px;
  color: var(--on-accent); background: var(--acGrad);
  box-shadow: 0 0 18px rgba(var(--acR), var(--gb));
  text-shadow: none;
}
.site-head nav { gap: 6px; }
.site-head nav a, .site-head nav span {
  font: 500 13.5px var(--mono); letter-spacing: .08em; text-transform: uppercase;
  padding: 7px 12px; border: 1px solid transparent; border-radius: 6px;
  white-space: nowrap;
}
/* Mục đang xem là một Ô CÓ VIỀN sáng, không chỉ đổi màu chữ — trên một hàng
   nav mono in hoa thì chỉ đổi màu là gần như không thấy. */
.site-head nav a[aria-current="page"] {
  color: var(--cobalt-strong); background: var(--cobalt-soft);
  border-color: var(--seal-line);
  box-shadow: 0 0 14px rgba(var(--acR), var(--gb));
}
@media (hover: hover) and (pointer: fine) {
  .site-head nav a:hover { color: var(--ink); background: none; border-color: var(--rule-strong); }
  .site-head nav a[aria-current="page"]:hover { background: var(--cobalt-soft); border-color: var(--seal-line); }
}
.site-head nav span::after { font-size: 11.5px; }
.head-sys { gap: 16px; }
.head-live { letter-spacing: .14em; }

/* Số hero đúng cỡ bàn giao: clamp(84, 10.5vw, 148). Bản trước tôi để
   clamp(52, 6vw, 88) — nhỏ hơn gần một nửa, và đó là khác biệt lớn nhất khi
   đặt hai ảnh cạnh nhau. Đây là VẬT THỂ CHÍNH của trang. */
.stage .hero-so .ck-num {
  font-size: clamp(84px, 10.5vw, 148px); line-height: .95; letter-spacing: -.03em;
}
.hero-dv { font-size: 21px; }

/* Tiêu đề khối: `01 · TOP 5 DẪN ĐẦU` mono in hoa cyan, không phải tít sans. */
.section-head h2 {
  font: 600 13px var(--mono); letter-spacing: .24em; text-transform: uppercase;
  color: var(--cobalt-strong);
}
.section-head h2 i {
  font: 600 13px var(--mono); border: 0; padding: 0; margin-right: 6px;
  color: var(--cobalt-strong);
}
.section-head p {
  /* Ghi chú mục là VĂN XUÔI — mấy câu liền ("BẢN GHI ĐÃ QUA CỔNG KIỂM…")
     từng bị mono hoá IN HOA 11,5px: vừa phạm luật VOLT số 4 vừa là thứ chủ
     dự án chấm "mờ nhạt khó đọc" 13/08 tối. Mono in hoa chỉ dành cho NHÃN. */
  font: 500 15px/1.55 var(--sans); letter-spacing: 0; text-transform: none;
  color: var(--ink-2);
}

/* ── 24b. Ép về đúng MỘT hàng ──────────────────────────────────────────
   Bản bàn giao để logo · nav · trạng thái trên một thanh 46px. Ở bản trước
   nhóm trạng thái rơi xuống hàng thứ hai vì đệm nav và khoảng cách rộng hơn
   bản gốc. Đây là đo chứ không phải cảm tính: 1440px, hàng đầu cao 92px thay
   vì 46px, tức nó đã gãy làm đôi. */
.head-top { gap: 10px 18px; }
.site-head nav { gap: 3px; }
.site-head nav a, .site-head nav span { padding: 6px 9px; letter-spacing: .06em; }
.head-sys { gap: 12px; }
/* Bản nút-chữ cũ đặt đệm ở đây; công tắc mới tự quản kích thước
   trong .nt-track nên luật này thành vô nghĩa — bỏ, không để lại
   luật mồ côi đè lên bản dựng sau. */

/* Hàng chip kỳ hạn + công tắc lớp cũng phải đứng chung một hàng. */
.ky-chips a, .ky-chips button { padding: 6px 10px; }
/* Cỡ chữ nâng cho người lớn tuổi (14/08) làm nav dài thêm ~40px: ở khung
   1280 chữ "Phương pháp" chui xuống dưới nút TỐI. Bóp đệm + giãn cách chữ
   của nav ở khung hẹp hơn 1360 thay vì hạ lại cỡ chữ. */
@media (max-width: 1360px) {
  .site-head nav a, .site-head nav span { padding: 6px 6px; letter-spacing: .01em; }
  .head-top { gap: 10px 12px; }
  .head-sys { gap: 9px; }
}
.hero-ctl { gap: 8px; }

/* Dải HUD là MỘT dòng chữ: "Gửi [chip] nhận <số> đ tiền lãi sau N tháng".
   Nó gãy đôi thì mất đúng cái ý làm nên nó — câu hỏi và câu trả lời rời nhau
   thành hai khối, đọc lại như một cái form. */
.tien-chips { flex-wrap: nowrap; gap: 5px; }
.tien-chips button { padding: 6px 11px; font-size: 13.5px; }
.hero-tinh { gap: 8px; flex-wrap: nowrap; overflow-x: auto; }
.hero-tinh > span { white-space: nowrap; }
@media (max-width: 720px) {
  /* Ở khung hẹp thì cho gãy — ép một dòng trên điện thoại là bắt cuộn ngang. */
  .hero-tinh, .tien-chips { flex-wrap: wrap; overflow-x: visible; }
}

/* ── 24c. Ép một hàng ở khung rộng ─────────────────────────────────────
   Cộng bề rộng ba khối ra 1169px trong khung 1200px — vừa đủ, nhưng
   `margin-left: auto` trong một flex CÓ wrap vẫn đẩy khối cuối xuống hàng mới
   khi khoảng trống còn lại nhỏ hơn chỗ nó cần để canh phải. Ở khung rộng thì
   khai thẳng `nowrap`; dưới 1100px trả lại `wrap` để điện thoại không cuộn
   ngang. */
@media (min-width: 1100px) {
  .head-top { flex-wrap: nowrap; }
  .site-head nav { flex-wrap: nowrap; }
  .hero-ctl { flex-wrap: nowrap; }
  .ky-chips { flex-wrap: nowrap; }
}

/* ── 24d. `nowrap` phải đi kèm `flex: none` ────────────────────────────
   `flex-wrap: nowrap` chỉ cấm ITEM xuống hàng; bản thân item vẫn co lại dưới
   bề rộng nội dung và chữ BÊN TRONG nó gãy. Kết quả ở bản trước: logo "Lãi
   suất" vỡ hai dòng, nhãn "KỲ HẠN" vỡ đôi, hai nút công tắc lớp cụt chữ.
   Khối nào không được co thì phải nói ra. */
.logo, .hero-ctl-k, .head-sys, .seg, .hero-dv { flex: none; white-space: nowrap; }
.seg button { white-space: nowrap; flex: none; }
.site-head nav { flex: 0 1 auto; min-width: 0; }

/* Dải HUD: cho gãy dòng lại. Cuộn ngang giấu mất đuôi câu ("đ tiền lãi sau 12
   tháng") — mất nghĩa còn tệ hơn gãy dòng. Giữ cụm "nhận <số> đ" liền khối
   để câu không đứt ở giữa con số. */
.hero-tinh { flex-wrap: wrap; overflow-x: visible; }

/* `nowrap` trên CẢ cụm là quá tay, và nó tràn ngay khi hero in một KHOẢNG chứ
   không phải một số. Đo 24/08 ở 375px: "93.000.000–95.000.000" rộng 317px, cụm
   "nhận … đ" thành 382px trong khi lòng hộp chỉ 329px — trang cuộn ngang 404px
   và `.bottomnav` phình theo. Số đơn thì vừa, nên lỗi chỉ hiện những ngày lớp
   khảo sát trả về khoảng; đó là lý do nó sống sót nhiều lượt kiểm.

   Điều PHẢI giữ vẫn là "không đứt ở giữa con số" — nên nowrap chuyển xuống
   đúng con số, còn cụm chữ quanh nó được phép gãy dòng. Cỡ chữ thêm sàn theo
   vw để một khoảng dài hơn nữa cũng không tràn lại; trên 464px thì clamp chạm
   trần 26px nên máy tính bảng không đổi gì. */
.hero-nhan-lai { display: inline-flex; align-items: baseline; gap: 8px; white-space: normal; }
.hero-nhan-lai .hero-lai { white-space: nowrap; font-size: clamp(21px, 5.6vw, 26px); }

/* Chip tiền chỉ được `nowrap` ở khung rộng. Luật ở mục 24b áp cho MỌI bề rộng
   nên ở 390px nó đẩy trang tràn ngang — đo được, và `kiem_giao_dien.py` bắt. */
@media (max-width: 900px) {
  .tien-chips { flex-wrap: wrap; }
  .hero-tinh { overflow-x: visible; }
}

/* Nhóm trạng thái rộng 396px, không vừa khung 390px. `flex: none` ở mục 24d
   cần cho khung rộng lại chính là thứ đẩy nó tràn ở khung hẹp. Ở điện thoại:
   cho co lại, cho gãy dòng, và bỏ đồng hồ — nó là trang trí (`aria-hidden`),
   còn mốc bản chốt thì không. */
@media (max-width: 560px) {
  .head-sys { flex: 1 1 100%; white-space: normal; flex-wrap: wrap; gap: 10px; }
  .head-clock { display: none; }
  .head-live { font-size: 12.5px; }
}

/* ── 24e. Khung rộng 1320px theo bản bàn giao ──────────────────────────
   Bản bàn giao dùng `max-width: 1320px`; kho này đang 1200px. 120px chênh
   lệch đó là lý do thật khiến thanh tiêu đề chồng chữ khi ép một hàng: logo +
   năm mục nav mono in hoa + công tắc + mốc + đồng hồ cần 1290px, thừa ra 90px
   so với 1200. Nới khung là sửa nguyên nhân; ép `nowrap` trong khung chật chỉ
   đổi "gãy dòng" thành "chồng chữ", tệ hơn. */
.wrap { max-width: 1320px; }
/* Nav được phép co, nhưng co thì phải BỎ BỚT chứ không được chồng lên nhau. */
.site-head nav { overflow: hidden; }
/* KHÔNG khai lại grid .stage-volt ở đây. Bản 13/08 sáng có dòng
   `.stage-volt { grid-template-columns: minmax(0,1fr) 384px }` — bản sao
   y hệt luật gốc nhưng đứng SAU media query mobile trong file, nên nó đè
   mất `1fr` của ≤1000px: điện thoại nhận cột chữ 0px và chữ vỡ từng từ
   (ảnh chủ dự án 13/08 chiều). Cổng "tràn ngang" không bắt được vì trang
   không tràn — nó SẬP VÀO TRONG; cổng nay đo thêm "cột chữ hẹp". */

/* ═══ 25. Hàng Top 5 theo bản bàn giao VOLT ═══════════════════════════════
   Bảng vùng đổi để nhãn đối chiếu (`ny`) đứng NGAY DƯỚI TÊN thành một chip,
   thay vì trải hết bề ngang thành dòng thứ hai. Ba cột phải (`bar`/`rate`/
   `lai`) trải cả hai hàng nên chúng canh giữa theo cả khối — đó là lý do hàng
   trong file đọc như một dòng liền chứ không phải hai dòng chồng. */
.rank-ks li {
  grid-template-areas:
    "stt who bar rate lai"
    "stt ny  bar rate lai";
  padding: 15px 18px; gap: 5px var(--s4);
  grid-template-columns: 44px minmax(0, 200px) minmax(120px, 1fr) 118px 150px;
}
/* Số hạng: mono lớn, hàng đầu mang màu accent — người dẫn đầu phải nhận ra
   được mà không cần đọc số. */
.rank10 li::before {
  content: counter(r10, decimal-leading-zero);
  grid-area: stt; font: 600 20px var(--mono); color: var(--faint);
}
.rank10 li:first-child::before { color: var(--cobalt); }
/* Nhãn đối chiếu thành CHIP, không phải một dòng chữ chạy hết bề ngang. */
.rank-ks .r10-ny {
  grid-area: ny; justify-self: start;
  font: 500 12.5px var(--mono); letter-spacing: .08em;
  padding: 3px 9px; border-radius: 999px;
  color: var(--cobalt); border: 1px solid var(--seal-line);
  background: var(--cobalt-soft);
}
.rank-ks .r10-ny b { color: var(--cobalt-strong); font-weight: 600; }
/* Thanh: mảnh hơn, gradient accent, có quầng — lớp thị trường. */
.rank10 .r10-bar { height: 8px; background: rgba(var(--lnR), .09); }
.rank10 .r10-bar i { background: var(--acGrad90); }
.rank10 li:first-child .r10-bar i { background: var(--acGrad90); }
.r10-rate {
  font: 600 23px var(--mono); text-align: right; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.r10-rate i { font: 500 12px var(--mono); font-style: normal; color: var(--ink-2); margin-left: 4px; }
.r10-lai { text-align: right; }
.r10-lai b {
  display: block; font: 500 15.5px var(--mono); color: var(--cobalt-strong);
  font-variant-numeric: tabular-nums;
}
.r10-lai i {
  display: block; margin-top: 2px; font: 500 12px var(--mono); font-style: normal;
  letter-spacing: .08em; text-transform: uppercase; color: var(--faint);
}
/* Hàng dữ liệu sáng lên khi trỏ vào — VOLT §5. */
@media (hover: hover) and (pointer: fine) {
  .rank10 li:hover { background: rgba(var(--acR), .045); }
}
@media (max-width: 760px) {
  .rank-ks li {
    grid-template-areas: "stt who rate" "stt ny lai" "bar bar bar";
    grid-template-columns: 34px minmax(0, 1fr) auto;
  }
  .r10-rate { font-size: 19px; }
  .r10-lai { text-align: left; }
  .r10-lai b { font-size: 14px; }
}

/* Chip nhãn gãy hai dòng làm mỗi hàng cao thêm 18px và năm hàng lệch nhịp.
   Cột tên rộng 200px không đủ cho "niêm yết 7,00% · +2,6 điểm" — nới lên 248px
   và cấm gãy: chip là MỘT nhãn, không phải một câu. */
.rank-ks li { grid-template-columns: 44px minmax(0, 248px) minmax(110px, 1fr) 118px 150px; }
.rank-ks .r10-ny { white-space: nowrap; }
@media (max-width: 1100px) {
  .rank-ks li { grid-template-columns: 40px minmax(0, 210px) minmax(80px, 1fr) 104px 132px; }
  .rank-ks .r10-ny { white-space: normal; }
}

/* ═══ 26. Nền trần + panel trong mờ — khớp bản bàn giao ═══════════════════
   Hero KHÔNG phải một tấm thẻ: dữ liệu nằm thẳng trên nền trang, lưới kỹ
   thuật và vệt sáng chạy phía sau. Chỉ các khối con là panel. */
.stage-bare {
  background: none; border: 0; box-shadow: none; border-radius: 0;
  overflow: visible; padding: 42px 0 38px;
}
.stage-bare::before { display: none; }

.kpi { background: var(--panel-2); border-color: rgba(var(--lnR), .14); border-radius: 10px; }
.hero-tinh {
  background: var(--panel-hi); border-color: rgba(var(--lnR), .16);
  border-radius: 12px;
}
.card, .hai-cong {
  background: var(--panel); border-color: rgba(var(--lnR), .14);
  border-radius: 12px; box-shadow: none;
}

/* Hình đường cong trong hero: panel + khung HUD góc + đầu đề mono. */
.hero-cong {
  margin: var(--s5) 0 0; padding: 18px 14px 8px;
  background: var(--panel); border: 1px solid rgba(var(--lnR), .14);
  border-radius: 12px; position: relative;
}
.hero-cong::before, .hero-cong::after {
  content: ""; position: absolute; width: 14px; height: 14px; pointer-events: none;
}
.hero-cong::before {
  top: -1px; left: -1px;
  border-top: 1px solid rgba(var(--acR), .7); border-left: 1px solid rgba(var(--acR), .7);
}
.hero-cong::after {
  bottom: -1px; right: -1px;
  border-bottom: 1px solid rgba(var(--acR), .7); border-right: 1px solid rgba(var(--acR), .7);
}
.hero-cong figcaption {
  font: 600 13px var(--mono); letter-spacing: .18em; text-transform: uppercase;
  color: var(--cobalt-strong); margin-bottom: 10px;
}
.hero-cong figcaption span {
  font: 500 12.5px var(--mono); letter-spacing: .08em; color: var(--muted);
  text-transform: none; margin-left: 12px;
}
/* Đường thị trường: gradient + quầng + TỰ VẼ khi trang mở. Một lần, 1,3s —
   không lặp nên KHÔNG gắn --play (paused sẽ giữ đường ở trạng thái vô hình);
   reduced-motion đã có luật duration .001ms toàn cục lo. */
.hc-line, .hc2-ks {
  stroke: var(--cobalt); stroke-width: 2.6; fill: none;
  stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 8px rgba(var(--acR), var(--gb)));
}
[pathLength] { stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: ls-dash 1.3s .4s cubic-bezier(.4, 0, .2, 1) forwards; }
.hc2-ny { stroke: var(--steel-line); stroke-width: 1.8; fill: none; stroke-dasharray: 5 6; }
.hc2-band { fill: rgba(var(--acR), .10); }
.hc2-dks { fill: var(--cobalt); stroke: var(--bg); stroke-width: 1.4; }
.hc2-dny { fill: var(--bg); stroke: var(--steel-line); stroke-width: 1.2; }
.hc2-t, .hc-t { font: 500 12px var(--mono); fill: var(--faint); }
.hc-dot { fill: var(--bg); }
.hc-lb { fill: var(--ink); font: 700 14px var(--mono); }
.hai-cong .hc-leg { font: 500 12.5px var(--mono); letter-spacing: .06em; color: var(--ink-2); }

/* ═══ 27. Trang phương pháp — sơ đồ quy trình 7 bước ═════════════════════
   Quy trình là thứ NHÌN THẤY ĐƯỢC: chuỗi bước có thứ tự. Mỗi bước một ô
   panel nhỏ, icon Lucide, nối nhau bằng mũi tên; điện thoại xếp dọc và mũi
   tên quay xuống. Văn xuôi phía dưới thành phần đọc thêm, không bị xoá —
   test khoá nội dung vẫn nguyên. */
.wf {
  list-style: none; margin: 0; padding: 0; counter-reset: wf;
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 26px 22px;
}
.wf li {
  counter-increment: wf; position: relative;
  background: var(--panel-2); border: 1px solid rgba(var(--lnR), .14);
  border-radius: 10px; padding: 14px 12px 12px;
  display: grid; gap: 6px; justify-items: start; align-content: start;
}
.wf li::before {
  content: counter(wf, decimal-leading-zero);
  font: 600 12px var(--mono); letter-spacing: .12em; color: var(--faint);
}
.wf li .li { width: 22px; height: 22px; color: var(--cobalt); }
.wf li b { font: 650 14.5px var(--sans); color: var(--ink); letter-spacing: -.01em; }
.wf li i { font: 500 12px var(--mono); font-style: normal; color: var(--muted); line-height: 1.5; }
/* Mũi tên nối — vẽ bằng mask sẵn có của hệ, không thêm glyph lạ. */
.wf li:not(:last-child)::after {
  content: ""; position: absolute; top: 50%; right: -19px; width: 15px; height: 15px;
  transform: translateY(-50%) rotate(-90deg);
  background: var(--cobalt); opacity: .55;
  -webkit-mask: var(--ic-chevron) center / contain no-repeat;
  mask: var(--ic-chevron) center / contain no-repeat;
}
@media (max-width: 1100px) { .wf { grid-template-columns: repeat(4, 1fr); }
  .wf li:nth-child(4)::after { display: none; } }
@media (max-width: 640px) {
  .wf { grid-template-columns: 1fr 1fr; gap: 20px 16px; }
  .wf li::after { display: none; }
}
/* Bốn ô sức khoẻ dữ liệu: hàng ngang trên desktop (khác lưới 2×2 của hero). */
.kpi-hang { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .kpi-hang { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .kpi-hang { grid-template-columns: 1fr; } }

/* Hình chính trong bản nhận định — cùng khuôn thẻ hai lớp của trang chủ. */
.art-main .hai-cong { margin: var(--s5) 0; }
.art-hinh-k {
  margin: var(--s6) 0 var(--s3); font: 600 13px var(--mono);
  letter-spacing: .2em; text-transform: uppercase; color: var(--cobalt-strong);
}

/* ═══ 28. Nguyên tắc dự án 13/08 — áp toàn trang ═════════════════════════ */
/* 28a. TIÊU ĐỀ BẢNG LẶP KHI CUỘN. `thead th` đã sticky nhưng bị hai thứ vô
   hiệu: (1) top:0 chui dưới thanh tiêu đề dính; (2) `.scroller{overflow-x:
   auto}` biến wrapper thành scroll container nên sticky bám wrapper chứ không
   bám cửa sổ. Ở khung rộng bảng vốn không tràn ngang → `overflow-x: clip`
   (KHÔNG tạo scroll container, sticky bám cửa sổ trở lại); khung hẹp giữ
   `auto` vì bảng phải cuộn ngang được. */
thead th { top: var(--cao-dau, 46px); }
@media (min-width: 901px) { .scroller { overflow-x: clip; } }

/* 28b. Trang công cụ — cụm điều khiển là MỘT bảng điều khiển, không phải các
   hàng rơi tự do. Nhãn cột trái thẳng hàng, chip cột phải. */
.ctl-card { padding: var(--s5) var(--s5) var(--s4); gap: var(--s4); }
@media (min-width: 761px) {
  .ctl-card .control { display: grid; grid-template-columns: 168px minmax(0, 1fr);
    align-items: baseline; column-gap: var(--s4); }
  .ctl-card .control > span:first-child { margin: 0; }
}

/* 28c. Khối "Cách tính": công thức mono lớn + ba thẻ icon. */
.ct-congthuc {
  margin: 0 0 var(--s2); font: 600 clamp(17px, 2vw, 22px) var(--mono);
  letter-spacing: -.01em; color: var(--ink);
}
.ct-congthuc span { color: var(--cobalt-strong); }
.ct-luoi { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: var(--s4); }
@media (max-width: 900px) { .ct-luoi { grid-template-columns: 1fr; } }
.ct-o {
  background: var(--panel-2); border: 1px solid rgba(var(--lnR), .14);
  border-radius: 10px; padding: 16px 18px;
}
.ct-o p { margin: 0; font-size: 14.5px; line-height: 1.65; color: var(--ink-2); }
.ct-o .ct-k {
  display: flex; align-items: center; gap: 8px; margin: 0 0 8px;
  font: 650 14px var(--sans); color: var(--ink);
}
.ct-o .ct-k .li { width: 17px; height: 17px; color: var(--cobalt); }

/* 28d. Tiêu đề cột "Ngân hàng" canh TRÁI như chính cột của nó — mọi bảng.
   Luật chung canh phải cho th số đúng với mọi cột trừ cột định danh. */
#calc-table th:nth-child(2) { text-align: left; }

/* ═══ 29. Vòng craft 13/08 (review Codex/Grok) ═══════════════════════════ */
/* 29a. Thanh khoảng-cách-với-dẫn-đầu trong rankrow — trục CẮT 85–100% của
   mức dẫn đầu, nên chú thích trục nằm ở ghi chú cuối bảng (luật trục cắt). */
.rr-bar { grid-area: bar; display: block; height: 6px; border-radius: 4px;
  background: rgba(var(--lnR), .10); overflow: hidden; }
.rr-bar i { display: block; height: 100%; border-radius: 4px;
  background: var(--acGrad90); box-shadow: 0 0 12px rgba(var(--acR), var(--gb)); }
.rankrow { grid-template-areas: "pos who rate lai" "pos bar bar bar" "pos cond cond cond"; }
@supports not (grid-template-areas: "a") { .rr-bar { display: none; } }

/* 29b. Tooltip đường cong hai lớp — ba dòng THỊ TRƯỜNG / NIÊM YẾT / CHÊNH. */
.hc2-tip { position: absolute; pointer-events: none; z-index: 6;
  /* Mặc định nổi TRÊN điểm; điểm nằm nửa trên biểu đồ thì lật xuống DƯỚI
     (`.duoi`) — nếu không, hộp trồi khỏi mép trên khung và mất dòng đầu
     (lỗi 13/08 chiều: dòng "THỊ TRƯỜNG" bị cắt). */
  transform: translate(-50%, -112%); min-width: 168px;
  background: var(--panel); border: 1px solid rgba(var(--acR), .4);
  border-radius: 8px; padding: 10px 13px;
  box-shadow: 0 0 24px rgba(var(--acR), .18);
  font: 500 13.5px var(--mono); }
.hc2-tip p { margin: 0; display: flex; justify-content: space-between; gap: 16px; }
.hc2-tip .t { font-size: 12.5px; letter-spacing: .2em; color: var(--muted); margin-bottom: 7px; }
.hc2-tip .ks span:first-child { color: var(--cobalt); }
.hc2-tip .ny span:first-child { color: var(--steel-line); }
.hc2-tip .ch { border-top: 1px solid rgba(var(--lnR), .15); padding-top: 5px; margin-top: 4px; }
.hc2-tip .ch span:last-child { color: var(--cobalt-strong); }
.hai-cong { position: relative; }
.hc2-tip.duoi { transform: translate(-50%, 14%); }
/* Sát mép trái/phải thì kéo hộp vào trong, khỏi tràn khung. */
.hc2-tip.trai { transform: translate(-6%, -112%); }
.hc2-tip.trai.duoi { transform: translate(-6%, 14%); }
.hc2-tip.phai { transform: translate(-94%, -112%); }
.hc2-tip.phai.duoi { transform: translate(-94%, 14%); }
.hc2-cross { stroke: rgba(var(--acR), .4); stroke-width: 1; }

/* 29c. Mobile hero — thiết kế riêng, không phải desktop thu nhỏ. */
@media (max-width: 720px) {
  .stage-bare { padding: 20px 0 26px; }
  /* Chip kỳ hạn: MỘT dòng cuộn ngang tràn mép, không gãy hai hàng. */
  .hero-ctl { flex-wrap: nowrap; overflow-x: auto; gap: 8px;
    margin-inline: calc(-1 * var(--gutter)); padding: 2px var(--gutter) 8px;
    -webkit-overflow-scrolling: touch; }
  .hero-ctl::-webkit-scrollbar { display: none; }
  .ky-chips { flex-wrap: nowrap; }
  .seg { flex: none; }
  /* Dòng nhãn: thôi giãn chữ dài — ở 390px nó gãy thành cột chữ dựng đứng. */
  .stage .hero-nhan { letter-spacing: .06em; font-size: 12.5px; margin-bottom: 4px; }
  .stage .hero-so .ck-num { font-size: clamp(64px, 21vw, 84px); }
  .hero-dv { font-size: 16px; }
  .hero-kpi { gap: 8px; }
  .kpi { padding: 12px 13px; }
  .kpi-v { font-size: 22px; }
  .kpi-k { margin-bottom: 6px; }
  .hero-tinh { padding: 12px 14px; }
  .hero-sosanh { font-size: 14px; }
}

/* 29d. Ticker tinh lại: chậm hơn, thoáng hơn, tăng/giảm rõ bằng mũi tên màu. */
.ticker-track { animation-duration: 60s; }
.ticker-set li { padding: 0 26px; gap: 10px; font-size: 12.5px; letter-spacing: .08em; }
.ticker .up::before { content: "▲ "; font-size: 12px; }
.ticker .down::before { content: "▼ "; font-size: 12px; }

/* 29e. Vật liệu bản sáng: hairline rõ + bóng hai lớp cho panel. */
:root[data-theme="light"] .card,
:root[data-theme="light"] .kpi,
:root[data-theme="light"] .hero-tinh,
:root[data-theme="light"] .hero-cong {
  border-color: rgba(30, 70, 150, .18);
  box-shadow: 0 1px 2px rgba(12, 27, 56, .05), 0 10px 28px -18px rgba(12, 27, 56, .18);
}

/* ═══ 30. Sơ đồ quy trình — làm lại (review 13/08: "đơn sơ, lộn xộn") ═════
   Nguyên nhân kỹ thuật của bản xấu: ba icon tự viết thiếu class="lucide" nên
   icon() không gắn được .li — chúng phình ra chiếm cả thẻ, thẻ 05–07 cao gấp
   đôi thẻ 01–04. Đã vá tận gốc ở file SVG; luật dưới đây là chốt an toàn +
   phần thiết kế lại: icon vào chip vuông tô màu, thẻ cao ĐỀU, mũi tên canh
   theo hàng chip. */
.wf li svg, .wf li .li { width: 20px; height: 20px; }
.wf-ic {
  width: 40px; height: 40px; border-radius: 10px; flex: none;
  display: grid; place-items: center;
  background: var(--cobalt-soft); color: var(--cobalt);
  border: 1px solid var(--seal-line);
  box-shadow: 0 0 14px rgba(var(--acR), var(--gb));
}
.wf li { grid-template-rows: auto auto auto 1fr; align-items: start; min-height: 132px; }
.wf li::after { top: 44px; transform: rotate(-90deg); }
.wf li:not(:last-child)::after { top: 46px; }

/* ═══ 31. Bản nhận định bớt "toàn chữ": sự kiện thành lưới thẻ ═══════════ */
.dukien {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px;
  list-style: none; margin: 0 0 var(--s4); padding: 0;
}
.dukien li {
  margin: 0; padding: 11px 14px; font-size: 15px; line-height: 1.6;
  background: var(--panel-2); border: 1px solid rgba(var(--lnR), .14);
  border-left: 3px solid var(--cobalt); border-radius: 8px;
}
.dukien li::marker { content: ""; }
@media (max-width: 760px) { .dukien { grid-template-columns: 1fr; } }

/* ═══ 32. Lưới phản ứng theo con trỏ (chốt 13/08 chiều) ══════════════════
   Chỉ còn MỘT lớp: tấm lưới cùng hoạ tiết nền nhưng tô bằng MÀU ACCENT, bịt
   mask tròn — lưới "thức dậy" quanh con trỏ rồi tắt dần. Vòng tâm + vạch
   ngấn của bản trước đã bỏ theo yêu cầu chủ dự án.

   JS bù `background-position` từng khung hình để vân tấm TRÙNG KHÍT lưới
   nền — thiếu bù là hai lớp lưới lệch nhau, lộ mẹo ngay. Bước lưới 44px phải
   khớp `body::before` và hằng O trong app.js.

   z-index 0: dưới mọi nội dung; vùng nội dung che nền thì tự biến mất.
   Chỉ con trỏ thật; tắt theo reduced-motion. */
.truc-luoi { display: none; }
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .truc-luoi {
    display: block; position: fixed; left: 0; top: 0; z-index: 0;
    pointer-events: none; opacity: 0; transition: opacity .35s ease;
    will-change: transform;
    width: 640px; height: 640px;
    /* Màu accent chứ không phải màu lưới nền: đây là chỗ "mạnh về thị giác"
       đến từ SẮC chứ không phải từ đậm đặc — tăng alpha lưới xám chỉ ra bẩn. */
    background-image:
      linear-gradient(rgba(var(--acR), .38) 1px, transparent 1px),
      linear-gradient(90deg, rgba(var(--acR), .38) 1px, transparent 1px);
    background-size: 44px 44px;
    -webkit-mask-image: radial-gradient(circle 300px at center, #000 0%, rgba(0,0,0,.8) 42%, transparent 70%);
    mask-image: radial-gradient(circle 300px at center, #000 0%, rgba(0,0,0,.8) 42%, transparent 70%);
  }
  body[data-truc] .truc-luoi { opacity: 1; }
}

/* ═══ 33. Cụm điều khiển trang công cụ — làm lại (13/08: "lộn xộn, khó bấm")
   Nguyên nhân: `.controls` gốc là lưới NHIỀU CỘT (sinh cho bộ lọc trang so
   sánh) nên các control ở đây xếp cạnh nhau — nhãn "CHỌN NHANH" trôi ra giữa
   hàng của ô nhập. Trang công cụ cần dạng FORM: một control một hàng, nhãn
   một cột thẳng, kẻ hairline giữa các hàng để mắt bám. */
.ctl-card { display: grid; grid-template-columns: 1fr; gap: 0;
  padding: 4px var(--s5); }
.ctl-card .control {
  display: grid; grid-template-columns: 176px minmax(0, 1fr);
  align-items: center; column-gap: var(--s5);
  padding: 14px 0; border-bottom: 1px solid var(--rule); margin: 0;
}
.ctl-card .control:last-of-type { border-bottom: 0; }
/* `display: grid` mạnh hơn thuộc tính [hidden] — nhóm "Cách trả lãi" ẩn ở
   lớp thị trường phải THẬT SỰ biến mất. */
.ctl-card .control[hidden] { display: none; }
.ctl-card .control > span:first-child { margin: 0; }
/* Ô nhập + chữ đọc số xếp dọc trong cột phải. */
.ctl-card .amount { margin: 0; }
.ctl-card .so-chu { grid-column: 2; margin-top: 2px; }
@media (max-width: 760px) {
  .ctl-card .control { grid-template-columns: 1fr; row-gap: 8px; padding: 12px 0; }
  .ctl-card .so-chu { grid-column: 1; }
}

/* ── 30. Khung tư vấn ─────────────────────────────────────────────── */
/* Nút nổi + khung hỏi đáp. Ba ràng buộc hình học, mỗi cái từ một chỗ có thể
   vỡ:

   1. TRÊN ĐIỆN THOẠI PHẢI NẰM TRÊN `.bottomnav`. Bottom nav hiện từ 640px trở
      xuống và `body` chừa 76px chân trang cho nó; nút nổi đặt ở `bottom: 16px`
      sẽ nằm ĐÈ lên tab "Nhận định". Đây là loại lỗi chỉ thấy ở khung hẹp, tức
      là đúng khung của phần lớn người đọc.
   2. Khung không cao quá màn hình. `max-height` tính theo `dvh` chứ không `vh`
      — trên Safari iOS thanh địa chỉ co giãn làm `vh` lớn hơn vùng nhìn thật,
      và ô nhập bị đẩy xuống dưới mép.
   3. Khung KHÔNG chặn trang (không `aria-modal`, không lớp phủ): người ta vừa
      hỏi vừa cuộn bảng phía sau, đó là cách một bảng so sánh được dùng thật. */

/* `column-reverse` chứ không `column`: nút nổi phải ở ĐÁY, khung mở LÊN TRÊN
   nó. Thứ tự trong DOM giữ nguyên nút-trước-khung vì đó là thứ tự đọc đúng
   cho bàn phím và trình đọc màn hình (bấm nút → vào khung), còn thứ tự nhìn
   thì đảo bằng CSS. */
/* `pointer-events: none` trên VỎ, `auto` trên hai con — vá 20/08/2026.
   Đo được: trên điện thoại `.tuvan` trải HẾT bề ngang (381×49px ở khổ 404) và
   trong suốt, nhưng vẫn nhận chuột. `elementFromPoint` ở x = 30, 100, 200, 300
   đều trả về `DIV.tuvan`. Nghĩa là ngay phía trên thanh điều hướng dưới có một
   vệt vô hình nuốt mọi cú chạm vào nội dung nằm dưới nó — trên MỌI trang, từ
   lúc khối tư vấn ra đời, không ai thấy vì nó không vẽ gì cả.
   Vỏ chỉ làm việc xếp chỗ; chỉ nút và khung chat mới đáng nhận thao tác. */
.tuvan { pointer-events: none; }
.tuvan > * { pointer-events: auto; }
.tuvan { position: fixed; right: var(--s4); bottom: var(--s4); z-index: 40;
  display: flex; flex-direction: column-reverse; align-items: flex-end;
  gap: var(--s2);

  /* Độ nổi riêng, KHÔNG dùng `--shadow-2`. Ở bản sáng biến đó là
     `0 1px 2px rgba(12,27,56,.05)` — đủ cho một thẻ nằm trong dòng chảy trang,
     nhưng một khung nổi màu trắng đặt trên nền #EEF2F9 với cái bóng đó thì
     tan vào trang: đo bằng ảnh chụp 390px, mép khung không nhận ra được.
     Khung nổi cần bóng của khung nổi. */
  --tv-noi: 0 12px 32px -8px rgba(12, 27, 56, .28), 0 2px 8px -2px rgba(12, 27, 56, .16);
}
:root:not([data-theme="light"]) .tuvan {
  /* Nền tối không đổ bóng được — bóng đen trên nền đen là vô hình. Ở đây độ
     nổi đến từ VIỀN SÁNG và một quầng sâu, cùng lối với `--shadow-1` của hệ. */
  --tv-noi: 0 24px 56px -20px #000, inset 0 1px 0 rgba(233, 240, 253, .06);
}

.tuvan-nut {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 10px var(--s4); border: 1px solid var(--rule-strong);
  border-radius: 999px; background: var(--surface); color: var(--ink);
  font: 600 15px var(--sans); cursor: pointer;
  box-shadow: var(--tv-noi);
}
.tuvan-nut:hover { border-color: var(--cobalt); color: var(--cobalt); }
.tuvan-nut svg { width: 18px; height: 18px; stroke: currentColor; fill: none; }

.tuvan-khung {
  display: flex; flex-direction: column;
  width: min(384px, calc(100vw - var(--s4) * 2));
  max-height: min(560px, calc(100dvh - 132px));
  background: var(--surface); border: 1px solid var(--rule-strong);
  border-radius: var(--r-lg); box-shadow: var(--tv-noi); overflow: hidden;
}
.tuvan-khung[hidden] { display: none; }

.tuvan-dau {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3); padding: var(--s3) var(--s4);
  background: var(--head); border-bottom: 1px solid var(--rule);
}
.tuvan-dau h2 { margin: 0; font: 650 16px var(--sans); color: var(--ink); }
.tuvan-x { border: 0; background: none; color: var(--muted);
  font-size: 16px; line-height: 1; padding: 6px; cursor: pointer;
  border-radius: var(--r-sm); }
.tuvan-x:hover { color: var(--ink); background: var(--surface-2); }

.tuvan-log { flex: 1; overflow-y: auto; padding: var(--s4);
  display: flex; flex-direction: column; gap: var(--s3); font-size: 15px; }
.tuvan-log p { margin: 0 0 6px; line-height: 1.6; }
.tuvan-log p:last-child { margin-bottom: 0; }
.tuvan-log ul { margin: 4px 0 8px; padding: 0; list-style: none; }
.tuvan-log li { padding: 5px 0; border-bottom: 1px solid var(--rule); }
.tuvan-log li:last-child { border-bottom: 0; }

.tv-tin { max-width: 100%; }
.tv-nguoi { align-self: flex-end; max-width: 85%;
  background: var(--stage-2); border: 1px solid var(--rule);
  border-radius: var(--r) var(--r) 2px var(--r); padding: 8px var(--s3); }
.tv-bot { align-self: stretch; }

/* Con số là thứ người đọc quét trước — cùng font đo với bảng chính, không
   phải font chữ thường, để mắt nhận ra ngay đây là dữ liệu. */
.tv-so { font: 650 16px var(--mono); color: var(--ink); font-variant-numeric: tabular-nums; }
.tv-phu { color: var(--muted); font-size: 13.5px; }
.tv-lop { color: var(--muted); font: 600 12px var(--mono);
  letter-spacing: .1em; text-transform: uppercase; margin-top: var(--s2); }

/* Nhãn nguồn — amber, đúng màu "caveat và điều kiện" của hệ. Nó phải đứng
   NGAY CẠNH con số nó nói về, không dồn xuống cuối khối: một mức khảo sát bị
   tách khỏi nhãn của nó thì đọc y như một mức niêm yết. */
.tv-nhan { display: inline-block; margin-left: 6px; padding: 1px 6px;
  border-radius: var(--r-sm); background: var(--amber-soft); color: var(--amber);
  font: 600 12.5px var(--sans); white-space: nowrap; }
.tv-mien { color: var(--muted); font-size: 13px; line-height: 1.5;
  border-left: 2px solid var(--amber); padding-left: var(--s2); }

.tv-go { display: inline-block; width: 26px; height: 8px;
  background: radial-gradient(circle 3px at 4px 4px, var(--muted) 96%, transparent)
              0 0 / 11px 8px repeat-x;
  animation: tvGo 1s linear infinite; animation-play-state: var(--play, running); }
@keyframes tvGo { 50% { opacity: .35; } }

.tuvan-goi { display: flex; flex-wrap: wrap; gap: 6px;
  padding: 0 var(--s4) var(--s3); }
.tuvan-goi:empty { display: none; }
.tv-goi { border: 1px solid var(--rule-strong); background: none;
  color: var(--cobalt); border-radius: 999px; padding: 5px 11px;
  font: 500 13.5px var(--sans); cursor: pointer; }
.tv-goi:hover { background: var(--surface-2); }

.tuvan-nhap { display: flex; gap: var(--s2); padding: var(--s3) var(--s4);
  border-top: 1px solid var(--rule); }
.tuvan-nhap input {
  flex: 1; min-width: 0; padding: 9px var(--s3);
  border: 1px solid var(--rule-strong); border-radius: var(--r-sm);
  background: var(--bg); color: var(--ink); font: 400 15px var(--sans);
}
.tuvan-nhap button { border: 0; background: var(--cobalt-deep, var(--cobalt));
  color: #fff; border-radius: var(--r-sm); padding: 0 12px; cursor: pointer; }
.tuvan-nhap button svg { width: 18px; height: 18px; stroke: currentColor; fill: none; }

.tuvan-chan { margin: 0; padding: 0 var(--s4) var(--s3);
  color: var(--muted); font-size: 12.5px; }

/* Phiếu để lại nhu cầu. Ô đồng ý đứng ngay trên nút gửi và KHÔNG tick sẵn —
   luật này sống ở chat.js, chỗ này chỉ bảo đảm nó không bị lướt qua. */
.tv-form { display: grid; gap: var(--s2); margin-top: var(--s2); }
.tv-hang { display: grid; gap: 3px; font-size: 13.5px; color: var(--muted); }
.tv-hang input, .tv-hang select {
  padding: 8px var(--s3); border: 1px solid var(--rule-strong);
  border-radius: var(--r-sm); background: var(--bg); color: var(--ink);
  font: 400 15px var(--sans);
}
.tv-dongy { display: grid; grid-template-columns: auto 1fr; gap: var(--s2);
  align-items: start; font-size: 13px; line-height: 1.5; color: var(--muted);
  background: var(--surface-2); padding: var(--s3); border-radius: var(--r-sm);
  margin-top: var(--s2); }
.tv-dongy input { margin-top: 2px; width: 16px; height: 16px; }
.tv-loi { color: var(--amber); font-size: 13.5px; }
.tv-loi:empty { display: none; }

@media (max-width: 640px) {
  /* 76px chân trang cho bottom nav + khoảng thở. Đọc từ cùng con số đã dùng
     ở `body { padding-bottom }` — hai chỗ lệch nhau là nút đè lên tab. */
  .tuvan { right: var(--s3); left: var(--s3); bottom: calc(76px + var(--s2));
    align-items: flex-end; }
  .tuvan-khung { width: 100%; max-height: calc(100dvh - 76px - 96px); }
  /* Nút gọi thu về TRÒN CHỈ ICON: pill chữ ~150px nằm đè lên chip "5 tỷ"
     của hero ngay màn đầu (ảnh chủ dự án 13/08 tối). Tên nút chuyển cho
     aria-label ở template — không mất tên với trình đọc màn hình. */
  .tuvan-nut span { display: none; }
  .tuvan-nut { padding: 13px; }
  .tuvan-nut svg { width: 21px; height: 21px; }
}

/* Nút Zalo — hành động chính khi khung chat đã hết việc tự làm được.
   Xanh cobalt đặc chứ không viền rỗng như chip gợi ý: ở đây chỉ có MỘT việc
   đáng làm tiếp, và nó phải khác hẳn về sức nặng so với bốn gợi ý bên cạnh. */
.tv-zalo {
  display: inline-flex; align-items: center; gap: 6px; margin-top: var(--s2);
  padding: 9px var(--s4); border-radius: 999px;
  background: var(--cobalt-deep); color: #fff; text-decoration: none;
  font: 650 14.5px var(--sans);
}
.tv-zalo::before { content: "◈"; font-size: 12px; opacity: .85; }
.tv-zalo:hover { filter: brightness(1.08); }
.tv-zalo:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 2px; }

/* Bản in: khung tư vấn là công cụ, không phải nội dung. */
@media print { .tuvan { display: none; } }

/* ═══ 34. Quy tắc 13/08 (đợt hai) ════════════════════════════════════════ */
/* Logo trong dải ticker và rail nguồn — ô nhỏ cùng khuôn bank-logo. */
.tk-logo { width: 16px; height: 16px; border-radius: 4px; flex: none;
  object-fit: contain; background: var(--chip-bg);
  border: 1px solid rgba(var(--lnR), .25); padding: 1px; }
.ri-logo { width: 18px; height: 18px; border-radius: 5px; padding: 1px;
  margin-right: 6px; vertical-align: -4px; }
.ticker-set li .bank-name { font-weight: 650; font-size: 13px; }

/* Thân trang tĩnh dùng khung rộng: cột chữ tự giới hạn, lưới thẻ trải hết. */
.prose-rong { max-width: none; }
.prose-rong > p, .prose-rong > ul { max-width: 70ch; }
.prose-rong h2 { max-width: none; }

/* Căn đều hai lề cho MỌI đoạn văn (chốt 13/08 — "mang tính chuyên nghiệp").
   Chỉ ĐOẠN VĂN: nhãn, ô số, hàng bảng là chữ một dòng, justify không đổi gì
   nên không cần loại trừ từng cái. `text-wrap: pretty` giảm dòng mồ côi. */
p, .dukien li, .prose li {
  text-align: justify; text-justify: inter-word; text-wrap: pretty;
}
/* Trừ: đoạn đứng trong ô hẹp cạnh số — justify cột hẹp sinh sông trắng. */
.kpi-s, .st-s, .chart-note, .kicker, .hero-nhan, .ticker-set li span,
.head-live, .head-clock { text-align: left; }

/* ═══ 35. Nhật ký biến động + banner công cụ (file thiết kế 13/08) ════════ */
.nk-tom { margin-left: auto; font: 600 12.5px var(--mono); letter-spacing: .08em;
  white-space: nowrap; }
.nk-tom .up { color: var(--emerald); } .nk-tom .down { color: var(--warn); }
.nk-tom i { font-style: normal; color: var(--faint); margin: 0 4px; }
.delta-list { list-style: none; margin: 0; padding: 0; }
/* Làm kĩ 14/08 (ảnh 00:03): mũi tên nhập vào HUY HIỆU delta nên lưới còn
   NĂM cột — ngày · tên · huy hiệu · kỳ hạn · thị trường. Cột 16px đứng lẻ
   giữa ngày và tên chính là chỗ làm cả khối trông rời rạc trên điện thoại. */
.delta-list li {
  display: grid; align-items: center; gap: var(--s2) var(--s4);
  grid-template-columns: 46px minmax(0, 1.3fr) auto minmax(0, 1.2fr) auto;
  padding: 12px 4px; border-bottom: 1px solid var(--rule);
  transition: background-color var(--t-mau) ease;
}
.delta-list li:last-child { border-bottom: 0; }
@media (hover: hover) and (pointer: fine) {
  .delta-list li:hover { background: rgba(var(--acR), .045); }
}
.nk-ngay { font: 500 13px var(--mono); color: var(--faint); }
/* Huy hiệu đổi mức: mũi tên + số + ĐƠN VỊ THẬT ("điểm" phần trăm — bản cũ in
   "đ" là ký hiệu tiền đồng, sai nghĩa) trong một viên nang xanh/đỏ nhạt. */
.nk-delta {
  font: 600 13.5px var(--mono); font-variant-numeric: tabular-nums;
  padding: 4px 11px; border-radius: 999px; white-space: nowrap;
  justify-self: start;
}
.nk-delta.up { color: var(--emerald); background: rgba(var(--upR), .12);
  border: 1px solid rgba(var(--upR), .38); }
.nk-delta.down { color: var(--warn); background: rgba(var(--dnR), .10);
  border: 1px solid rgba(var(--dnR), .38); }
.delta-ky { font: 500 14px var(--mono); color: var(--ink-2); }
.delta-ky i { font-style: normal; color: var(--faint); margin-left: 6px; }
.delta-ky .chenh-ky { margin-left: 0; vertical-align: 1px; }
.delta-chao { justify-self: end; text-align: right; font: 500 13.5px var(--mono); }
.delta-chao b { color: var(--cobalt-strong); font-weight: 600; }
.delta-chao .na { color: var(--faint); }
@media (max-width: 760px) {
  /* Hai tầng gọn: tên + huy hiệu ở tầng nhìn đầu, ngày · kỳ hạn · thị trường
     xuống tầng chú thích — hết rãnh ngày dựng đứng ôm hai hàng. */
  .delta-list li {
    grid-template-areas: "who who delta" "ngay ky chao";
    grid-template-columns: auto minmax(0, 1fr) auto; row-gap: 7px;
  }
  .nk-ngay { grid-area: ngay; align-self: center; }
  .delta-who { grid-area: who; }
  .nk-delta { grid-area: delta; justify-self: end; }
  .delta-ky { grid-area: ky; } .delta-chao { grid-area: chao; }
}

.tool-banner {
  display: flex; align-items: center; gap: var(--s5); flex-wrap: wrap;
  padding: 26px 28px;
  background: linear-gradient(115deg, rgba(var(--cbR), .10), rgba(var(--acR), .04));
  border: 1px solid rgba(var(--acR), .3);
}
.tb-k { margin: 0 0 8px; font: 600 12px var(--mono); letter-spacing: .22em;
  text-transform: uppercase; color: var(--cobalt-strong); }
.tb-ct { margin: 0; font: 700 clamp(19px, 2.2vw, 24px)/1.3 var(--sans);
  letter-spacing: -.015em; color: var(--ink); }
.tb-s { margin: 6px 0 0; font-size: 14.5px; color: var(--ink-2); max-width: 60ch; }
.tool-banner > div { flex: 1; min-width: 260px; }
.tb-btn { flex: none; font: 600 14px var(--mono); letter-spacing: .1em;
  text-transform: uppercase; border-radius: 9px; padding: 14px 22px; }

/* ═══ 36. Card phản ứng khi rê — TOÀN WEB (13/08: "card không tương tác") ══
   Mọi mặt panel sáng lên bằng VIỀN + QUẦNG, không đổi nền — đổi nền cả card
   sẽ đè lên hover của từng hàng bên trong. Chỉ con trỏ thật. */
.card, .kpi, .ct-o, .wf li, .ans, .hero-tinh, .tool-banner, .hero-cong {
  transition: border-color var(--t-mau) ease, box-shadow var(--t-mau) ease,
    background-color var(--t-mau) ease, transform var(--t-vua) var(--ease-vao);
}
@media (hover: hover) and (pointer: fine) {
  .card:hover, .kpi:hover, .ct-o:hover, .wf li:hover, .ans:hover,
  .hero-tinh:hover, .tool-banner:hover, .hero-cong:hover {
    border-color: rgba(var(--acR), .45);
    box-shadow: 0 0 0 1px rgba(var(--acR), .18), 0 8px 28px -14px rgba(var(--acR), .35);
  }
}

/* Luật hover mục 36 thua luật vật liệu bản sáng (mục 29e mang tiền tố
   :root[data-theme=light] — độ cụ thể 0,3,0 so với 0,2,0): trên bản sáng
   card không phản ứng gì. Nhắc lại hover Ở CÙNG TẦNG cụ thể. */
@media (hover: hover) and (pointer: fine) {
  :root[data-theme="light"] .card:hover, :root[data-theme="light"] .kpi:hover,
  :root[data-theme="light"] .ct-o:hover, :root[data-theme="light"] .wf li:hover,
  :root[data-theme="light"] .ans:hover, :root[data-theme="light"] .hero-tinh:hover,
  :root[data-theme="light"] .tool-banner:hover, :root[data-theme="light"] .hero-cong:hover {
    border-color: rgba(var(--acR), .5);
    box-shadow: 0 0 0 1px rgba(var(--acR), .16), 0 10px 30px -14px rgba(var(--acR), .3);
  }
}

/* ═══ 37. Nền hover của PANEL NGOÀI CÙNG phải ĐỤC ════════════════════════
   Đây là nguyên nhân thật của "rê chuột vào ô là lộ lưới" (13/08 chiều):
   luật hover cũ đặt `background: rgba(accent, .045)` — nền TRONG SUỐT 4,5%
   THAY THẾ mặt panel đục, nên lưới phản ứng ở z:0 xuyên thẳng qua.

   Hàng trong bảng thì không sao (chúng nằm trên `.card` đục nên nền trong
   suốt vẫn có mặt đục đỡ phía sau) — chỉ panel NGOÀI CÙNG mới lộ nền trang.
   Cách đúng: TRỘN sắc accent vào chính màu panel, giữ độ đục. */
@media (hover: hover) and (pointer: fine) {
  .kpi:hover, .hero-tinh:hover, .ct-o:hover, .wf li:hover, .ans:hover,
  .tool-banner:hover, .card:hover, .hero-cong:hover {
    background: color-mix(in srgb, var(--panel) 95%, var(--cobalt));
  }
  /* Trình duyệt không có color-mix: giữ nguyên nền panel, chiều sâu vẫn còn
     ở viền và quầng — thà mất một chút phản hồi còn hơn lộ lưới. */
  @supports not (background: color-mix(in srgb, red 50%, blue)) {
    .kpi:hover, .hero-tinh:hover, .ct-o:hover, .wf li:hover, .ans:hover,
    .tool-banner:hover, .card:hover, .hero-cong:hover { background: var(--panel); }
  }
  /* Banner công cụ có nền gradient riêng — trộn sẽ nuốt mất nó. */
  .tool-banner:hover {
    background: linear-gradient(115deg, rgba(var(--cbR), .14), rgba(var(--acR), .06)),
      var(--panel);
  }
}

/* ═══ 38. Kỷ luật hover: sáng ĐÚNG phần tử được rê ═══════════════════════
   Lỗi 13/08 chiều: thẻ CHỨA bảng nhiều dòng cũng sáng lên, nên rê vào một
   hàng thì cả khối 5 hàng cùng sáng — mắt không biết đang trỏ vào đâu.

   Luật mới: chỉ thẻ LÁ (không chứa danh sách/bảng nào có hover riêng) mới
   được sáng. Thẻ chứa hàng thì hàng tự lo — dùng `:has()` để phân biệt,
   không phải liệt kê tay từng chỗ. */
@media (hover: hover) and (pointer: fine) {
  .card:has(.delta-list, .rank10, table, .ranklist, .rankrow, .gop-cards):hover,
  .hai-cong:hover, .hero-cong:hover, .tablewrap:hover {
    background: var(--panel);
    border-color: rgba(var(--lnR), .14);
    box-shadow: none;
  }
  /* Trình duyệt không có :has() — thà tắt hẳn hover thẻ còn hơn sáng cả khối. */
  @supports not selector(:has(a)) {
    .card:hover { background: var(--panel); border-color: rgba(var(--lnR), .14);
      box-shadow: none; }
  }
  /* Bản SÁNG: quầng dịu hơn hẳn — trên nền trắng nó chói hơn nhiều so với
     nền tối cùng một giá trị alpha (13/08: "dark thì đẹp, light khó chịu"). */
  :root[data-theme="light"] .kpi:hover, :root[data-theme="light"] .ct-o:hover,
  :root[data-theme="light"] .wf li:hover, :root[data-theme="light"] .ans:hover,
  :root[data-theme="light"] .hero-tinh:hover, :root[data-theme="light"] .tool-banner:hover {
    border-color: rgba(var(--acR), .32);
    box-shadow: 0 1px 2px rgba(12, 27, 56, .05), 0 6px 18px -12px rgba(var(--acR), .28);
  }
}

/* ═══ 39. Vùng chữ phụ đang quá nhạt (13/08 chiều) ═══════════════════════ */
/* Dữ kiện và diễn giải là NỘI DUNG, không phải chú thích — chúng đang dùng
   `--ink-2` như metadata. Trả về màu mực chính; chỉ nhãn mới nhạt. */
.dukien li { color: var(--ink); }
.reading > p:not(.rd-k) { color: var(--ink); }
.rd-k, .rail-k { color: var(--cobalt-strong); font-weight: 700; }

/* Ngăn kéo nguồn: mỗi mục là một THẺ có nền, không phải dòng trôi cạnh vạch
   kẻ — rê chuột vào mới có ranh giới rõ để mắt bám. */
.rail-item {
  padding: 11px 13px; margin-bottom: 10px; border-left: 0;
  background: var(--panel-2); border: 1px solid var(--rule);
  border-radius: 8px;
}
@media (hover: hover) and (pointer: fine) {
  .rail-item { transition: border-color var(--t-mau) ease, background-color var(--t-mau) ease; }
  .rail-item:hover { border-color: var(--seal-line);
    background: color-mix(in srgb, var(--panel-2) 94%, var(--cobalt)); }
}
.ri-t { font-size: 14.5px; }
.ri-n { font-size: 16px; margin-top: 2px; }
.ri-s { color: var(--muted); }

/* Khung miễn trừ/giới hạn: chữ đang trôi trên nền pha nên khó đọc. */
.scope-note, .limits p { color: var(--ink); }
.scope-note { border-left-width: 4px; }
.limits .lim-k { color: var(--amber); }

/* Luật "không sáng khối chứa" (mục 38) có độ cụ thể 0,2,0, thua luật vật
   liệu bản sáng `:root[data-theme=light] .card:hover` (0,3,0) — nên trên bản
   sáng khối chứa vẫn sáng. Nhắc lại Ở CÙNG TẦNG. Cùng họ lỗi với vụ hover
   bị nuốt hôm nay: sửa bằng độ cụ thể, không bằng !important. */
@media (hover: hover) and (pointer: fine) {
  :root[data-theme="light"] .card:has(.delta-list, .rank10, table, .ranklist, .rankrow, .gop-cards):hover,
  :root[data-theme="light"] .hai-cong:hover,
  :root[data-theme="light"] .hero-cong:hover,
  :root[data-theme="light"] .tablewrap:hover,
  :root[data-theme="dark"] .card:has(.delta-list, .rank10, table, .ranklist, .rankrow, .gop-cards):hover {
    background: var(--panel);
    border-color: rgba(var(--lnR), .14);
    box-shadow: none;
  }
}

/* ═══ 40. Mobile vỡ toàn trang — hai gốc, hai dòng chữa (13/08 tối) ═══════
   1. Hàng chip cuộn ngang là ITEM trong cột dọc nên `min-width: auto` =
      max-content 773px — nó NỞ cả layout viewport lên 765px, mọi thứ khác
      chỉ là nạn nhân (Chrome Android/emulation nở viewport theo min-content).
      `overflow-x: auto` không cứu được vì min-width mới là thứ quyết định.
   2. Ngăn kéo biên nhận trên trang ngân hàng: cột mô tả bị bóp <130px, chữ
      vỡ từng từ — cho lưới về một cột ở khung hẹp. */
.hero-ctl { min-width: 0; max-width: 100%; }
.stage-ans > * { min-width: 0; }
@media (max-width: 720px) {
  /* dl chứa dt/dd TRỰC TIẾP (không có div bọc) — selector bản đầu trật cấu
     trúc nên không ăn. Về một cột: nhãn trên, giá trị dưới, hết cột 130px
     vỡ chữ từng từ. */
  .receipt-body dl, .ngan-dl > div { grid-template-columns: 1fr; gap: 2px var(--s3); }
  .receipt-body dt { margin-top: 6px; }
  .receipt-body dt:first-child { margin-top: 0; }
  /* Bảng nhiều cột trong .scroller: đặt SÀN bề rộng để cột không bị nghiền
     nát thành cột chữ dọc — thà cuộn ngang (đúng vai trò .scroller) còn hơn
     mỗi ô một cột chữ 100px. */
  .scroller table { min-width: 560px; }
}

/* ═══ 41. Trao giải thay thanh ngang (13/08 tối) ══════════════════════════
   Thanh ngang trục-cắt đã bỏ ở CẢ Top 5 lẫn rankrow — chủ dự án chấm "xấu và
   vô nghĩa" trên cả hai khung. Thứ bậc nay nói bằng HUY HIỆU RANK: hạng 1
   gradient accent + quầng, 2–3 nền soft, còn lại viền trơn. */
.rank-tag {
  display: inline-flex; align-items: center; white-space: nowrap;
  font: 700 12.5px var(--mono); letter-spacing: .1em;
  padding: 4px 9px; border-radius: 7px;
  border: 1px solid var(--rule-strong); color: var(--muted);
  background: var(--panel-2);
}
.rank-tag.r1 {
  background: var(--acGrad); border-color: transparent; color: var(--on-accent);
  box-shadow: 0 0 14px rgba(var(--acR), var(--gb));
}
.rank-tag.r23 {
  background: var(--cobalt-soft); border-color: var(--seal-line); color: var(--cobalt-strong);
}
/* Hạng 1 của Top 5: cả HÀNG được nâng — podium, không chỉ cái tag. */
.rank-ks li:first-child, .rankrow:has(.rank-tag.r1) {
  background: color-mix(in srgb, var(--panel) 96%, var(--cobalt));
}
/* Lưới hàng sau khi bỏ thanh: tag · tên · mức · lãi. */
.rank-ks li {
  grid-template-areas: "stt who rate lai" "stt ny rate lai";
  grid-template-columns: 84px minmax(0, 1fr) 118px 150px;
}
/* Tag trong ranklist /so-sanh/ phải NHẬN vùng "pos" — không khai thì lưới
   auto-place nó vào rãnh 34px của số thứ tự cũ: pill 64px tràn khỏi rãnh, đè
   lên logo và cắt mất số hạng (ảnh chủ dự án 13/08 tối). Rãnh nới sang auto
   vì pill rộng hơn con số nó thay thế. */
@media (min-width: 901px) {
  .ranklist-luon .rankrow { grid-template-columns: auto minmax(0, 1fr) 92px 186px 196px; }
}
.rankrow .rank-tag { grid-area: pos; align-self: start; justify-self: start; margin-top: 5px; }
.rank10 li::before { content: none; }   /* số thứ tự cũ — tag đã nói thay */
.rankrow .pos { display: none; }
/* Dọn luật thanh cũ (giữ chọn lọc: .r10-bar còn dùng ở thang trang kỳ hạn?
   — không: xoá element rồi, luật thành mồ côi vô hại nhưng tắt glow cũ). */
.r10-bar, .rr-bar { display: none; }

/* ═══ 42. Mobile: Top 5 + bảng chênh + hero (ảnh 5383/5384/5385) ═════════ */
@media (max-width: 760px) {
  /* Top 5: hàng hai tầng — tầng 1 tag+tên+mức, tầng 2 chip đối chiếu TRỌN
     BỀ NGANG (hết pill dựng đứng đè lên tên như ảnh 5383). */
  .rank-ks li {
    grid-template-areas: "stt who rate" "ny ny ny";
    grid-template-columns: auto minmax(0, 1fr) auto; row-gap: 8px;
  }
  .rank-ks .r10-ny { white-space: normal; justify-self: start; }
  .r10-lai { display: none; }   /* tiền lãi đã có ở hero + công cụ */
  /* Hero: công tắc lớp xuống HÀNG RIÊNG, chip kỳ hạn chiếm trọn dòng cuộn
     — hết cảnh chỉ thấy 1T/3T mà không biết kỳ hạn nào đang chọn. */
  .hero-ctl { flex-wrap: wrap; overflow-x: visible; margin-inline: 0; padding: 0 0 6px; }
  /* KHÔNG kéo âm ra mép nữa: biên kéo phải khớp đệm wrap từng khung — đệm
     mobile đổi 16→8px (13/08 tối) là hàng chip lòi 8px và cả trang tràn
     ngang. Hàng cuộn trong lòng cột là đủ, không cần full-bleed. */
  .ky-chips { flex: 1 1 100%; overflow-x: auto; flex-wrap: nowrap;
    margin-inline: 0; padding: 2px 0 6px;
    -webkit-overflow-scrolling: touch; }
  .ky-chips::-webkit-scrollbar { display: none; }
  .seg { margin-left: 0; }
  /* Bảng chênh: mỗi hàng thành thẻ ba tầng, nhãn lớp in NGAY TRONG ô —
     hết cảnh tiêu đề cột rơi chữ "CHÊNH" mồ côi và chip +2,6 trôi nổi.
     Tầng cuối là Ghi chú (điều kiện) — cột mới 13/08 tối. */
  /* li.chenh-head: `.chenh-list li` (0,1,1) đè `.chenh-head` (0,1,0) —
     display:none thua về ĐẶC HIỆU nên header vẫn hiện trên điện thoại
     (ảnh chủ dự án 23:17). Cùng bài học specificity với hover light. */
  .chenh-list li.chenh-head { display: none; }
  .chenh-list li {
    grid-template-areas: "who who" "ny ks" "ghi ghi";
    grid-template-columns: 1fr 1fr; row-gap: 6px;
  }
  .chenh-who { grid-area: who; }
  .chenh-ny { grid-area: ny; text-align: left; }
  .chenh-ks { grid-area: ks; }
  .chenh-ghi { grid-area: ghi; }
  .chenh-ny::before, .chenh-ks::before {
    display: block; font: 600 12px var(--mono); letter-spacing: .14em;
    text-transform: uppercase; margin-bottom: 2px;
  }
  .chenh-ny::before { content: "Niêm yết"; color: var(--steel); }
  .chenh-ks::before { content: "Thị trường"; color: var(--cobalt); }
}
/* Nhấn lớp ở MỌI khung (13/08 tối: "nhấn mạnh chữ niêm yết và thị trường"):
   tiêu đề cột mang màu ĐÚNG LỚP — thép cho biểu, accent cho thị trường. */
.chenh-head span:nth-child(3) { color: var(--cobalt); font-weight: 700; }
.chenh-ks b { color: var(--cobalt-strong); }
/* Chữ "niêm yết" ĐẬM và SÁNG RỰC ở mọi nơi nó làm nhãn lớp (chốt 13/08 tối:
   "in đậm để người xem biết đây là niêm yết. in đậm và sáng rực lên") —
   ngoại lệ CÓ CHỦ ĐÍCH với luật VOLT "niêm yết không quầng": quầng ở đây nằm
   trên NHÃN chữ để gọi tên lớp, không nằm trên con số/đường số liệu. */
.ny-manh, .chenh-head span:nth-child(2), .chenh-ny::before, .sg-ny .sg-k {
  color: var(--steel); font-weight: 800;
}
/* Tên ngân hàng đứng TRONG heading/dòng phụ thừa kế cỡ chữ của chỗ nó đứng —
   `.bank-name` khai 15px cho ngữ cảnh bảng, để nguyên thì tít "Lãi suất
   ABBANK" có chữ ABBANK teo lại giữa câu (rà nguyên tắc 2, 13/08 tối). */
h1 .bank-name, .section-head h2 .bank-name, .sub .bank-name {
  font-size: inherit; font-weight: inherit;
}
/* Quầng CHỈ trên nền tối: bóng 3px cùng màu chữ trên nền sáng bị axe tính là
   "nền" của glyph → tỉ lệ 1:1, trượt AA (đo 13/08 tối, 6 nút). Nền tối quầng
   là ánh sáng phát ra, nền sáng độ "rực" đến từ mực đậm 800. */
:root:not([data-theme="light"]) .ny-manh,
:root:not([data-theme="light"]) .chenh-head span:nth-child(2),
:root:not([data-theme="light"]) .chenh-ny::before,
:root:not([data-theme="light"]) .sg-ny .sg-k {
  text-shadow: 0 0 14px rgba(var(--stR), .65);
}

/* Tag trong Top 5 đứng ở rãnh "stt" của lưới sẵn có. */
.rank-ks .rank-tag { grid-area: stt; justify-self: start; align-self: center; }

/* Sparkline trong Top 5 ở khung hẹp: vắt qua cột số (ảnh RANK 1 — nét gạch
   đè lên "9,60"). 64px không đọc được gì trên điện thoại — ẩn; desktop giữ. */
@media (max-width: 760px) { .rank-ks .spark { display: none; } }

/* Sparkline bị GIAM trong cột tên: hàng RANK 1 tên dài là nét gạch tràn sang
   cột số, đọc như "9,60 bị gạch bỏ" (chủ dự án bắt 13/08 tối). Cột tên thành
   flex có overflow ẩn — spark hết đường vắt; thiếu chỗ thì nó bị cắt trước,
   tên và số không bao giờ bị đè. */
.rank-ks .r10-who {
  display: flex; align-items: center; gap: 8px;
  min-width: 0; overflow: hidden;
}
.rank-ks .spark { flex: none; }

/* ═══ 42. So găng ngân hàng (/so-sanh/) ═══════════════════════════════
   Tối đa 4 thẻ đứng cạnh nhau, mỗi thẻ hai ô lớp nguồn: niêm yết tông THÉP,
   thị trường tông ACCENT — đúng bảng màu lớp của cả hệ (mục 41, .chenh-*).
   Thẻ dựng bằng JS nhưng chỉ dùng token sẵn có; không token mới. */
.sg-goi-y { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s2); max-width: 560px; }
.sg-goi-y button {
  font: 500 14.5px var(--sans); padding: 6px 12px; background: var(--surface);
  border: 1px solid var(--rule-strong); border-radius: 999px; cursor: pointer;
  color: var(--ink-2);
  transition: background-color var(--t-mau) ease, color var(--t-mau) ease,
    border-color var(--t-mau) ease, transform var(--t-vua) var(--ease-vao);
}
.sg-goi-y button small { color: var(--muted); font-size: 12px; margin-left: 6px; }
@media (hover: hover) and (pointer: fine) {
  .sg-goi-y button:hover { background: var(--cobalt-soft); color: var(--cobalt); border-color: var(--seal-line); }
}
.sg-goi-y button:active { transform: translateY(1px) scale(.97); }

/* Chip ngân hàng ĐÃ CHỌN — tên mang màu thương hiệu như mọi nơi khác. */
.sg-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font: 600 14.5px var(--sans); padding: 4px 5px 4px 10px;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: var(--surface); color: var(--mau-bank-toi, var(--ink));
}
:root[data-theme="light"] .sg-chip { color: var(--mau-bank, var(--ink)); }
.sg-chip .bank-logo { width: 20px; height: 20px; }
.sg-chip button {
  font: 600 16px/1 var(--sans); width: 26px; height: 26px; border-radius: 50%;
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  transition: background-color var(--t-mau) ease, color var(--t-mau) ease,
    transform var(--t-vua) var(--ease-vao);
}
@media (hover: hover) and (pointer: fine) {
  .sg-chip button:hover { background: var(--warn-soft); color: var(--warn); }
}
.sg-chip button:active { transform: scale(.9); }

.sg-luoi {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--s3); margin-top: var(--s5); align-items: stretch;
}
.sg-the {
  display: flex; flex-direction: column; gap: var(--s3);
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: var(--r); padding: var(--s4); min-width: 0;
  box-shadow: var(--shadow-1);
}
.sg-dau { display: grid; gap: 2px; min-width: 0; }
.sg-dau .bank-name { font-size: 16px; }
.sg-o {
  display: grid; gap: 3px; align-content: start;
  padding: var(--s3); border: 1px solid var(--rule);
  border-radius: var(--r-sm); background: var(--panel-2);
}
/* Ô thị trường nở hết phần dư để 4 thẻ bằng đáy nhau. */
.sg-the .sg-tt { flex: 1; }
.sg-k {
  display: flex; align-items: center; gap: 6px;
  font: 600 12.5px var(--mono); letter-spacing: .1em; text-transform: uppercase;
}
.sg-ny .sg-k { color: var(--steel); }
.sg-tt .sg-k { color: var(--cobalt); }
.sg-so {
  font: 700 24px/1.15 var(--sans); letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.sg-so i { font: 500 13px var(--mono); font-style: normal; letter-spacing: 0; color: var(--muted); margin-left: 4px; }
.sg-ny .sg-so { color: var(--steel); }
.sg-tt .sg-so { color: var(--cobalt-strong); }
.sg-lai { font: 600 14.5px var(--mono); color: var(--ink-2); }
.sg-caveat { font: 500 13px/1.5 var(--sans); color: var(--amber); }
/* Bên thắng chỉ tiêu — cùng cách nâng nền với podium Top 5 (mục 41). */
.sg-thang {
  border-color: var(--seal-line);
  background: color-mix(in srgb, var(--panel-2) 94%, var(--cobalt));
}
@media (max-width: 760px) {
  .sg-luoi { grid-template-columns: 1fr; }
}

/* ── 46. Nút chuyển ngôn ngữ ──────────────────────────────────────────
   HAI LINK "VI | EN" trong `.head-sys`, đứng cạnh công tắc sáng/tối và cùng
   ngôn ngữ hình với nó: viên nang bo tròn hết cỡ, VIỀN 2px, chữ mono đậm.
   Hai điều khiển hệ thống cạnh nhau mà một cái là viên nang có viền còn cái
   kia là chữ trơn thì cái chữ trơn đọc thành một mẩu văn bản, không phải nút.

   Không phải nút bấm JS mà là hai `<a>` trỏ sang đúng trang của ngôn ngữ kia
   (xem base.html) — nên ở đây không có trạng thái `hidden` như `.nut-theme`:
   nó chạy cả khi tắt JS, và phải hiện ngay từ HTML máy chủ.

   Ngôn ngữ ĐANG XEM (`.on` + `aria-current="page"`) lấy nền đặc, không chỉ
   đậm chữ: phân biệt bằng độ đậm font thì ở 12px gần như không thấy, và
   người không phân biệt được màu cũng không đọc ra. */
.nut-lang {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 2px; border-radius: 999px;
  border: 2px solid rgba(var(--cbR), .55);
  background: var(--cobalt-soft);
  box-shadow: 0 0 14px rgba(var(--cbR), .18), inset 0 1px 2px rgba(12, 27, 56, .10);
  transition: border-color var(--t-mau) ease, box-shadow var(--t-mau) ease;
}
.nut-lang a {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 30px; height: 24px; padding: 0 8px; border-radius: 999px;
  font: 700 12.5px var(--mono); letter-spacing: .1em;
  color: var(--muted); text-decoration: none;
  transition: color var(--t-mau) ease, background var(--t-mau) ease;
}
/* Ngôn ngữ đang xem — cùng nền gradient với núm của công tắc chủ đề, nên hai
   điều khiển nói "đang bật" bằng CÙNG một tín hiệu. */
.nut-lang a.on {
  background: var(--acGrad); color: var(--on-accent);
  box-shadow: 0 2px 6px rgba(12, 27, 56, .35);
}
@media (hover: hover) and (pointer: fine) {
  .nut-lang:hover {
    border-color: var(--cobalt); box-shadow: 0 0 20px rgba(var(--cbR), .38);
  }
  .nut-lang a:not(.on):hover { color: var(--ink); }
}
.nut-lang a:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 2px; }
/* Khung hẹp: giữ nguyên viên nang, chỉ bóp đệm — đây là đường DUY NHẤT sang
   bản ngôn ngữ kia trên điện thoại (bottom nav không chở nổi thêm một tab). */
@media (max-width: 1360px) {
  .nut-lang a { min-width: 28px; padding: 0 7px; height: 23px; }
}
@media (max-width: 560px) {
  .nut-lang a { min-width: 26px; padding: 0 6px; height: 22px; font-size: 11.5px; }
}

/* Nút ngôn ngữ ăn 77px của thanh đầu trang, và ở 1280 thanh đó vốn đã vừa
   khít: đo được ngay sau khi cắm nút vào — "Phương pháp" bị cắt còn "Phươn"
   trên CẢ hai bản ngôn ngữ. Thứ nhường chỗ là ĐỒNG HỒ, theo đúng luật đã
   dùng ở khung 560px (mục 24d): đồng hồ là trang trí (`aria-hidden`, chỉ
   chạy khi có JS), còn mốc BẢN CHỐT cạnh nó là bằng chứng độ tươi của dữ
   liệu — hai thứ không cùng hạng, nên khi hết chỗ thì bỏ thứ nhẹ hơn.
   Mốc 1360px trùng đúng mốc mà nav đã phải bóp đệm (mục 24b). */
/* Đệm nav gọn ở MỌI bề rộng, không chỉ dưới 1360px (mục 24b đang khai luật
   này trong một media query — luật ở đây phủ lên nó, cố ý, và luật kia giữ
   nguyên để lịch sử quyết định còn đọc được).

   Lý do: `.wrap` chốt 1320px, nên trên 1360px thanh đầu trang KHÔNG rộng
   thêm một pixel nào — màn 1920 và màn 1400 có đúng cùng chỗ trống. Nút ngôn
   ngữ ăn 77px của khoảng đó, và đo ở 1320px cho thấy thiếu 87px: "Phương
   pháp" cụt còn "Phươn" trên cả hai bản. Bóp đệm nav lấy lại 62px, nhãn đồng
   hồ rút còn "VN" (app.js) lấy nốt 36px. */
.site-head nav a, .site-head nav span { padding: 6px 6px; letter-spacing: .01em; }
.head-top { gap: 10px 12px; }
.head-sys { gap: 9px; }
/* Dưới 1360px thì `.wrap` hẹp hơn 1320 và hai khoản trên KHÔNG đủ nữa (đo ở
   1280: còn thiếu 19px). Thứ nhường chỗ là ĐỒNG HỒ, theo đúng luật đã dùng ở
   khung 560px (mục 24d): nó là trang trí — `aria-hidden`, chỉ chạy khi có JS
   — còn mốc BẢN CHỐT cạnh nó là bằng chứng độ tươi của dữ liệu. Mốc 1360px
   lấy lại đúng mốc nav đã phải bóp đệm ở mục 24b, không đẻ thêm số lạ. */
@media (max-width: 1360px) {
  .head-clock { display: none; }
}

/* Nhãn "sắp có" của mục điều hướng chưa dựng nằm trong `content` của CSS
   (mục 3a), nên nó KHÔNG đi qua tầng dịch được — chữ trong CSS thì Jinja
   không thấy. Chữa ở đúng nơi nó sống, chọn theo `<html lang>`. Đây là chỗ
   ba chỗ của cả tệp có chữ cho người đọc (nhãn "sắp có", tít khối nhận định,
   nhãn ô quảng cáo); thêm chữ vào `content` sau này thì phải thêm một luật ở
   đây, cạnh chúng. */
html[lang="en"] .site-head nav span::after { content: "soon"; }
html[lang="en"] .notes::before { content: "Analysis"; }
html[lang="en"] .ad::before { content: "Sponsored"; }

/* ═══ 47. Mục Đăng tin và Góc kết nối ════════════════════════════════════
   Khối MỚI, nên luật ở đây chỉ nói về lớp mới (`.dt-*`, `.kn-*`, `.nav-dt`).
   Không đổi token, không đổi bảng màu, không sửa luật của khối cũ — bốn trang
   này mượn nguyên hệ đang chạy: `.wrap-narrow` cho cột đọc, `.ct-o` cho thẻ
   giải thích, `.btn`/`.btn-ghost` cho hành động, `.scroller` cho bảng.

   Một biểu mẫu là khối duy nhất của cả site mà người đọc GÕ vào, nên nó có
   hai đòi hỏi riêng, và cả hai đều là lý do kỹ thuật chứ không phải thẩm mỹ:
     · vùng chạm ≥44px ở khung hẹp — ngón tay không có con trỏ;
     · nhãn LUÔN hiện, không dùng placeholder thay nhãn — placeholder biến mất
       ngay khi người ta bắt đầu gõ, tức là biến mất đúng lúc cần nhất.
   ══════════════════════════════════════════════════════════════════════ */

/* 47a. Lối vào ở điều hướng ───────────────────────────────────────────── */
/* Mục thứ bảy của hàng nav. Màu accent vì nó khác LOẠI với sáu mục kia (một
   việc để làm, không phải một trang số liệu) — không phải để nó to hơn. */
.site-head nav a.nav-dt { color: var(--cobalt); }
@media (hover: hover) and (pointer: fine) {
  .site-head nav a.nav-dt:hover { color: var(--cobalt-strong); border-color: var(--seal-line); }
}
/* Đệm ngang của mục nav: 6px → 4px. Đo 17/08 trên bản đang chạy: `.wrap` chốt
   1320px nên khung chữ của thanh đầu trang là 1240px ở MỌI màn từ 1360 trở
   lên, và ba khối trong đó cần 1252,9px — thiếu 12,9px, mà `overflow: hidden`
   ở mục 24e biến chỗ thiếu ấy thành "ĐĂNG TIN cụt còn ĐĂNG T" chứ không thành
   một lỗi ai đó nhìn thấy.
   Bóp đệm lấy lại 7 × 4 = 28px, dư 15px cho cả hai ngôn ngữ. Đây đúng là cách
   mục 46 đã dùng khi cắm nút ngôn ngữ vào thanh này (62px lấy từ đệm nav,
   36px từ nhãn đồng hồ) — không đẻ thêm một cơ chế thứ hai cho cùng một loại
   vấn đề. */
.site-head nav a, .site-head nav span { padding: 6px 3px; }
/* Bản tiếng Anh phải bóp thêm, vì hàng của nó rộng hơn ở CẢ HAI đầu: nhãn dài
   hơn ("INTEREST RATES · CALCULATOR · METHODOLOGY" so với "LÃI SUẤT · TÍNH
   LÃI · PHƯƠNG PHÁP") và mốc bản chốt bên phải cũng dài hơn ("DATA AS OF 14
   Aug 2026" so với "BẢN CHỐT 14/08/2026"). Đo được: nav bản Anh cần 590px
   trong khi bản Việt cần 566px, còn chỗ được cấp thì ÍT hơn 20px.

   Hạ cỡ chữ thay vì đổi bản dịch: "Interest rates" là khoá dùng chung với
   tiêu đề cột của ba bảng (`tu_dien_bank.py`), rút gọn nó ở đây là sửa chữ
   của những trang không liên quan gì tới việc này. */
html[lang="en"] .site-head nav a, html[lang="en"] .site-head nav span {
  font-size: 12px;
}
/* Khung 1100–1199px vẫn không đủ (nav cần 566px, được cấp 473px) — và nó đã
   không đủ TỪ TRƯỚC khi có mục này: đo trên bản đang chạy, nav cần 511px và
   được cấp 465px, tức "Phương pháp" đang bị cắt ở đúng khung đó. Cho gãy dòng
   ở đây: hai hàng nav xấu hơn một hàng, nhưng một mục điều hướng biến mất thì
   người dùng không có cách nào biết mà tìm. */
@media (min-width: 1100px) and (max-width: 1199px) {
  .site-head nav { flex-wrap: wrap; }
}
/* Cột thứ tư của chân trang. Media query BẮT BUỘC: luật một cột ở ≤640px
   (mục 22) đứng TRƯỚC luật này trong file, nên khai trần ở đây là ghi đè mất
   nó và chân trang điện thoại vỡ thành bốn cột 25%. */
@media (min-width: 641px) {
  .foot-grid { grid-template-columns: 1.5fr 1fr 1fr 1fr; }
}

/* 47b. Trang cửa — hai lối vào ────────────────────────────────────────── */
.dt-cua { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
@media (max-width: 760px) { .dt-cua { grid-template-columns: 1fr; } }
/* Cả thẻ là một link: đích chạm bằng cả khối chứ không bằng một dòng chữ.
   Nút bên trong là `<span>`, không phải `<a>` lồng trong `<a>` — link lồng
   nhau là HTML không hợp lệ và trình đọc màn hình đọc ra hai đích. */
.dt-o {
  display: block; text-decoration: none; color: inherit;
  background: var(--panel-2); border: 1px solid rgba(var(--lnR), .14);
  border-radius: var(--r-lg); padding: var(--s5);
  transition: border-color var(--t-mau) ease, background-color var(--t-mau) ease;
}
.dt-o h3 { margin: var(--s3) 0 var(--s2); font-size: 19px; font-weight: 750; letter-spacing: -.02em; color: var(--ink); }
.dt-o > p { margin: 0; font-size: 15px; line-height: 1.65; color: var(--ink-2); }
/* Đường liên hệ dưới hai cửa (19/08). Câu và nút nằm CÙNG một hàng khi còn
   chỗ: tách thành hai dòng thì cái nút đọc ra như một lối vào thứ ba, mà nó
   không phải — nó là chỗ hỏi khi hai lối trên đều chưa hợp.
   Chữ nhỏ hơn và mực nhạt hơn hai thẻ vì đây là đường phụ, không phải đường
   dự án muốn người đọc đi trước. */
.dt-cua-lh {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: var(--s3);
  margin: var(--s5) 0 0; font-size: 14.5px; color: var(--muted); text-align: center;
}
.dt-o-di { margin-top: var(--s4) !important; }
.dt-o-phu {
  margin-top: var(--s3) !important; font-size: 13.5px; color: var(--muted);
  border-left: 2px solid var(--rule-strong); padding-left: var(--s3);
}
.dt-nut {
  display: inline-block; background: var(--acGrad); color: var(--on-accent);
  padding: var(--s3) var(--s5); font-weight: 600; border-radius: 999px;
  box-shadow: 0 0 26px rgba(var(--acR), var(--ga));
}
@media (hover: hover) and (pointer: fine) {
  .dt-o:hover { border-color: var(--seal-line); background: rgba(var(--acR), .045); }
}
.dt-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 11px;
  background: var(--cobalt-soft); color: var(--cobalt);
}
.dt-ic svg, .dt-ic .li { width: 21px; height: 21px; }

.dt-doc {
  display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  background: var(--panel-2); border: 1px solid rgba(var(--lnR), .14);
  border-radius: var(--r-lg); padding: var(--s5);
}
.dt-doc > div { flex: 1 1 300px; }
.dt-doc h2 { margin: 0 0 6px; font-size: 19px; font-weight: 750; letter-spacing: -.02em; }
.dt-doc p { margin: 0; font-size: 15px; color: var(--ink-2); }

/* 47c. Biểu mẫu ───────────────────────────────────────────────────────── */
/* `hidden` phải THẮNG mọi khai báo `display` của mục này. Thuộc tính `hidden`
   chỉ là một luật `display: none` của trình duyệt, hạng thấp nhất — khối nào
   khai `display: grid` thì `hidden` mất tác dụng, và JS đặt `.hidden = true`
   xong vẫn thấy khối nằm nguyên đó (lỗi thật: khu nộp liệu không biến mất khi
   thư phân vị hiện ra).
   Khai theo TỪNG lớp chứ không phải `[hidden] { display: none !important }`
   toàn cục: luật toàn cục sẽ phá nhánh không-JS của macro `ck2` và của
   `tool.html`, nơi `<noscript><style>` cố ý gỡ `hidden` để hiện cả hai panel. */
.dt-form[hidden], .dt-lam[hidden], .dt-thu[hidden], .dt-nhac[hidden],
.dt-seg label[hidden] { display: none; }
.dt-form { display: grid; gap: var(--s5); }
.dt-fs { margin: 0; padding: 0; border: 0; }
.dt-fs legend { padding: 0 0 var(--s2); font: 600 12px var(--mono); letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
/* Hai lựa chọn loại nhu cầu: nút thật, có `:has()` để cả ô sáng lên khi chọn.
   Trình duyệt không có `:has()` vẫn thấy chấm radio — mất phần nền, không mất
   thông tin. */
.dt-seg { display: flex; gap: var(--s2); flex-wrap: wrap; }
.dt-seg label {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 10px var(--s4); min-height: 44px; cursor: pointer;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: var(--surface); color: var(--ink-2); font-weight: 600; font-size: 15px;
}
.dt-seg label:has(input:checked) {
  border-color: var(--seal-line); background: var(--cobalt-soft); color: var(--cobalt);
}
.dt-seg input { width: 16px; height: 16px; accent-color: var(--cobalt); }

.dt-luoi2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
@media (max-width: 700px) { .dt-luoi2 { grid-template-columns: 1fr; } }
.dt-hang { display: grid; gap: 5px; margin: 0; }
.dt-hang label { font: 600 12px var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.dt-hang input, .dt-hang select {
  width: 100%; min-height: 44px; padding: 10px var(--s3);
  border: 1px solid var(--rule-strong); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); font: 400 16px var(--sans);
}
.dt-hang input[type="date"] { font-variant-numeric: tabular-nums; }
.dt-hang input:focus-visible, .dt-hang select:focus-visible { border-color: var(--cobalt); }
.dt-hang i {
  font-style: normal; font-size: 13px; line-height: 1.5; color: var(--muted);
}
.dt-hang-sdt { max-width: 320px; }

/* Ô đồng ý: nền riêng, viền accent ở mép trái, và đứng NGAY TRÊN nút gửi. Nó
   không được lướt qua được — nhưng cũng không được to hơn chính phiếu. */
.dt-dongy {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s3);
  align-items: start; padding: var(--s4);
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  font-size: 14px; line-height: 1.6; color: var(--ink-2); cursor: pointer;
}
/* Ô đã tick sáng lên: người đọc phải thấy mình vừa đồng ý cái gì mà không
   phải soi lại ba dấu tick nhỏ. */
.dt-dongy:has(input:checked) { border-color: var(--seal-line); background: var(--cobalt-soft); }
.dt-dongy input { margin-top: 3px; width: 20px; height: 20px; accent-color: var(--cobalt); }
.dt-dongy a { color: var(--cobalt); }
/* Khối đồng ý: khối nêu đủ + ba ô. Một viền accent bao CẢ khối, không phải
   ba viền cho ba ô — ba ô là một quyết định, không phải ba khối rời. */
.dt-dy {
  display: grid; gap: var(--s3); padding: var(--s5);
  background: var(--surface-2); border: 1px solid var(--rule);
  border-left: 3px solid var(--cobalt); border-radius: var(--r);
}
.dt-neu { margin: 0; padding-left: var(--s5); display: grid; gap: 6px; }
.dt-neu li { font-size: 13.5px; line-height: 1.6; color: var(--muted); }
.dt-dy-link { margin: 0; font-size: 13.5px; }
.dt-dy-link a { color: var(--cobalt); }
.dt-loi { margin: 0; color: var(--warn); font-size: 14.5px; font-weight: 600; }
.dt-loi:empty { display: none; }
.dt-gui { margin: 0; }
.dt-gui .btn { border: 0; cursor: pointer; font: 600 16px var(--sans); }

/* Khối "cách khác" và khối "đã nhận" — cùng khuôn, khác vai. */
.dt-thay, .dt-xong-in, .kn-trong {
  background: var(--panel-2); border: 1px solid rgba(var(--lnR), .14);
  border-radius: var(--r-lg); padding: var(--s5); margin-top: var(--s5);
}
.dt-thay p, .dt-xong-in p, .kn-trong p { margin: 0 0 var(--s3); font-size: 15px; color: var(--ink-2); line-height: 1.65; }
.dt-thay p:last-child, .dt-xong-in p:last-child { margin-bottom: 0; }
/* Câu đồng ý của nhánh KHÔNG-JS. Nhỏ hơn và im hơn phần trên — nó là chữ pháp
   lý, phải ĐỌC ĐƯỢC và ở ngay đó, nhưng không được to hơn việc người ta đang
   định làm. Cùng vai với `.chart-note`. */
   Chọn bằng `.dt-thay p.dt-thay-dy` (0,2,1) để thắng `.dt-thay p` (0,1,1) —
   độ cụ thể, không `!important`, cùng nếp với mục 39. */
.dt-thay p.dt-thay-dy { font-size: 13.5px; color: var(--muted); }
.dt-thay p.dt-thay-dy a { color: var(--cobalt); }
.dt-k {
  display: flex; align-items: center; gap: 8px;
  font: 650 15px var(--sans) !important; color: var(--ink) !important;
}
.dt-k svg, .dt-k .li { width: 18px; height: 18px; color: var(--cobalt); flex: none; }
.dt-xong-in { border-color: rgba(var(--upR), .35); }
.dt-xong-in .dt-k svg { color: var(--emerald); }
.dt-ma { font: 600 16px var(--mono); color: var(--cobalt); }

/* 47d. Cửa nộp liệu ───────────────────────────────────────────────────── */
/* Câu cam kết của chủ dự án. Không phải hộp cảnh báo (không amber, không đỏ):
   nó là một lời hứa, và một lời hứa in bằng màu cảnh báo đọc ra lời đe doạ. */
.dt-cam {
  display: flex; gap: var(--s3); align-items: flex-start;
  margin: 0; padding: var(--s4);
  background: var(--cobalt-soft); border-radius: var(--r);
  border: 1px solid var(--seal-line);
  font-size: 14.5px; line-height: 1.6; color: var(--ink);
}
.dt-cam svg, .dt-cam .li { width: 19px; height: 19px; color: var(--cobalt); flex: none; margin-top: 1px; }
.dt-cho { margin: var(--s5) 0 0; color: var(--muted); font: 500 14.5px var(--mono); }
/* `minmax(0, 1fr)` + `min-width: 0` — HAI dòng chữa cùng một bẫy, và nếu thiếu
   thì trang tràn ngang 186px trên iPhone 13, nhưng CHỈ SAU KHI lưới nạp xong
   (ảnh chụp trạng thái rỗng không bắt được).

   Chuỗi nguyên nhân đo ở 390×844 với lưới 8 kỳ hạn: `.scroller` có
   `overflow-x: auto` — đúng — nhưng nó nằm trong một `<form>` là GRID ITEM của
   `.dt-lam`, và grid item mặc định `min-width: auto`, tức sàn của nó là
   min-content. min-content ở đây là 560px (`.scroller table` mục 40 đặt sàn
   đó), nên track của `.dt-lam` nở lên 560px và đẩy nội dung ra khỏi
   `.wrap-narrow` 390px. `overflow-x` không cứu được: min-width mới là thứ
   quyết định, cùng đúng họ lỗi với hàng chip ở mục 40.

   Chữa ở CHỖ CHỨA chứ không ở cái bảng: mọi grid item của `.dt-lam` đều có
   thể mọc ra một khối rộng như vậy về sau. */
.dt-lam { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); margin-top: var(--s5); }
.dt-lam form { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
.dt-lam > *, .dt-lam form > * { min-width: 0; }

.dt-ngu {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s6);
  padding: var(--s4); border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--surface-2);
}
.dt-ngu p { margin: 0; display: grid; gap: 2px; }
.dt-ngu span { font: 600 11.5px var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.dt-ngu b { font-size: 17px; font-weight: 700; color: var(--ink); }
.dt-ngu-nho { flex: 1 1 100%; font-size: 13px; color: var(--muted); }

.dt-tabs { display: flex; gap: var(--s2); flex-wrap: wrap; }
.dt-tabs button {
  min-height: 44px; padding: 10px var(--s4); cursor: pointer;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: var(--surface); color: var(--ink-2);
  font: 600 14.5px var(--sans);
  transition: border-color var(--t-mau) ease, background-color var(--t-mau) ease;
}
.dt-tabs button[aria-selected="true"] {
  border-color: var(--seal-line); background: var(--cobalt-soft); color: var(--cobalt);
  box-shadow: 0 0 14px rgba(var(--acR), var(--gb));
}
.dt-huong { margin: 0 0 var(--s3); font-size: 14px; color: var(--muted); line-height: 1.6; }
.dt-huong b { color: var(--ink); }
.dt-anh-ten { margin: var(--s2) 0 0; font: 500 13.5px var(--mono); color: var(--emerald); }
.dt-anh-ten:empty { display: none; }

.dt-bang { width: 100%; border-collapse: collapse; }
.dt-bang th[scope="col"] {
  text-align: left; padding: 8px var(--s2); white-space: nowrap;
  font: 600 11.5px var(--mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--rule-strong);
}
/* `text-align: left` khai lại: luật chung của bảng số (mục 10) canh PHẢI mọi
   `td`, đúng cho một cột số đọc-để-so nhưng sai cho một ô NHẬP — nhãn và ô gõ
   phải bắt đầu ở cùng một mép, nếu không mắt phải nhảy qua lại giữa hai lề. */
.dt-bang td, .dt-bang th[scope="row"] {
  padding: 6px var(--s2); border-bottom: 1px solid var(--rule); text-align: left;
}
.dt-bang th[scope="row"] { text-align: left; font: 600 14.5px var(--sans); color: var(--ink); white-space: nowrap; }
.dt-bang input, .dt-bang select {
  width: 100%; min-width: 76px; min-height: 40px; padding: 7px var(--s2);
  border: 1px solid var(--rule-strong); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); font: 400 15px var(--sans);
}
.dt-bang .dt-i-muc { font: 600 15px var(--mono); font-variant-numeric: tabular-nums; }
.dt-bac { display: flex; align-items: center; gap: 5px; }
.dt-bac span { color: var(--muted); }
.dt-bac input { min-width: 62px; }

/* Khung hẹp: một bảng 5 cột không co xuống 390px được, và cuộn ngang trong
   một biểu mẫu nghĩa là người ta gõ mà không thấy nhãn cột. Mỗi dòng thành
   một THẺ, nhãn cột đọc từ `data-nhan` — thuộc tính do Jinja render nên nó
   vẫn đi qua tầng dịch. */
@media (max-width: 700px) {
  /* Gỡ SÀN 560px mà mục 40 đặt cho `.scroller table`. Sàn đó đúng cho một bảng
     SỐ đọc-để-so (thà cuộn ngang còn hơn nghiền cột thành chữ dọc), nhưng ở
     đây bảng đã thành THẺ nên nó không còn cột nào để nghiền — giữ sàn lại chỉ
     tạo đúng cái cuộn ngang trong biểu mẫu mà khối chú thích trên vừa nói là
     phải tránh. Cần `.scroller table.dt-bang` chứ không phải `.dt-bang`: luật
     của mục 40 có độ cụ thể 0,1,1, sửa bằng độ cụ thể chứ không bằng
     `!important` (cùng nếp với mục 39). */
  .scroller table.dt-bang { min-width: 0; }
  .dt-bang thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .dt-bang tr {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2);
    padding: var(--s3); margin-bottom: var(--s3);
    border: 1px solid var(--rule); border-radius: var(--r);
    background: var(--surface-2);
  }
  .dt-bang th[scope="row"] { grid-column: 1 / -1; border: 0; padding: 0 0 2px; }
  .dt-bang td { border: 0; padding: 0; display: grid; gap: 3px; }
  .dt-bang td::before {
    content: attr(data-nhan);
    font: 600 11px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
  }
  /* Mức chào ăn cả hàng: nó là con số DUY NHẤT của dòng này, và để nó nằm nửa
     hàng với nửa kia trống thì thẻ đọc ra như đang thiếu một ô. Bậc tiền cũng
     cả hàng vì nó là hai ô nối bằng gạch nối. Kênh và hiệu lực chia đôi hàng
     cuối — cả hai đều ngắn và luôn đi cùng nhau. */
  .dt-bang td:nth-child(2) { grid-column: 1 / -1; }
  .dt-bang td.dt-bac {
    grid-column: 1 / -1;
    display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  }
  .dt-bang td.dt-bac::before { grid-column: 1 / -1; }
}

/* 47e. Thư phân vị — phần thưởng, nên nó được làm như một lá thư ───────── */
/* `scroll-margin-top`: JS gọi `focus()` để đưa người vừa nộp tới lá thư, mà
   `focus()` cuộn phần tử lên SÁT đỉnh khung nhìn — nơi thanh tiêu đề dính và
   dải biến động đang che. Cộng chiều cao thật của thanh (`--cao-dau`, app.js
   đo) thay vì gõ một con số: thanh đó cao khác nhau ở mỗi khung. Cùng lý do
   cho khối "đã nhận" của phiếu khách. */
.dt-thu, .dt-xong { scroll-margin-top: calc(var(--cao-dau, 60px) + 52px); }
.dt-thu {
  margin-top: var(--s5); padding: var(--s6);
  background: var(--panel-hi); border: 1px solid var(--seal-line);
  border-radius: var(--r-lg); box-shadow: 0 0 30px rgba(var(--acR), var(--gb));
}
.dt-thu h2 { margin: 0 0 var(--s2); font-size: clamp(21px, 2.4vw, 28px); font-weight: 750; letter-spacing: -.028em; }
.dt-thu-de { margin: 0 0 var(--s5); color: var(--ink-2); font-size: 15.5px; }
.dt-thu .chart-note { margin: var(--s5) 0 var(--s4); }
/* Câu nhắc của máy chủ — amber, đúng vai màu "caveat và điều kiện" của hệ. */
.dt-nhac {
  margin: 0 0 var(--s4); padding: var(--s3) var(--s4);
  background: var(--amber-soft); border-left: 2px solid var(--amber);
  border-radius: var(--r-sm); color: var(--amber); font-size: 14px; line-height: 1.55;
}
.dt-pv { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.dt-pv li { display: grid; gap: 6px; }
.dt-pv-k { margin: 0; display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.dt-pv-ky { font: 700 16px var(--sans); color: var(--ink); }
.dt-pv-vt { font: 600 14px var(--mono); color: var(--cobalt); letter-spacing: .04em; }
/* Thanh phân vị: nền là cả phân bố, phần tô là chỗ mức của người nộp đứng.
   Không có thang chia — nó là một vị trí tương đối, không phải một phép đo. */
.dt-pv-thanh {
  position: relative; margin: 0; height: 10px; border-radius: 999px;
  background: var(--chip-bg); overflow: hidden;
}
.dt-pv-thanh > span {
  position: absolute; inset: 0 auto 0 0; width: 0;
  background: var(--acGrad90); border-radius: 999px;
}
.dt-pv-s { margin: 0; font-size: 13.5px; color: var(--muted); }
.dt-pv-tv { font: 600 14px var(--mono); color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* 47f. Góc kết nối ────────────────────────────────────────────────────── */
.kn-luoi {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--s4);
}
.kn-tin {
  display: grid; gap: var(--s3); align-content: start;
  padding: var(--s5); background: var(--panel-2);
  border: 1px solid rgba(var(--lnR), .14); border-radius: var(--r-lg);
}
.kn-dau { margin: 0; display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.kn-loai {
  padding: 3px 10px; border-radius: 999px;
  font: 600 12.5px var(--sans); white-space: nowrap;
}
/* Hai loại nhu cầu, hai vai màu đã có sẵn trong hệ: gửi tiền là dòng tiền vào
   (emerald), vay là dòng tiền ra (thép). KHÔNG dùng đỏ cho "vay" — đỏ ở hệ
   này nghĩa là cảnh báo, và một người đi vay không phải một cảnh báo. */
.kn-loai.gui { background: var(--emerald-soft); color: var(--emerald); }
.kn-loai.vay { background: var(--chip-bg); color: var(--ink-2); }
.kn-tuan { font: 500 12.5px var(--mono); color: var(--muted); white-space: nowrap; }
/* `text-align: left` khai lại ở mọi ô GIÁ TRỊ và mọi nhãn: luật chung ở mục
   43 canh đều hai lề cho MỌI thẻ `p`, đúng cho văn xuôi và sai cho một con số
   hai chữ. "100 triệu – 300 triệu" gãy hai dòng bị justify kéo giãn thành
   "100        triệu –" — chữ bị bè ra đúng chỗ người đọc quét nhanh nhất. */
.kn-tien, .kn-ct dd, .dt-pv-k, .dt-pv-s, .dt-cho, .dt-loi, .dt-anh-ten,
.dt-hang i, .dt-ngu p, .dt-nhac { text-align: left; }
.kn-trong p, .kn-trong h2 { text-align: center; }
.kn-tien { margin: 0; font: 700 clamp(19px, 2.2vw, 23px) var(--mono); color: var(--ink); letter-spacing: -.02em; }
.kn-ct { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 4px var(--s3); }
.kn-ct dt { font: 600 11.5px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); align-self: center; }
.kn-ct dd { margin: 0; font-size: 14.5px; color: var(--ink-2); }
.kn-di { margin: var(--s2) 0 0; }
.kn-trong { text-align: center; }
.kn-trong h2 { margin: var(--s3) 0 var(--s2); font-size: 21px; font-weight: 750; letter-spacing: -.024em; }
.kn-trong p { max-width: 46ch; margin-inline: auto; }
.kn-trong-di { display: flex; gap: var(--s3); justify-content: center; flex-wrap: wrap; margin-top: var(--s5) !important; }

/* Lưới hai cột cho khối giải thích của mục này. KHÔNG khai `.ct-luoi-2` —
   lớp đó đang được ba trang cũ dùng mà chưa có luật nào, và cho nó một luật ở
   đây là lặng lẽ đổi bố cục của những trang không thuộc phần việc này. */
.ct-luoi.dt-2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .ct-luoi.dt-2 { grid-template-columns: 1fr; } }

/* ── 48. Cặp thẻ So sánh ↔ Tính lãi ──────────────────────────────────────
   Hai trang, một mục ở thanh điều hướng (chốt 17/08). Cặp thẻ này là đường đi
   lại giữa chúng, nên nó phải đọc ra "hai mặt của cùng một việc" chứ không
   phải hai nút bấm rời. Nền chìm + viên đang xem nổi lên là khuôn đã dùng cho
   công tắc lớp dữ liệu ở hero — dùng lại để người đọc không phải học lần hai. */
/* Khoảng thở giữa thẻ tiêu đề và cặp thẻ — 19/08.
   Bản 17/08 kéo cặp thẻ LÊN `calc(-1 * var(--s4))` để nó đọc ra "dính vào thẻ
   tiêu đề". Đo lại thì kết quả ngược hẳn ý định: `.stage` có `position:
   relative`, nên trong cùng một ngữ cảnh xếp lớp nó được vẽ SAU (đè lên) mọi
   anh em tĩnh — cặp thẻ bị chính thẻ tiêu đề phủ mất 16px mép trên ở cả bốn
   trang, cả VI lẫn EN, ở mọi khung. `elementFromPoint` ngay trên viên nang trả
   về `.stage` chứ không phải `.cap-tab`: chỗ đó bấm vào cũng không trúng.
   Đảo dấu thành `var(--s5)` — bằng đúng `margin-top` của chính `.stage`, nên
   thẻ tiêu đề có khoảng trống bằng nhau ở trên và dưới.
   `position: relative` là chốt an toàn, không phải trang trí: nó đưa cặp thẻ
   lên cùng tầng vẽ với `.stage` và vì đứng sau trong DOM nên luôn thắng. Có
   lỡ đặt lại lề âm lần nữa thì cặp thẻ vẫn bấm được, không âm thầm chui xuống
   dưới tấm sân khấu. */
.cap-trang { margin-top: var(--s5); position: relative; }
.cap-tab {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: 999px; background: var(--chip-bg);
  border: 1px solid var(--rule);
}
.cap-tab a {
  padding: 7px 16px; border-radius: 999px; text-decoration: none;
  font: 600 13.5px var(--sans); color: var(--ink-2); white-space: nowrap;
  transition: background-color var(--t-mau) ease, color var(--t-mau) ease;
}
.cap-tab a.on { background: var(--surface); color: var(--cobalt-strong); box-shadow: var(--shadow-1); }
@media (hover: hover) and (pointer: fine) {
  .cap-tab a:not(.on):hover { color: var(--ink); }
}
.cap-tab a:active { transform: translateY(1px) scale(.97); }
@media (max-width: 560px) { .cap-tab { display: flex; width: 100%; }
  .cap-tab a { flex: 1; text-align: center; padding-inline: 8px; } }

/* ── 49. Ngân sách bề ngang của hàng đầu trang ───────────────────────────
   Sự cố 17/08 (chủ dự án chụp): mục "ĐĂNG TIN" BIẾN MẤT khỏi thanh điều hướng
   ở khung 1440 — không phải đè lên nhau mà bị `overflow: hidden` cắt trong im
   lặng, nên nhìn thì tưởng trang lành.

   Phép đo giải thích tất cả: `.wrap` chốt `max-width: 1320px`, nên hàng đầu
   trang có ĐÚNG 1320px ở MỌI khung từ 1320 trở lên — màn 1600 hay 1920 không
   cho thêm một pixel nào. Ngân sách: 1320 − logo 175 − rãnh 24 = 1121px cho
   điều hướng + trạng thái. Trước lượt này chúng cần 1210px (nav 581 · trạng
   thái 629) — thiếu 89px, và mục thêm sau cùng là mục bị cắt.

   Vì ngân sách không đổi theo khung, luật thu hẹp KHÔNG bọc trong media query
   khung rộng: một luật chỉ chạy ở khung hẹp là luật không bao giờ chạy đúng
   chỗ hỏng. Đã cắt 105px ở hai chỗ rẻ nhất:
     · mốc đầu trang bỏ NĂM (ngày/tháng là đủ cho một trang cập nhật hằng
       ngày; bản đầy đủ vẫn còn ở con dấu cuối trang) — 45px;
     · điều hướng bớt đệm và giãn cách chữ, KHÔNG giảm cỡ chữ — 60px.
   ĐẶT CUỐI FILE CÓ CHỦ Ý: khối nav mono (mục 24d) đứng sau khối nav gốc nên
   nó ghi đè `padding` và `letter-spacing`; media query không cộng thêm độ cụ
   thể, nên luật thu hẹp phải đứng SAU nó mới có tác dụng. Mất một lượt đo mới
   thấy — ghi lại để lần sau khỏi lặp. */
@media (min-width: 901px) {
  .site-head nav a, .site-head nav span { padding-inline: 7px; letter-spacing: .04em; }
  .site-head nav { gap: 4px; }
}
/* Thứ tự nhường chỗ khi vẫn không đủ, từ ít quan trọng nhất: đồng hồ (trang
   trí, đã `aria-hidden`) → mốc thị trường (mốc phụ). Ba thứ giữ tới cùng:
   điều hướng, nút ngôn ngữ, mốc bản chốt. */
/* Đồng hồ tắt ở MỌI khung có thanh điều hướng (≥901px), không phải chỉ ở
   khung hẹp: `.wrap` chốt 1320px nên màn rộng hơn KHÔNG cho thêm chỗ, và
   ngân sách đo được vẫn thiếu 22px sau khi đã rút mốc và bóp đệm. Đồng hồ là
   thứ rẻ nhất để bỏ — nó `aria-hidden`, không mang thông tin quyết định, và
   người đọc có sẵn đồng hồ trên máy. Ở khung dưới 901px thanh điều hướng ẩn
   (bottom nav lo), lúc đó đồng hồ có chỗ nên được hiện lại. */
@media (min-width: 901px) { .head-clock { display: none; } }
/* Dải 1121–1319px là chỗ vỡ cuối cùng: đo ở 1200 thấy mục "Đăng tin" kết
   thúc ở 783 trong khi khối trạng thái bắt đầu ở 673 — đè 110px. Mốc thị
   trường (161px) là thứ tiếp theo trong thứ tự nhường chỗ, bỏ nó là vừa.
   Từ 1320 trở lên cả hai mốc cùng hiện — đã đo 1320/1440/1920: không đè,
   không mục nào bị ẩn. */
@media (max-width: 1319px) { .head-tt { display: none; } }

/* Điều hướng KHÔNG được cắt cụt trong im lặng. `overflow: hidden` ở khối gốc
   xén 6px cuối — vô hại với chữ, nhưng mục "đang xem" là một ô CÓ VIỀN nên
   nó bị xén mất cạnh phải khi đứng cuối hàng. Cho phép tràn thấy được: nếu
   ngân sách lại thiếu thì lỗi phải LỘ RA để sửa, chứ không tự giấu. */
@media (min-width: 901px) { .site-head nav { overflow: visible; } }

/* ── 50. Hàng đầu trang trải hết bề ngang, hai điều khiển thu nhỏ ─────────
   Chủ dự án 17/08: "nút EN/VI và light dark to quá… thanh tiêu đề có vẻ bị
   gom vào giữa, thiết kế lại để tiêu đề dàn ra đủ chiều ngang".

   Cả hai nhận xét cùng một gốc. `.head-top` dùng chung khung `.wrap` với thân
   trang (`max-width: 1320px`), nên ở màn 1920 thanh đầu trang co về giữa và
   chừa 300px trắng mỗi bên — đúng cảm giác "bị gom vào giữa". Và vì chỉ có
   1320px, hai điều khiển buộc phải to để còn bấm được trong khi mọi thứ khác
   chen chúc.

   Sửa gốc: thanh đầu trang KHÔNG dùng khung thân trang nữa, nó trải hết bề
   ngang với lề co giãn. Thân trang giữ nguyên 1320px — cột chữ hẹp là cố ý,
   còn thanh điều hướng thì không phải cột chữ.

   Món lợi kèm theo: ngân sách bề ngang từ 1121px lên ~1700px ở màn 1920, nên
   mốc thị trường không phải nhường chỗ nữa (xem cuối mục). */
.site-head .head-top {
  max-width: none;
  width: 100%;
  padding-inline: clamp(16px, 2.6vw, 44px);
  gap: clamp(12px, 1.6vw, 28px);
}
/* Điều hướng đẩy về phía trạng thái thay vì dính sát logo: khoảng thở giữa ba
   khối làm hàng đọc ra BA nhóm chứ không phải một dãy chữ dài. */
@media (min-width: 901px) {
  .site-head nav { margin-inline: auto; }
}

/* Hai điều khiển thu nhỏ — cùng một nhịp, vì chúng đứng cạnh nhau và lệch cỡ
   thì đọc ra "hai thứ rời rạc". Viền 2px xuống 1px, quầng bỏ hẳn: khi chúng
   đã nhỏ và gọn thì không cần quầng để tìm ra nữa. */
.nut-lang {
  padding: 1.5px; border-width: 1px;
  box-shadow: inset 0 1px 2px rgba(12, 27, 56, .06);
}
.nut-lang a {
  min-width: 26px; height: 20px; padding: 0 6px;
  font-size: 11px; letter-spacing: .06em;
}
.nut-lang a.on { box-shadow: 0 1px 3px rgba(12, 27, 56, .28); }
.nt-track {
  width: 50px; height: 24px; padding: 0 5px; gap: 3px;
  border-width: 1px;
  box-shadow: inset 0 1px 2px rgba(12, 27, 56, .06);
}
.nt-ic .lucide { width: 13px; height: 13px; stroke-width: 2.2; }
.nt-knob { width: 18px; height: 18px; margin-top: -9px; left: 2px;
  box-shadow: 0 1px 3px rgba(12, 27, 56, .28); }
.nut-theme[aria-checked="true"] .nt-knob { transform: translateX(26px); }
@media (hover: hover) and (pointer: fine) {
  .nut-lang:hover, .nut-theme:hover .nt-track {
    border-color: var(--cobalt); box-shadow: 0 0 10px rgba(var(--cbR), .22);
  }
}

/* Có chỗ rồi thì mốc thị trường hiện lại — nhưng không phải ở mọi khung.
   Đo lại sau khi thanh trải hết bề ngang: từ 1280px trở lên hàng còn dư chỗ;
   dải 1160–1279 vẫn thiếu 33px và mục "Đăng tin" là mục chạm vào khối trạng
   thái. Mốc thị trường (161px) vẫn là thứ nhường trước, đúng thứ tự đã đặt ở
   mục 49 — chỉ khác là ngưỡng nhường lùi từ 1320 xuống 1280. */
@media (min-width: 1280px) { .head-tt { display: inline-flex; } }

/* ── 31. Kênh theo dõi ────────────────────────────────────────────── */
/* Mỗi kênh một hàng: nút bên trái, câu giải thích bên phải. Xếp NGANG hàng
   nhau thì ba nút cạnh nhau thành một hàng rào và không nút nào được bấm —
   còn xếp dọc thì mắt đọc được "cái này để làm gì" trước khi bấm. */
.kenh-ds { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.kenh-ds li { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }
.kenh-ds .btn { min-width: 148px; text-align: center; }
.kenh-ds span { color: var(--muted); font-size: 14.5px; }

/* Nút viền cho kênh phụ. Cùng hình dạng nút chính nhưng không cùng sức nặng —
   người đọc phải thấy ngay đâu là kênh dự án muốn họ vào. */
.btn-vien {
  background: none; color: var(--cobalt);
  border: 1px solid var(--rule-strong);
}
.btn-vien:hover { border-color: var(--cobalt); }

@media (max-width: 560px) {
  /* Điện thoại: nút chiếm hết bề ngang, chữ giải thích xuống dòng dưới nó. */
  .kenh-ds li { gap: 4px; }
  .kenh-ds .btn { width: 100%; }
}

/* ── 51 · Nút liên hệ đứng trong một ô <dd> ────────────────────────────
   `.mq-dk dd` đặt `font-weight: 600` cho cả ô, mà `.btn` không tự ghi đè nét
   chữ — không có khối này thì nút Zalo thừa hưởng nét đậm của ô mô tả và trông
   dày hơn mọi nút khác trên site. `display: block` để nút xuống dòng riêng
   thay vì dính đuôi câu, và `margin-top` giữ đúng nhịp dọc của thẻ. */
.mq-nut { display: block; margin-top: var(--s2); font-weight: 400; }
.mq-nut .btn { display: inline-flex; align-items: center; gap: 6px; }

/* ── 52 · Dải kênh NỔI (Zalo OA · Fanpage · TikTok) ─────────────────────────
   Đọc chú thích macro `dai_kenh_noi` trong _macros.html trước: bốn ràng buộc
   hình học nằm ở đó, khối này chỉ là phần thi hành.

   z-index 39, THẤP HƠN nút tư vấn (40) một bậc và cao hơn bottom nav (30).
   Thứ tự đó có lý do: khi hai thứ buộc phải chồng nhau ở màn hẹp, cái được
   nằm trên phải là cái người dùng đang chủ động mở, không phải cái luôn hiện. */
.kn-noi {
  position: fixed; z-index: 39;
  right: var(--s4); bottom: calc(var(--s4) + 68px);
  display: grid; gap: 10px;
}
.kn-nut {
  width: 44px; height: 44px;          /* đúng ngưỡng vùng chạm, không hơn */
  display: grid; place-items: center;
  border-radius: 999px; border: 1px solid var(--rule);
  background: var(--panel); color: var(--muted);
  box-shadow: 0 6px 18px -10px rgba(15, 23, 41, .45);
  transition: color .16s ease, border-color .16s ease, transform .16s ease;
}
.kn-nut svg { width: 21px; height: 21px; fill: currentColor; }
/* Chữ "Z" trong bong bóng Zalo là nét, không phải mảng — tô đặc thì nó biến
   mất vào nền bong bóng. */
.kn-nut .kn-chu { stroke: var(--panel); stroke-width: 1.7; stroke-linecap: round;
  stroke-linejoin: round; }
.kn-nut:hover, .kn-nut:focus-visible {
  color: var(--cobalt); border-color: var(--cobalt); transform: translateY(-1px);
}
.kn-nut:active { transform: scale(.94); }

/* Điện thoại: dải nằm NGANG ở mép TRÁI, cùng hàng với nút tư vấn bên phải.
   68px là chiều cao nút tư vấn cộng khoảng thở — dùng chung con số với
   `.tuvan` để hai chỗ không trôi khỏi nhau. */
@media (max-width: 640px) {
  .kn-noi {
    left: var(--s3); right: auto; bottom: calc(76px + var(--s2));
    grid-auto-flow: column; gap: var(--s2);
  }
  .kn-nut { width: 42px; height: 42px; }
}

/* Màn rất thấp (điện thoại nằm ngang, cửa sổ nhỏ): ba nút nổi cộng bottom nav
   cộng nút tư vấn ăn hết chỗ đọc. Ẩn dải — khối CTA ở chân trang vẫn còn đủ
   ba kênh, nên không mất đường nào, chỉ mất lối tắt. */
@media (max-height: 460px) {
  .kn-noi { display: none; }
}

/* Trạng thái "lùi": trượt ra mép trái và mờ đi, KHÔNG `display: none` —
   phần tử biến mất khỏi cây bố cục thì tiêu điểm bàn phím đang ở trên nó bị
   rơi về đầu trang. Ẩn bằng dịch chuyển thì nó vẫn ở đó, chỉ là không chắn ai. */
.kn-noi { transition: transform .22s ease, opacity .22s ease; }
/* Điện thoại: dải nằm bên TRÁI nên lùi sang trái. Máy tính bảng và laptop nhỏ:
   dải nằm bên PHẢI nên lùi sang phải. Lùi nhầm hướng là đi ngang qua cả màn hình. */
@media (max-width: 640px) {
  .kn-noi.kn-lui { transform: translateX(calc(-100% - var(--s3))); opacity: 0; }
}
@media (min-width: 641px) and (max-width: 1399px) {
  .kn-noi.kn-lui { transform: translateX(calc(100% + var(--s4))); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .kn-noi { transition: none; }
  .kn-noi.kn-lui { transform: none; opacity: 1; }
  .kn-nut { transition: none; }
  .kn-nut:hover, .kn-nut:focus-visible, .kn-nut:active { transform: none; }
}

/* ═══ Trang lãi vay — bảng so sánh (build_vay + lai-suat-vay.html) ═══════════
   Xoay quanh lãi cơ sở/thả nổi (số cào đáng tin), xếp tăng dần. Ba cột gọn nên
   đọc được trên mobile; .scroller (đã có) lo cuộn ngang nếu chật. Nhãn lớp mang
   màu ngữ nghĩa palette VOLT (khảo sát=emerald, niêm yết=thép, cũ=amber, thị
   trường=mờ) — hợp cả hai theme vì dùng token. */
.bang-vay-so { width: 100%; border-collapse: collapse; font-size: 14px; }
.bang-vay-so thead th {
  text-align: left; padding: 8px 10px; background: var(--head);
  color: var(--ink-2); font-weight: 600; font-size: 12px;
  border-bottom: 1px solid var(--rule-strong); white-space: nowrap;
}
.bang-vay-so tbody th, .bang-vay-so tbody td {
  padding: 10px; border-bottom: 1px solid var(--rule);
  vertical-align: top; text-align: left;
}
.bang-vay-so tbody th { font-weight: 700; min-width: 128px; }
.bang-vay-so .vs-co {
  font-variant-numeric: tabular-nums; font-weight: 700;
  color: var(--ink); white-space: nowrap;
}
.vc-nhom {
  display: block; font-size: 11px; color: var(--faint);
  font-weight: 400; margin-top: 2px;
}
.vc-bd { font-size: 11px; font-weight: 600; color: var(--muted); }
.uu-chip {
  display: inline-flex; align-items: baseline; gap: 4px;
  margin: 0 6px 4px 0; padding: 2px 8px; background: var(--chip-bg);
  border-radius: var(--r-sm); font-size: 12px; white-space: nowrap;
}
.uu-chip b { font-variant-numeric: tabular-nums; color: var(--ink); }
.vc-lop { font-size: 10px; font-weight: 600; }
.lop-khao_sat { color: var(--emerald); }
.lop-khao_sat_cu { color: var(--amber); }
.lop-niem_yet { color: var(--steel); }
.lop-thi_truong { color: var(--muted); }
.vc-cu { display: block; font-size: 11px; color: var(--amber); margin-top: 3px; }
.bang-vay-so .dim { color: var(--faint); }
/* Mobile: 3 cột quá rộng cho 375px → xếp mỗi ngân hàng thành KHỐI (recon: bảng
   dày → thẻ trên điện thoại). Ẩn thead, mỗi hàng là một thẻ có viền, nhãn cột
   chèn bằng attr(data-nhan) — dịch được theo ngôn ngữ, KHÔNG gõ cứng trong CSS. */
@media (max-width: 640px) {
  .bang-vay-so thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  }
  .bang-vay-so, .bang-vay-so tbody, .bang-vay-so tr,
  .bang-vay-so tbody th, .bang-vay-so tbody td { display: block; }
  .bang-vay-so tr {
    border: 1px solid var(--rule); border-radius: var(--r);
    padding: var(--s3) var(--s4); margin-bottom: var(--s3);
  }
  .bang-vay-so tbody th { min-width: 0; padding: 0 0 8px; border: 0; }
  .bang-vay-so tbody td { padding: 5px 0 0; border: 0; }
  .bang-vay-so .vs-co { font-size: 17px; }
  .bang-vay-so .vs-co::before {
    content: attr(data-nhan) " "; font-size: 12px; font-weight: 400; color: var(--ink-2);
  }
  .bang-vay-so .vs-uu::before {
    content: attr(data-nhan); display: block; font-size: 12px;
    color: var(--ink-2); margin-bottom: 4px;
  }
}

/* Lưới liên kết mọi trang ngân hàng trên trang chủ (spec SEO 22/09, mục 5).
   Chữ thường cỡ đọc, không phải nút: đây là mục lục, không phải lời mời bấm. */
.luoi-bank { list-style: none; margin: var(--s4) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--s2) var(--s4); }
.luoi-bank a { color: var(--ink); text-decoration: none; font-size: 15px;
  border-bottom: 1px solid var(--rule); padding: 6px 0; display: block; }
.luoi-bank a:hover { color: var(--cobalt-bright); border-color: var(--cobalt-bright); }

/* Trang theo cụm từ khoá (src/site/trang_cum.py · cum.html). */
.cum-tra-loi { margin: 0; padding-left: 1.2em; font-size: 17px; line-height: 1.6; }
.cum-tra-loi li { margin: 0 0 var(--s2); }
.cum-hai-lop { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--s5); }
.cum-bang { width: 100%; border-collapse: collapse; font-size: 15px; }
.cum-bang caption { text-align: left; font-weight: 700; padding: 0 0 var(--s2); color: var(--ink-2); }
.cum-bang th, .cum-bang td { padding: 8px 10px; border-bottom: 1px solid var(--rule); text-align: left; }
.cum-bang .so { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cum-bang small { display: block; color: var(--muted); font-size: 12.5px; }
.cum-cuon { overflow-x: auto; }
.cum-bang-rong { min-width: 560px; }
.cum-lead { border: 1px solid var(--rule-strong); border-radius: 12px; padding: var(--s5); }
.cum-lead h2 { margin-top: 0; }
