/* ═══════════════════════════════════════════════════════════════════════════════════════
   GENUP — BỘ MÀU GỐC. MỘT NGUỒN DUY NHẤT.
   ═══════════════════════════════════════════════════════════════════════════════════════

   Chủ dự án 06/09/2026:
     *"GENUP CANONICAL UI PALETTE: BLACK · WHITE · RED · BLUE. KHÔNG dùng GREEN làm màu
      trạng thái success/good/healthy trong UI GENUP."*
     *"Điểm quan trọng nhất là đừng chỉ 'xoá xanh lá'. Phải biến màu thành design system có
      token + CI gate, để vài tuần sau không quay lại đúng lỗi này nữa."*

   ── VÌ SAO TỆP NÀY TỒN TẠI ──────────────────────────────────────────────────────────────

   Ngày 06/09 phải sửa xanh lá ở **27 tệp**, ba lượt quét mới hết: lượt một tìm theo mã hex ra
   59 chỗ, lượt hai tìm `rgb()` theo quan hệ ba kênh ra **45 chỗ nữa**, lượt ba đo màu ĐÃ TÍNH
   trong Chrome thật ra **9 giá trị nữa**. Ba lượt cho cùng một câu hỏi, vì mỗi trang tự khai
   màu của nó.

   Gốc của chuyện ấy không phải "có người chọn nhầm màu". Gốc là **không có chỗ nào để chọn
   đúng**: mỗi trang khai `--green` / `--xanh` riêng, nên "màu của trạng thái tốt" là một ý
   kiến lặp lại hai mươi bảy lần chứ không phải một quyết định ghi ở một chỗ.

   Nên tệp này giữ HAI TẦNG, và thứ tự giữa chúng mới là phần quan trọng:

     ① MÀU NHẬN DIỆN   đen · trắng · đỏ · xanh dương — bốn màu, không hơn
     ② MÀU NGỮ NGHĨA   success · info · warning · error · degraded · disabled
                       → TRỎ VÀO tầng ①, không tự khai mã màu mới

   Trang chỉ được dùng tầng ②. Muốn nói "cái này đang tốt" thì viết `var(--status-success)`,
   không viết một mã màu. Đổi ý về màu của "tốt" thì sửa ĐÚNG MỘT DÒNG ở đây.

   🔴 `--status-success` TRỎ VÀO XANH DƯƠNG, KHÔNG PHẢI XANH LÁ. Đây là điểm cả bộ này sinh ra
   để giữ. Xanh lá = "tốt" là phản xạ mặc định của mọi thư viện giao diện, nên nó sẽ quay lại
   nếu không có một chỗ nói thẳng rằng ở GENUP thì không.

   ── MÀU CỦA HÃNG KHÁC ───────────────────────────────────────────────────────────────────

   Logo Google, Drive, Sheets, WhatsApp có xanh lá trong bộ nhận diện của HỌ. Đổi màu logo của
   người ta là làm sai logo, không phải làm đúng bảng màu của mình. Những màu ấy nằm ở nhóm
   `--google-*` / `--whatsapp-*` — **tên nói rõ nó là của ai**.

   ⚠️ KHÔNG BAO GIỜ dùng `--google-green` làm nền nút, chấm trạng thái, huy hiệu hay điểm nhấn
   của GENUP. Nó chỉ được nằm trong nét vẽ của chính logo ấy. `doKhongCoXanhLa.js` canh đúng
   ranh giới này: cùng một mã màu, nằm trong `<path>` của logo thì tha, nằm ở nền một cái nút
   thì đỏ.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── ① BỐN MÀU NHẬN DIỆN ────────────────────────────────────────────────────────────── */
  /* 🔴 29/09/2026 — OWNER: "tạo chiều sâu bằng CÁC LỚP MÀU TỐI CHÊNH TONE — nền đen sâu → khối
     xanh-đen → khối con xám-đen", KHÔNG bằng hộp có viền. Ba mức dưới là ba lớp ấy. */
  --genup-black: #08090C;        /* đen sâu — nền trang */
  --genup-black-2: #0D1520;      /* XANH-ĐEN — thẻ/khối trên nền đen (trước #0F1216, xám phẳng) */
  --genup-black-3: #161A21;      /* XÁM-ĐEN — khối con trong thẻ (trước #151920) */
  --genup-white: #FFFFFF;
  --genup-white-2: #F2F6FA;      /* chữ chính trên nền tối — trắng ngà cho đỡ chói */
  --genup-white-3: #CFD8E1;      /* chữ phụ */
  --genup-red: #DB1920;
  --genup-red-2: #F0333A;        /* đỏ sáng — điểm nhấn trên nền tối */
  --genup-red-d: #B0141A;        /* đỏ đậm — trạng thái rê chuột */
  /* 🔴 ĐỎ DÀNH CHO CHỮ TRÊN NỀN TỐI. Đo 06/09/2026 trên năm mức nền tối của bảng màu:
         #DB1920  3,96 · 3,73 · 3,50 · 3,22 · 3,45   → trượt 4,5 ở MỌI nền
         #F0333A  4,97 · 4,68 · 4,40 · 4,04 · 4,34   → vẫn trượt ở ba nền
         #FF5C63  6,60 · 6,23 · 5,84 · 5,37 · 5,76   → đạt khắp nơi
     Đỏ thương hiệu #DB1920 vẫn đúng cho NỀN nút (chữ trắng trên nó được 5,03). Nó chỉ
     không đủ tương phản khi làm CHỮ. Hai vai, hai token — đừng sửa một cái cho cả hai. */
  --genup-red-chu: #FF5C63;      /* đỏ — dùng khi đỏ là CHỮ, không phải nền */

  /* 🔴 VIỀN CẤU KIỆN PHẢI NHÌN THẤY ĐƯỢC — WCAG 1.4.11 đòi 3:1.
     Viền "mờ nhẹ" quen dùng (#2a3244 trên nền đen) chỉ đạt 1,55, và #e5e8ed trên nền
     trắng chỉ đạt 1,44 — tức một cái nút mà không ai thấy đâu là mép. Hai số dưới đã
     đo trên cả hai mức nền tối (#08090C và #151920) và trên nền trắng. */
  --genup-vien-ro: #69717f;       /* viền cấu kiện trên nền TỐI — 4,05 và 3,58 */
  --genup-vien-ro-sang: #7C8894;  /* viền cấu kiện trên nền SÁNG — 3,62 */
  --genup-blue: #1F5FBF;
  --genup-blue-2: #4DA6FF;       /* xanh sáng — điểm nhấn trên nền tối */
  --genup-blue-3: #8EC5FF;       /* xanh nhạt — chữ phụ trên nền tối */
  --genup-blue-d: #1A56C4;       /* xanh đậm — trạng thái rê chuột */

  /* Xám trung tính pha một chút xanh dương của bộ nhận diện — xám thuần đọc ra là "chưa ai
     chọn", còn xám lệch nhẹ về màu nhấn thì đọc ra là "đã chọn". */
  --genup-mut: #93A0AC;
  --genup-line: rgba(255, 255, 255, .085);
  --genup-line-2: rgba(255, 255, 255, .16);

  /* ── ② MÀU NGỮ NGHĨA — TRỎ VÀO TẦNG ①, KHÔNG KHAI MÃ MỚI ────────────────────────────── */

  /* 🔴 TỐT = XANH DƯƠNG. Xem khối ghi chú đầu tệp. */
  --status-success: var(--genup-blue);
  --status-success-2: var(--genup-blue-2);
  --status-success-nen: rgba(31, 95, 191, .14);
  --status-success-vien: transparent;

  --status-info: var(--genup-blue);
  --status-info-2: var(--genup-blue-2);
  --status-info-nen: rgba(31, 95, 191, .12);
  --status-info-vien: transparent;

  --status-error: var(--genup-red);
  --status-error-2: var(--genup-red-2);
  --status-error-nen: rgba(219, 25, 32, .14);
  --status-error-vien: transparent;

  /* CẢNH BÁO và GIẢM CHẤT LƯỢNG dùng ĐỎ NHẠT, không dùng cam/vàng mới và tuyệt đối không
     kéo lại xanh lá. Chúng là "đang có chuyện" ở mức nhẹ hơn lỗi, nên đứng cùng phía với
     đỏ là đúng nghĩa — và giữ bảng màu ở bốn màu. */
  --status-warning: var(--genup-red-2);
  --status-warning-nen: rgba(240, 51, 58, .10);
  --status-warning-vien: transparent;

  --status-degraded: var(--genup-red-2);
  --status-degraded-nen: rgba(240, 51, 58, .08);
  --status-degraded-vien: transparent;

  /* ── ②b CHỮ NẰM TRÊN CHÍNH NỀN NHẠT CỦA NÓ ──────────────────────────────────────────
     06/09/2026. Hộp thông báo thường viết như thế này:

         .xong { background: var(--status-success-nen); color: var(--status-success) }

     Nền là màu ấy pha loãng 8–14% trên nền trang tối, nên nó vẫn RẤT TỐI. Còn chữ là màu
     gốc bậc ①, vốn chọn để đứng trên nền đen — không phải để đứng trên chính nó. Kết quả
     đo được: chữ `.xong` 3,56 và chữ `.loi` 4,34, cả hai dưới ngưỡng 4,5 của WCAG. Hai
     hộp ấy là hộp BÁO LỖI và hộp BÁO XONG — đúng hai chỗ khách buộc phải đọc được.

     🔴 KHÔNG sửa bằng cách đổi `--status-error` cho sáng lên. Ngày 06/09 đã một lần đổi
     `--coral` vì lý do y hệt và làm hỏng 11 chỗ chữ trắng trên nút — một biến mang hai
     vai thì sửa vai này là hỏng vai kia. Nên đây là một tầng RIÊNG, chỉ dùng khi chữ nằm
     trên nền `-nen` tương ứng.

     Số đo trên nền thật: #FF5C63/#2a1414 = 5,76 · #4DA6FF/#101c2e = 6,69. */
  --status-success-chu: var(--genup-blue-2);
  --status-info-chu: var(--genup-blue-2);
  --status-error-chu: var(--genup-red-chu);
  --status-warning-chu: var(--genup-red-chu);
  --status-degraded-chu: var(--genup-red-chu);

  /* CHƯA BIẾT và ĐANG TẮT là trung tính. Một trạng thái chưa đo được mà tô màu có nghĩa thì
     nó đang nói dối về thứ nó chưa biết. */
  --status-unknown: var(--genup-mut);
  --status-unknown-nen: rgba(147, 160, 172, .12);
  --status-unknown-vien: transparent;

  --status-disabled: var(--genup-mut);
  --status-disabled-nen: rgba(147, 160, 172, .08);
  --status-disabled-vien: transparent;

  /* ── ③ MÀU CỦA HÃNG KHÁC — CHỈ DÙNG TRONG LOGO CỦA CHÍNH HỌ ─────────────────────────── */
  --google-green: #0F9D58;       /* Google Sheets — thân biểu tượng */
  --google-green-d: #0B8043;     /* Google Sheets — nếp gấp góc */
  --google-green-2: #34A853;     /* Google — cung xanh của chữ G */
  --google-green-3: #4CAF50;     /* Google Drive — nhánh xanh của tam giác */
  --whatsapp-green: #25D366;
}

/* Nền sáng: chỉ đổi GIÁ TRỊ của tầng ①, tầng ② tự đúng theo. Đây chính là chỗ hai tầng trả
   công: một bộ nền sáng không phải khai lại "tốt là màu gì". */
:root[data-theme="light"] {
  /* Không viền thì trắng-trên-gần-trắng mất lớp: nền trang xám rất nhạt → thẻ TRẮNG (+ bóng mềm) → khối con xám nhạt. */
  --genup-black: #F3F5F8;
  --genup-black-2: #FFFFFF;
  --genup-black-3: #EDF1F6;
  --genup-white-2: #101418;
  --genup-white-3: #3B4652;
  --genup-mut: #5F6B77;
  --genup-line: rgba(0, 0, 0, .09);
  --genup-line-2: rgba(0, 0, 0, .16);
  --genup-blue-2: #1F5FBF;       /* nền sáng thì xanh sáng mất tương phản — hạ xuống */
  --genup-blue-3: #1A56C4;
  --genup-red-2: #C4141B;
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   VÒNG LẤY TIÊU ĐIỂM — MỘT LUẬT CHO CẢ ỨNG DỤNG
   ═══════════════════════════════════════════════════════════════════════════════════════

   Đo 06/09/2026 trên Chrome thật, ép `:focus-visible` lên từng thành phần tương tác của cả
   31 trang: **140 lượt** không đạt ngưỡng 3:1 của WCAG 1.4.11. Nghĩa là người dùng bàn phím
   đi Tab qua ứng dụng mà **không thấy mình đang đứng ở đâu**.

   Không trang nào khai vòng tiêu điểm riêng, nên mỗi trang rơi về vòng mặc định của trình
   duyệt — vốn là một đường mảnh màu tối, gần như tàng hình trên nền tối của GENUP.

   Chủ dự án: *"Không sửa từng trang nếu có thể sửa semantic token chung."* Nên một luật ở
   đây, và cả ứng dụng có vòng tiêu điểm thấy được.

   Dùng `--genup-blue-2`: trên nền tối `#4DA6FF` cho tỉ lệ 7,6; ở bộ nền sáng biến này đã
   được đổi thành `#1F5FBF`, cho 6,2 trên nền trắng. Một biến, hai nền, cả hai đều qua ngưỡng.

   `:focus-visible` chứ không phải `:focus` — bấm chuột vào một cái nút không nên vẽ vòng,
   chỉ đi bằng bàn phím mới cần. Trình duyệt tự phân biệt.

   `outline` chứ không phải `border`: `outline` không chiếm chỗ, nên bật lên không đẩy lệch
   bố cục — đây đúng là lý do thuộc tính ấy tồn tại. */
:focus-visible {
  outline: 2px solid var(--genup-blue-2, #4DA6FF);
  outline-offset: 2px;
  border-radius: inherit;
}
/* Bỏ vòng mặc định KHI VÀ CHỈ KHI đã có vòng của mình thay thế — bỏ trắng trơn là lấy đi
   thứ duy nhất người dùng bàn phím có. */
:focus:not(:focus-visible) { outline: none; }

/* ═══════════════════════════════════════════════════════════════════════════════════════
   ④ TOKEN CẤU KIỆN — CHỮ · KHOẢNG CÁCH · BO GÓC · BÓNG · BỀ MẶT · THẺ · NÚT (CORE, 22/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════

   OWNER 22/09: trang chủ mới *"sang trọng lịch lãm nhất có thể và ĐỒNG NHẤT"*, và CORE cùng chịu
   giao diện toàn hệ (trang chủ · trung tâm khách hàng · admin). "Đồng nhất" không giữ được bằng
   lời dặn: mỗi trang tự khai cỡ chữ, bo góc, bóng của mình thì sau vài tuần lại thành 31 ý kiến,
   đúng như chuyện màu 06/09. Nên tầng ④ nằm CÙNG tệp với tầng ①② (HTQT-B + BOSS: không mở tệp
   thứ ba), và theo đúng luật của tệp: token cấu kiện TRỎ VÀO tầng ①, không khai mã màu mới.

   Chủ tệp: CORE (PHOI-HOP/OWNERSHIP.md). Trang và các HST CHỈ DÙNG biến `--gu-*` dưới đây;
   cần thêm/đổi biến ⇒ CLAIM tới CORE. Tiền tố `--gu-` = GENUP UI, tách khỏi biến cục bộ cũ.

   Ba nguyên tắc cho "sang trọng":
     · ít màu, nhiều khoảng thở — thang khoảng cách 4px, bề mặt tối nhiều tầng thay vì màu rực;
     · một kiểu chữ tiêu đề (Oswald, cao–hẹp) + một kiểu chữ thân (Plus Jakarta Sans) — không thêm;
     · chiều sâu bằng viền mảnh + bóng mềm + ánh xanh rất nhẹ, không bằng nền tím/xanh đặc. */
:root {
  /* ── Chữ ── */
  --gu-font-display: var(--hoa, "Oswald", "Anton", system-ui, sans-serif);
  --gu-font-body: var(--sans, "Plus Jakarta Sans", system-ui, sans-serif);
  --gu-fs-xs: 12px;
  --gu-fs-sm: 13.5px;
  --gu-fs-base: 15px;
  --gu-fs-md: 17px;
  --gu-fs-lg: 20px;
  --gu-fs-xl: 26px;
  --gu-fs-2xl: clamp(26px, 2.4vw, 34px);            /* tiêu đề thẻ hệ */
  --gu-fs-hero: clamp(40px, 5.4vw, 76px);           /* "GEN UP AI BUSINESS OS" */
  /* CỠ CHỮ THEO VAI TRÒ (DEC-20260922-023, OWNER: "chữ nhỏ lại, sang trọng tinh tế như web app quốc tế, câu dài xuống
     hàng hợp lý"). Trang khách CHỈ dùng tầng này; thang xs…xl ở trên là nguyên liệu. --gu-fs-2xl/-hero chỉ cho hero
     trang chủ (bài coChuTheoVaiTro). */
  --gu-fs-trang: 20px;                              /* tiêu đề trang */
  --gu-fs-muc: 15px;                                /* tiêu đề mục / thẻ — đi với --gu-fw-strong */
  --gu-fs-than: 14px;                               /* chữ thân, nút, ô nhập */
  --gu-fs-mo-ta: 13.5px;                            /* câu mô tả / chú thích dưới tiêu đề */
  --gu-fs-nhan: 12px;                               /* nhãn, huy hiệu, tiêu đề cột */
  --gu-do-dai-dong: 65ch;                           /* đoạn văn không dài quá ~65 ký tự/dòng */
  --gu-lh-tieu-de: 1.3;                             /* tiêu đề chữ thường có dấu tiếng Việt: ≥1.2 để không xén "ệ", "g" */
  --gu-lh-display: 1.02;
  --gu-lh-body: 1.65;
  --gu-ls-display: .01em;
  --gu-ls-eyebrow: .22em;                           /* dòng nhỏ viết hoa trên tiêu đề */
  --gu-fw-body: 500;
  --gu-fw-strong: 700;

  /* ── Khoảng cách — LƯỚI 8px (DEC-20260922-021 ③): bố cục dùng bước chẵn sp-2/4/6/8/10/12/16; sp-1/3/5 chỉ cho khe NỘI BỘ cấu kiện ── */
  --gu-sp-1: 4px;  --gu-sp-2: 8px;  --gu-sp-3: 12px; --gu-sp-4: 16px; --gu-sp-5: 20px;
  --gu-sp-6: 24px; --gu-sp-8: 32px; --gu-sp-10: 40px; --gu-sp-12: 48px; --gu-sp-16: 64px;

  /* ── Bố cục ── */
  --gu-content-max: 1280px;
  --gu-gutter: clamp(16px, 3vw, 32px);              /* luật artifact/phone: ≥16px hai bên */
  --gu-sidebar-w: 280px;
  --gu-grid-gap: clamp(16px, 2vw, 28px);

  /* ── Bo góc ── */
  --gu-radius-sm: 8px;
  --gu-radius-md: var(--r, 14px);
  --gu-radius-lg: 20px;
  --gu-radius-pill: 999px;

  /* ── Bề mặt (tối nhiều tầng) ── */
  --gu-surface-0: var(--genup-black);               /* nền trang */
  --gu-surface-1: var(--genup-black-2);             /* thẻ, thanh */
  --gu-surface-2: var(--genup-black-3);             /* ô trong thẻ */
  /* 🔴 LUẬT KHÔNG VIỀN — OWNER 29/09/2026: "KHÔNG dùng các đường viền/stroke bao quanh card, panel, form,
     input hoặc các khung lồng nhau để phân tầng giao diện … tôi rất ghét các cái khung viền". Mọi chỗ còn
     `border: … var(--gu-border|--gu-border-strong)` tự thành vô hình; phân tầng bằng --gu-surface-* + khoảng
     cách + --gu-shadow-*. (Thay DEC-20260922-021 mục viền cấu kiện ≥3:1.) Đường phân cách THẬT SỰ cần về
     chức năng (hàng bảng, vạch "hoặc") dùng --gu-ke — mảnh, không bao quanh gì. */
  --gu-border: transparent;
  --gu-border-strong: transparent;
  --gu-ke: rgba(255, 255, 255, .07);
  --gu-text: var(--genup-white-2);
  --gu-text-2: var(--genup-white-3);
  --gu-text-mut: var(--genup-mut);
  /* Chữ trên bề mặt LUÔN TỐI (thanh trên, cột trái, chữ đè ảnh thẻ) — KHÔNG đổi theo nền sáng. Giá trị = đúng hai mức
     trắng của tầng ① bản tối (#F2F6FA · #CFD8E1), chép cố định vì tầng ① bị nền sáng ghi đè. HTQT-B xin 22/09. */
  --gu-text-tren-toi: #F2F6FA;
  --gu-text-tren-toi-2: #CFD8E1;
  /* Chữ TRẠNG THÁI trên bề mặt LUÔN TỐI (nhãn Sắp ra mắt/Đang cập nhật trên thẻ hệ ở nền sáng — Luồng B 28/09, B-15).
     = đỏ-chữ/xanh sáng tầng ① bản tối, chép cố định: #FF5C63 trên #0F1216 = 6,0 · #4DA6FF = 7,1; bản nền sáng (#C4141B) chỉ ~3,1. */
  --gu-chu-do-tren-toi: #FF5C63;
  --gu-chu-lam-tren-toi: #4DA6FF;
  /* 🔴 29/09/2026 — ANH EM CÒN THIẾU CỦA CẶP TRÊN, và chỗ thiếu ấy đã thành một lỗi thật.
     Họ token `*-tren-toi` có đủ đỏ/lam, còn phía `*-tren-sang` chỉ có chữ trung tính
     (`--gu-text-tren-sang`). Nên một hòn đảo LUÔN SÁNG muốn chữ ĐỎ thì không có gì để dùng,
     và người viết trang lấy tạm `--gu-chu-do` — token theo CHẾ ĐỘ TRANG. Trang tối ⇒ #FF5C63
     ⇒ 3,02 trên trắng (ô số nút "Kết quả GEN UP đã tạo", thuong-hieu-noi-dung, khi rê chuột).

     🔴 VÀ `.gu-tren-sang` KHÔNG CỨU ĐƯỢC CA NÀY. Giá trị tính toán của một biến CSS được thay
     thế NGAY TẠI PHẦN TỬ KHAI NÓ: `--gu-chu-do: var(--genup-red-chu)` khai ở `:root` nên nó đã
     hoá thành #FF5C63 ở `:root` rồi mới truyền xuống. Khai lại `--genup-red-chu` ở một phạm vi
     SÂU HƠN không kéo tầng ② đi theo. Đo thật: thêm `.gu-tren-sang` cho chính phần tử ấy —
     màu vẫn y nguyên #ff5c63. Nên cách duy nhất đúng là một token CỐ ĐỊNH, như cặp trên.
     = #C4141B (bản nền-sáng của `--genup-red-chu`): 6,0 trên #FFFFFF. */
  --gu-chu-do-tren-sang: #C4141B;
  /* Bề mặt LUÔN TỐI (thẻ hệ trên điện thoại: ảnh một bên, chữ một bên trên nền đen GENUP ở CẢ hai nền — OWNER 22/09).
     = hai mức đen tầng ① bản tối (#08090C · #0F1216), chép cố định vì tầng ① bị nền sáng ghi đè. Cặp với --gu-text-tren-toi. */
  --gu-be-mat-toi: #0F1216;
  --gu-be-mat-toi-0: #08090C;
  /* Bề mặt LUÔN SÁNG (viên thuốc trắng giữa trang tối, nút trắng — HST01 CLAIM 22/09) + chữ trên nó; không đổi theo nền.
     Đo: #101418 trên #FFFFFF = 18,6 · #3B4652 = 9,9. */
  /* Mặt nạ (chỉ dùng trong mask-image — lấy ĐỘ TRONG, alpha 1 là hiện đủ). HST01 22/09: --gu-overlay làm hero mờ đi. */
  --gu-mat-na: #000000;
  --gu-be-mat-sang: #FFFFFF;
  --gu-text-tren-sang: #101418;
  --gu-text-tren-sang-2: #3B4652;

  /* ── MÀU CHỮ AN TOÀN theo chế độ (HST07 đo 22/09: --gu-lam 2,56 trên nền sáng · --gu-vang 1,89 · --gu-do 3,73 trên tối) ──
     Khi một màu nhận diện là CHỮ thì dùng tầng này, KHÔNG dùng màu nền (--gu-do/--genup-red là NỀN nút). Mỗi biến có giá trị
     riêng cho nền sáng ở khối :root[data-theme="light"] dưới. Bài `tuongPhanTokenHaiCheDo` đo từng cặp, <4,5 ⇒ đỏ. */
  --gu-chu-lam: var(--genup-blue-2);                 /* tối #4DA6FF · sáng #1F5FBF (tầng ① tự đổi) */
  --gu-chu-do: var(--genup-red-chu);                 /* tối #FF5C63 · sáng #C4141B */
  --gu-chu-vang: #F0B23A;                            /* CHỈ để trang cũ đang dùng --gu-vang đổi sang; KHÔNG dùng mới (bảng 4 màu) */
  /* nền nhạt + viền cho khối trạng thái (chữ dùng --status-*-chu) */
  --gu-nen-lam: var(--status-info-nen);   --gu-vien-lam: var(--status-info-vien);
  --gu-nen-do: var(--status-error-nen);   --gu-vien-do: var(--status-error-vien);

  /* ── Bóng ── */
  --gu-shadow-1: 0 1px 2px rgba(0, 0, 0, .30), 0 4px 14px rgba(0, 0, 0, .28);
  --gu-shadow-2: 0 2px 6px rgba(0, 0, 0, .34), 0 14px 40px rgba(0, 0, 0, .40);
  --gu-glow-blue: 0 0 0 1px rgba(77, 166, 255, .35), 0 18px 48px rgba(31, 95, 191, .28);
  --gu-glow-red: 0 10px 30px rgba(219, 25, 32, .35);

  /* ── Thẻ hệ sinh thái (lưới trang chủ, thẻ Partner) ──
     Nền xanh dương SÂU chuyển về đen — cùng họ màu ảnh mẫu của OWNER nhưng không phẳng/đặc.
     Đo 22/09 tại điểm SÁNG NHẤT của dải (xanh 42% trên đen = rgb 18,45,87): chữ `--gu-text` 12,57 · chữ phụ `--gu-text-2` 9,46.
     Nền sáng (xanh 11% trên trắng): chữ 15,71 · chữ phụ 8,17. Không khai mã màu mới — chỉ color-mix tầng ①. */
  --gu-card-he-bg: linear-gradient(150deg, color-mix(in srgb, var(--genup-blue) 42%, var(--genup-black)) 0%, color-mix(in srgb, var(--genup-blue) 20%, var(--genup-black)) 42%, var(--genup-black-2) 100%);
  --gu-card-he-border: rgba(77, 166, 255, .22);
  --gu-card-he-border-hover: rgba(77, 166, 255, .55);
  --gu-card-he-radius: var(--gu-radius-lg);
  --gu-card-he-pad: clamp(20px, 2.2vw, 28px);
  --gu-card-he-min-h: 220px;
  --gu-card-he-lift: translateY(-3px);
  --gu-card-he-anh-toi: linear-gradient(180deg, rgba(8, 9, 12, 0) 35%, rgba(8, 9, 12, .78) 100%); /* phủ ảnh để chữ đọc được */

  /* ── Nút ── */
  --gu-btn-h: 44px;                                  /* vùng chạm ≥44px */
  --gu-btn-pad-x: 20px;
  --gu-btn-radius: var(--gu-radius-sm);
  --gu-btn-primary-bg: var(--genup-red);            /* chữ trắng trên nền này = 5,03 */
  --gu-btn-primary-bg-hover: var(--genup-red-d);
  /* ══ 2,5D CHO NÚT ĐỎ (OWNER 01/10/2026) ═══════════════════════════════════════════════
     Chủ dự án: *"MÀU ĐỎ QUÁ DẦY VÀ CHÓI MẮT … TRỪ LOGO HAY CHỮ GENUP MÀU ĐỎ GIỮ NGUYÊN,
     CÒN LẠI TẤT CẢ CÁC NÚT MÀU ĐỎ CHỈNH SANG MÀU ĐỎ SẬM LẠI, NÓ NHƯ KIỂU 2,5D NỔI GRADIENT
     CHUYỂN TỪ NÂU ĐỎ SANG ĐỎ … CHO KO BỊ CHÓI MẮT, NHÌN TRẦM ỔN HƠN"*.

     🔴 Đây là ẢNH NỀN (`background-image`), KHÔNG đổi `--gu-btn-primary-bg`. Hai lý do, cả hai
     đã đo:
       ① `background:` viết tắt với một gradient sẽ xoá `background-color` về trong suốt, và
          mọi nơi đang viết `background:var(--gu-btn-primary-bg)` sẽ mất màu nền đặc.
       ② Bộ đo tương phản đọc MỘT màu đặc. Giữ nền đặc `#DB1920` thì phép đo vẫn đúng và an
          toàn cả hai chiều: đó là điểm SÁNG NHẤT của nút, nên "nút nổi trên nền trang" đo ở
          mức khó nhất, còn "chữ trắng trên nút" (5,03) chỉ TỐT LÊN khi gradient tối dần.
          Ghi chú cũ trong `thuong-hieu-noi-dung.html` đã đo: để nền đặc `#B0141A` thì chính
          cái nút mất ranh giới với nền trang (2,57 < 3) — nên KHÔNG hạ màu nền đặc.
     Không có mã màu mới nào: tất cả pha từ `--genup-red` / `--genup-red-d` đang có. */
  --gu-btn-primary-anh: linear-gradient(180deg,
      var(--genup-red) 0%,
      var(--genup-red-d) 40%,
      color-mix(in srgb, var(--genup-red-d) 62%, black) 100%);
  --gu-btn-primary-anh-hover: linear-gradient(180deg,
      var(--genup-red) 0%,
      var(--genup-red-d) 58%,
      color-mix(in srgb, var(--genup-red-d) 66%, black) 100%);
  --gu-btn-primary-text: var(--genup-white);
  --gu-btn-secondary-bg: rgba(255, 255, 255, .07);  /* nút phụ = khối lấp đầy, KHÔNG viền (OWNER 29/09) */
  --gu-btn-secondary-bg-hover: rgba(255, 255, 255, .12);
  --gu-btn-secondary-border: transparent;
  --gu-btn-secondary-text: var(--gu-text);
  /* OWNER 01/10: nút CTA lớn cũng phải TRẦM lại — dải cũ bắt đầu từ `--genup-red-2` (đỏ sáng)
     nên cả nút rực. Nay bắt đầu từ đỏ thương hiệu rồi tối dần về nâu đỏ. */
  --gu-btn-cta-bg: linear-gradient(180deg, var(--genup-red) 0%, var(--genup-red-d) 48%, color-mix(in srgb, var(--genup-red-d) 62%, black) 100%);

  /* ── Hero ── */
  --gu-hero-nhan-do: var(--genup-red-chu);           /* "UP", "OS" — đỏ là CHỮ ⇒ dùng tầng chữ */
  --gu-hero-nhan-so: var(--genup-blue-2);            /* con số "10", "26" (xanh dương) */
  --gu-hero-bg: radial-gradient(1200px 380px at 50% 0%, rgba(31, 95, 191, .22), transparent 70%), var(--gu-surface-0);

  /* ── Form ── (DEC-20260922-021: đủ trạng thái; vùng chạm ≥44px) */
  --gu-input-h: 44px;
  --gu-input-pad-x: 14px;
  /* Ô nhập = FILLED SURFACE (OWNER 29/09): nền lấp đầy sáng hơn khối chứa một bậc; rê chuột sáng thêm;
     focus đổi tone xanh + glow mềm. Không viền cố định. `--gu-input-border-focus` vẫn là xanh vì nó còn làm
     VÒNG TIÊU ĐIỂM (outline) cho nút — thứ bàn phím cần, không phải viền trang trí. */
  --gu-input-bg: rgba(255, 255, 255, .055);
  --gu-input-bg-hover: rgba(255, 255, 255, .085);
  --gu-input-bg-focus: rgba(77, 166, 255, .10);
  /* vòng trong ĐẶC (WCAG 2.4.7 / 1.4.11 — OWNER 29/09 "không hạ accessibility"): #4DA6FF trên mọi mặt tối ≥ 6,8:1;
     bản rgba .42 cũ chỉ ~2,1:1. Quầng mềm phía ngoài giữ chiều sâu, không phải viền. */
  --gu-input-glow: 0 0 0 2px var(--genup-blue-2), 0 8px 24px rgba(31, 95, 191, .22);
  --gu-input-border: transparent;
  --gu-input-border-focus: var(--genup-blue-2);
  --gu-input-border-loi: var(--status-error);
  --gu-input-radius: var(--gu-radius-sm);
  --gu-input-text: var(--gu-text);
  --gu-input-placeholder: var(--gu-text-mut);
  --gu-label-text: var(--gu-text-2);
  --gu-help-text: var(--gu-text-mut);
  --gu-loi-text: var(--status-error-chu);

  /* ── Bảng ── */
  --gu-table-head-bg: var(--gu-surface-2);
  --gu-table-head-text: var(--gu-text-2);
  --gu-table-row-border: var(--gu-ke);              /* phân cách hàng — chức năng, không bao khung */
  --gu-table-row-hover: color-mix(in srgb, var(--genup-blue) 8%, transparent);
  --gu-table-cell-pad: 12px 16px;

  /* ── Trạng thái trang: tải · rỗng · lỗi · xong ── */
  --gu-skeleton-nen: color-mix(in srgb, var(--genup-white) 6%, transparent);
  --gu-skeleton-anh: color-mix(in srgb, var(--genup-white) 13%, transparent);
  --gu-rong-icon: var(--gu-text-mut);
  --gu-thong-bao-radius: var(--gu-radius-md);

  /* ── Icon · lớp chồng ── */
  --gu-icon-sm: 16px;
  --gu-icon-md: 20px;
  --gu-icon-lg: 28px;
  --gu-z-thanh: 40;
  --gu-z-menu: 60;
  --gu-z-hop-thoai: 80;
  --gu-z-thong-bao: 100;
  --gu-overlay: rgba(8, 9, 12, .64);

  /* ── Chuyển động ── */
  --gu-ease: cubic-bezier(.2, .7, .2, 1);
  --gu-dur-1: 140ms;
  --gu-dur-2: 240ms;
}
:root[data-theme="light"] {
  --gu-card-he-bg: linear-gradient(150deg, color-mix(in srgb, var(--genup-blue) 11%, var(--genup-white)) 0%, color-mix(in srgb, var(--genup-blue) 5%, var(--genup-white)) 45%, var(--genup-white) 100%);
  --gu-card-he-border: rgba(31, 95, 191, .22);
  --gu-card-he-border-hover: rgba(31, 95, 191, .55);
  --gu-card-he-anh-toi: linear-gradient(180deg, rgba(255, 255, 255, 0) 35%, rgba(255, 255, 255, .82) 100%);
  --gu-shadow-1: 0 1px 2px rgba(16, 20, 24, .06), 0 4px 14px rgba(16, 20, 24, .08);
  --gu-shadow-2: 0 2px 6px rgba(16, 20, 24, .08), 0 14px 40px rgba(16, 20, 24, .12);
  --gu-hero-bg: radial-gradient(1200px 380px at 50% 0%, rgba(31, 95, 191, .10), transparent 70%), var(--gu-surface-0);
  --gu-skeleton-nen: color-mix(in srgb, var(--genup-black-3) 90%, var(--genup-white-3));
  --gu-skeleton-anh: color-mix(in srgb, var(--genup-black-3) 70%, var(--genup-white-3));
  --gu-overlay: rgba(16, 20, 24, .48);
  --gu-chu-vang: #8A5A00;                            /* trên #FFFFFF = 6,05 */
  /* luật không viền — bản nền sáng */
  --gu-ke: rgba(16, 20, 24, .08);
  --gu-input-bg: rgba(16, 20, 24, .045);
  --gu-input-bg-hover: rgba(16, 20, 24, .07);
  --gu-input-bg-focus: rgba(31, 95, 191, .08);
  --gu-input-glow: 0 0 0 2px var(--genup-blue-2), 0 6px 18px rgba(31, 95, 191, .12);   /* #1F5FBF trên trắng 6,1:1 */
  --gu-btn-secondary-bg: rgba(16, 20, 24, .06);
  --gu-btn-secondary-bg-hover: rgba(16, 20, 24, .10);
}
/* PHẠM VI CHẾ ĐỘ CỐ ĐỊNH (HST01 22/09): khối LUÔN SÁNG (viên thuốc trắng giữa trang tối) cần trạng thái/chữ bản SÁNG bất kể
   chế độ trang — và ngược lại. Đặt `.gu-tren-sang` / `.gu-tren-toi` lên khối: tầng ① được khai lại TRONG phạm vi ⇒ tầng ②, --gu-*
   và mọi lớp .gu-* bên trong tự đúng. Không cần cặp token riêng. Giá trị = đúng hai khối :root ở trên. */
.gu-tren-sang {
  --genup-black: #F3F5F8; --genup-black-2: #FFFFFF; --genup-black-3: #EDF1F6;
  --genup-white-2: #101418; --genup-white-3: #3B4652; --genup-mut: #5F6B77;
  --genup-line: rgba(0, 0, 0, .09); --genup-line-2: rgba(0, 0, 0, .16);
  --genup-blue-2: #1F5FBF; --genup-blue-3: #1A56C4; --genup-red-2: #C4141B; --genup-red-chu: #C4141B;
  --gu-chu-vang: #8A5A00;
  color: var(--gu-text);
}
.gu-tren-toi {
  --genup-black: #08090C; --genup-black-2: #0D1520; --genup-black-3: #161A21;
  --genup-white-2: #F2F6FA; --genup-white-3: #CFD8E1; --genup-mut: #93A0AC;
  --genup-line: rgba(255, 255, 255, .085); --genup-line-2: rgba(255, 255, 255, .16);
  --genup-blue-2: #4DA6FF; --genup-blue-3: #8EC5FF; --genup-red-2: #F0333A; --genup-red-chu: #FF5C63;
  --genup-vien-ro: #69717f; --gu-chu-vang: #F0B23A;
  color: var(--gu-text);
}
/* Đỏ-làm-chữ trên nền sáng: #FF5C63 chỉ 2,95 trên trắng ⇒ hạ xuống (tầng ① bản sáng thiếu dòng này trước 22/09). */
:root[data-theme="light"] { --genup-red-chu: #C4141B; }
@media (prefers-reduced-motion: reduce) {
  :root { --gu-dur-1: 0ms; --gu-dur-2: 0ms; --gu-card-he-lift: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   ⑤ LỚP THÀNH PHẦN DÙNG CHUNG — .gu-btn · .gu-card · .gu-input/.gu-select · .gu-badge · .gu-table · .gu-skeleton · .gu-toast
   (CORE 22/09, BOSS P1: HST02 đo — chỉ có token nút mà không có LỚP ⇒ mỗi trang tự viết CSS nút ⇒ lại 10 kiểu.)
   Trang KHÔNG viết CSS nút/thẻ/ô nhập/nhãn/bảng/khung xương/thông báo riêng — dùng lớp dưới đây. Chỉ dùng token.
   Mẫu sống: docs/he-thiet-ke/mau-thanh-phan.html.
   ═══════════════════════════════════════════════════════════════════════════════════════ */
:root { --gu-btn-h-sm: 36px; --gu-btn-h-lg: 52px; --gu-skeleton-khoi-h: 120px; --gu-toast-max: 420px; }
.gu-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--gu-sp-2);
  height: var(--gu-btn-h); padding: 0 var(--gu-btn-pad-x); border-radius: var(--gu-btn-radius);
  font: inherit; font-family: var(--gu-font-body); font-size: var(--gu-fs-than); font-weight: var(--gu-fw-strong);
  line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer; user-select: none;
  border: 1px solid transparent; background-color: var(--gu-btn-primary-bg);
  background-image: var(--gu-btn-primary-anh); color: var(--gu-btn-primary-text);
  transition: background var(--gu-dur-1) var(--gu-ease), border-color var(--gu-dur-1) var(--gu-ease),
    transform var(--gu-dur-1) var(--gu-ease), box-shadow var(--gu-dur-1) var(--gu-ease);
}
.gu-btn:hover { background-color: var(--gu-btn-primary-bg-hover); background-image: var(--gu-btn-primary-anh-hover); }
.gu-btn:active { transform: translateY(1px); }
.gu-btn:focus-visible { outline: 2px solid var(--genup-blue-2); outline-offset: 2px; }
.gu-btn--secondary { background: var(--gu-btn-secondary-bg); color: var(--gu-btn-secondary-text); border-color: var(--gu-btn-secondary-border); }
.gu-btn--secondary:hover { background: var(--gu-btn-secondary-bg-hover); }
.gu-btn--ghost { background: transparent; color: var(--gu-text); border-color: transparent; }
.gu-btn--ghost:hover { background: var(--gu-surface-2); }
.gu-btn--danger { background: var(--status-error-nen); color: var(--gu-chu-do); border-color: transparent; }
.gu-btn--danger:hover { background: var(--status-error-nen); }
.gu-btn--cta { background: var(--gu-btn-cta-bg); box-shadow: var(--gu-glow-red); text-transform: uppercase; letter-spacing: .08em; padding: 0 var(--gu-sp-8); }
.gu-btn--sm { height: var(--gu-btn-h-sm); padding: 0 var(--gu-sp-3); font-size: var(--gu-fs-nhan); }
.gu-btn--lg { height: var(--gu-btn-h-lg); padding: 0 var(--gu-sp-8); font-size: var(--gu-fs-base); }
.gu-btn:disabled, .gu-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; transform: none; }
.gu-btn[aria-busy="true"] { cursor: progress; color: transparent; position: relative; }
.gu-btn[aria-busy="true"]::after {
  content: ""; position: absolute; width: var(--gu-icon-sm); height: var(--gu-icon-sm); border-radius: var(--gu-radius-pill);
  border: 2px solid var(--gu-btn-primary-text); border-right-color: transparent; animation: gu-quay .7s linear infinite;
}
.gu-btn--secondary[aria-busy="true"]::after, .gu-btn--ghost[aria-busy="true"]::after { border-color: var(--gu-text); border-right-color: transparent; }

.gu-card {
  background: var(--gu-surface-1); border: 0; border-radius: var(--gu-radius-md);
  padding: var(--gu-sp-6); box-shadow: var(--gu-shadow-1); color: var(--gu-text);
}
.gu-card--he {
  position: relative; min-height: var(--gu-card-he-min-h); padding: var(--gu-card-he-pad); border-radius: var(--gu-card-he-radius);
  background: var(--gu-card-he-bg); border-color: var(--gu-card-he-border);
  transition: transform var(--gu-dur-2) var(--gu-ease), border-color var(--gu-dur-2) var(--gu-ease), box-shadow var(--gu-dur-2) var(--gu-ease);
}
.gu-card--he:hover { transform: var(--gu-card-he-lift); border-color: var(--gu-card-he-border-hover); box-shadow: var(--gu-glow-blue); }
.gu-card--toi { background: var(--gu-be-mat-toi); color: var(--gu-text-tren-toi); border-color: transparent; }

.gu-field { display: grid; gap: var(--gu-sp-2); color: var(--gu-label-text); font-size: var(--gu-fs-mo-ta); font-weight: var(--gu-fw-strong); }
.gu-field__help { color: var(--gu-help-text); font-weight: var(--gu-fw-body); font-size: var(--gu-fs-nhan); text-wrap: pretty; }
.gu-field__loi { color: var(--gu-loi-text); font-weight: var(--gu-fw-body); font-size: var(--gu-fs-nhan); text-wrap: pretty; }
.gu-input, .gu-select {
  height: var(--gu-input-h); padding: 0 var(--gu-input-pad-x); border-radius: var(--gu-input-radius); width: 100%;
  font: inherit; font-family: var(--gu-font-body); font-size: var(--gu-fs-than); font-weight: var(--gu-fw-body);
  background: var(--gu-input-bg); color: var(--gu-input-text); border: 1px solid var(--gu-input-border);
  transition: background var(--gu-dur-1) var(--gu-ease), box-shadow var(--gu-dur-1) var(--gu-ease);
}
.gu-input:hover:not(:focus):not(:disabled), .gu-select:hover:not(:focus):not(:disabled) { background: var(--gu-input-bg-hover); }
.gu-input::placeholder { color: var(--gu-input-placeholder); }
.gu-input:focus, .gu-select:focus { outline: 0; border-color: transparent; background: var(--gu-input-bg-focus); box-shadow: var(--gu-input-glow); }
.gu-input[aria-invalid="true"], .gu-select[aria-invalid="true"] { background: var(--status-error-nen); box-shadow: 0 0 0 2px rgba(219, 25, 32, .38); }
.gu-input:disabled, .gu-select:disabled { opacity: .55; cursor: not-allowed; }

.gu-badge {
  display: inline-flex; align-items: center; gap: var(--gu-sp-1); padding: var(--gu-sp-1) var(--gu-sp-3);
  border-radius: var(--gu-radius-pill); font-size: var(--gu-fs-nhan); font-weight: var(--gu-fw-strong); line-height: 1.4;
  border: 1px solid var(--status-unknown-vien); background: var(--status-unknown-nen); color: var(--gu-text-mut);
}
.gu-badge--success { background: var(--status-success-nen); border-color: var(--status-success-vien); color: var(--status-success-chu); }
.gu-badge--info { background: var(--status-info-nen); border-color: var(--status-info-vien); color: var(--status-info-chu); }
.gu-badge--warning { background: var(--status-warning-nen); border-color: var(--status-warning-vien); color: var(--status-warning-chu); }
.gu-badge--error { background: var(--status-error-nen); border-color: var(--status-error-vien); color: var(--status-error-chu); }

.gu-table { width: 100%; border-collapse: collapse; background: var(--gu-surface-1); border-radius: var(--gu-radius-md); overflow: hidden; }
.gu-table th { background: var(--gu-table-head-bg); color: var(--gu-table-head-text); text-align: left; font-size: var(--gu-fs-nhan);
  font-weight: var(--gu-fw-strong); letter-spacing: .06em; text-transform: uppercase; padding: var(--gu-table-cell-pad); }
.gu-table td { font-size: var(--gu-fs-than); padding: var(--gu-table-cell-pad); border-top: 1px solid var(--gu-table-row-border); color: var(--gu-text-2); }
.gu-table tbody tr:hover td { background: var(--gu-table-row-hover); }
/* HST10 22/09: bảng rộng (URL, nhiều cột) bị CẮT ở 375px vì overflow:hidden — mất chữ chứ không cuộn (DEC-021 ⑤). */
/* HST02 22/09: `anywhere` hạ min-content xuống MỘT ký tự ⇒ cột bị bóp, ngắt GIỮA TỪ ("TH|ÁN|G") thay vì cuộn.
   `break-word` giữ nguyên từ khi tính bề rộng cột; chỉ chuỗi dài hơn cả ô (URL) mới bẻ. Tiêu đề cột không xuống dòng. */
.gu-table td, .gu-table th { overflow-wrap: break-word; }
.gu-table th { white-space: nowrap; }
@media (max-width: 520px) { .gu-table { display: block; overflow-x: auto; } }

/* Safari iOS phóng to cả trang khi chạm vào ô nhập chữ < 16px — giữ 16px ở màn cảm ứng, máy tính dùng --gu-fs-than. */
@media (pointer: coarse) { .gu-input, .gu-select, textarea.gu-input { font-size: max(16px, var(--gu-fs-than)); } }

/* ── CHỮ THEO VAI TRÒ (DEC-20260922-023) — trang dùng lớp này thay vì tự chọn cỡ ──
   <h1 class="gu-tieu-de-trang"> · <h2 class="gu-tieu-de-muc"> · <p class="gu-mo-ta"> · <span class="gu-nhan"> */
.gu-tieu-de-trang { margin: 0; font-family: var(--gu-font-body); font-size: var(--gu-fs-trang); font-weight: var(--gu-fw-strong);
  line-height: var(--gu-lh-tieu-de); letter-spacing: -.005em; color: var(--gu-text); text-wrap: balance; }
.gu-tieu-de-muc { margin: 0; font-family: var(--gu-font-body); font-size: var(--gu-fs-muc); font-weight: var(--gu-fw-strong);
  line-height: var(--gu-lh-tieu-de); color: var(--gu-text); text-wrap: balance; }
.gu-than { font-size: var(--gu-fs-than); line-height: 1.6; color: var(--gu-text-2); text-wrap: pretty; }
.gu-mo-ta { margin: 0; font-size: var(--gu-fs-mo-ta); line-height: 1.6; color: var(--gu-text-2); max-width: var(--gu-do-dai-dong); text-wrap: pretty; }
.gu-nhan { font-size: var(--gu-fs-nhan); font-weight: var(--gu-fw-strong); color: var(--gu-text-mut); letter-spacing: .02em; }

.gu-skeleton {
  display: block; height: var(--gu-sp-3); border-radius: var(--gu-radius-sm);
  background: linear-gradient(90deg, var(--gu-skeleton-nen) 0%, var(--gu-skeleton-anh) 50%, var(--gu-skeleton-nen) 100%);
  background-size: 200% 100%; animation: gu-xuong 1.4s var(--gu-ease) infinite;
}
.gu-skeleton--khoi { height: var(--gu-skeleton-khoi-h); border-radius: var(--gu-radius-md); }

.gu-toast {
  display: flex; gap: var(--gu-sp-3); align-items: flex-start; padding: var(--gu-sp-4); border-radius: var(--gu-thong-bao-radius);
  border: 1px solid var(--status-info-vien); background: var(--status-info-nen); color: var(--status-info-chu);
  font-size: var(--gu-fs-mo-ta); box-shadow: var(--gu-shadow-1); text-wrap: pretty;
}
.gu-toast--success { border-color: var(--status-success-vien); background: var(--status-success-nen); color: var(--status-success-chu); }
.gu-toast--warning { border-color: var(--status-warning-vien); background: var(--status-warning-nen); color: var(--status-warning-chu); }
.gu-toast--error { border-color: var(--status-error-vien); background: var(--status-error-nen); color: var(--status-error-chu); }
.gu-toast--noi { position: fixed; right: var(--gu-gutter); bottom: var(--gu-gutter); z-index: var(--gu-z-thong-bao); max-width: var(--gu-toast-max); }

/* ── .gu-tabs — thanh tab (BOSS 22/09: HST09 .gi-tabs, HST04 creative-studio tab kéo giãn + tương phản 1,08:1 nền sáng) ──
   <div class="gu-tabs" role="tablist"><button class="gu-tabs__tab" role="tab" aria-selected="true">…</button>…</div>
   Ngang; điện thoại cuộn ngang (không xuống dòng, không kéo giãn); chữ dùng --gu-text-2 / --gu-chu-lam (đã đo ≥4,5 hai chế độ). */
.gu-tabs {
  display: flex; gap: var(--gu-sp-1); overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  border-bottom: 1px solid var(--gu-border); padding: 0 var(--gu-sp-1);
}
.gu-tabs::-webkit-scrollbar { display: none; }
/* Tràn ngang (HST09: Growth 10 tab) ⇒ mép mờ dần báo "còn tab"; mặt nạ không đổi màu, chỉ độ trong.
   HST09 đo 22/09: ở 1440 tab cuối bị cắt ("Hồ sơ doar") mà KHÔNG mờ vì mờ chỉ bật ≤760px. Nay: trình duyệt có
   scroll-driven animation ⇒ mờ ở MỌI bề rộng, CHỈ khi hàng tab thật sự tràn (không tràn ⇒ timeline không hoạt động ⇒
   không mờ), và hết mờ khi đã cuộn tới tab cuối. Trình duyệt cũ: giữ cách cũ (mờ luôn ở ≤760px). */
@property --gu-tabs-mep { syntax: '<length>'; inherits: false; initial-value: 0px; }
.gu-tabs {
  mask-image: linear-gradient(90deg, var(--gu-mat-na) 0, var(--gu-mat-na) calc(100% - var(--gu-tabs-mep)), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, var(--gu-mat-na) 0, var(--gu-mat-na) calc(100% - var(--gu-tabs-mep)), transparent 100%);
}
@media (max-width: 760px) { .gu-tabs { --gu-tabs-mep: var(--gu-sp-10); padding-right: var(--gu-sp-8); } }
@supports (animation-timeline: scroll()) {
  .gu-tabs { --gu-tabs-mep: 0px; animation: gu-tabs-mep linear both; animation-timeline: scroll(self inline); }
  @keyframes gu-tabs-mep { 0%, 92% { --gu-tabs-mep: 40px; } 100% { --gu-tabs-mep: 0px; } }
}
.gu-tabs__tab {
  flex: 0 0 auto; min-height: var(--gu-btn-h); padding: 0 var(--gu-sp-4); background: transparent; border: 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; white-space: nowrap;
  font: inherit; font-family: var(--gu-font-body); font-size: var(--gu-fs-than); font-weight: var(--gu-fw-strong);
  color: var(--gu-text-2); transition: color var(--gu-dur-1) var(--gu-ease), border-color var(--gu-dur-1) var(--gu-ease);
}
.gu-tabs__tab:hover { color: var(--gu-text); }
.gu-tabs__tab[aria-selected="true"], .gu-tabs__tab.on { color: var(--gu-chu-lam); border-bottom-color: var(--gu-chu-lam); }
.gu-tabs__tab:focus-visible { outline: 2px solid var(--genup-blue-2); outline-offset: -2px; border-radius: var(--gu-radius-sm); }

/* ── .gu-gate — hộp MỜI ĐĂNG KÝ/ĐĂNG NHẬP · PHIÊN HẾT (DEC-20260922-022; mã: GENUP_PHIEN trong genup-phien.js) ── */
:root {
  --gu-gate-max: 440px;
  /* ẢNH GENUP GỐC (gấu trúc đỏ áo GENUP gõ cửa nhà UP, 1672×941) — OWNER 22/09 qua HTQT-B: màn chờ + hộp mời PHẢI dùng ảnh này.
     Đường TƯƠNG ĐỐI theo tệp CSS này ⇒ đúng cả ở /assets (production) lẫn trang mẫu docs. Cùng ảnh với GENUP_TRANG_THAI. */
  --gu-anh-man-cho: url('genup-trang-thai.webp');
  --gu-anh-man-cho-ti-le: 1672 / 941;
}
.gu-gate {
  position: fixed; inset: 0; z-index: var(--gu-z-hop-thoai); display: grid; place-items: center;
  padding: var(--gu-gutter); background: var(--gu-overlay); animation: gu-hien var(--gu-dur-2) var(--gu-ease);
}
.gu-gate__hop {
  position: relative; width: 100%; max-width: var(--gu-gate-max); padding: var(--gu-sp-8) var(--gu-sp-6) var(--gu-sp-6);
  background: var(--gu-card-he-bg); border: 1px solid var(--gu-card-he-border); border-radius: var(--gu-radius-lg);
  box-shadow: var(--gu-shadow-2); color: var(--gu-text); animation: gu-noi var(--gu-dur-2) var(--gu-ease);
}
.gu-gate__anh { margin: calc(var(--gu-sp-8) * -1) calc(var(--gu-sp-6) * -1) var(--gu-sp-6); aspect-ratio: var(--gu-anh-man-cho-ti-le);
  background: var(--gu-anh-man-cho) center / cover no-repeat, var(--gu-be-mat-toi); border-radius: var(--gu-radius-lg) var(--gu-radius-lg) 0 0; }
.gu-gate__tieu-de { margin: 0; font-family: var(--gu-font-display); font-weight: 400; font-size: var(--gu-fs-xl);
  line-height: var(--gu-lh-display); letter-spacing: var(--gu-ls-display); text-transform: uppercase; padding-right: var(--gu-sp-8); }
.gu-gate__mo-ta { margin: var(--gu-sp-3) 0 0; color: var(--gu-text-2); font-size: var(--gu-fs-mo-ta); text-wrap: pretty; line-height: var(--gu-lh-body); }
.gu-gate__nut { display: flex; flex-wrap: wrap; gap: var(--gu-sp-3); margin-top: var(--gu-sp-6); }
.gu-gate__nut .gu-btn { flex: 1 1 160px; }
.gu-gate__dong { position: absolute; top: var(--gu-sp-3); right: var(--gu-sp-3); font-size: var(--gu-fs-lg); }
html.gu-gate-mo { overflow: hidden; }

/* ── .gu-man-chao — màn chào trang chủ ≤1,5 s, bỏ qua được (JS không hiện khi prefers-reduced-motion) ── */
.gu-man-chao {
  position: fixed; inset: 0; z-index: var(--gu-z-thong-bao); display: grid; place-content: center; gap: var(--gu-sp-3);
  text-align: center; background: var(--gu-hero-bg); color: var(--gu-text);
  transition: opacity var(--gu-dur-2) var(--gu-ease);
}
.gu-man-chao--tat { opacity: 0; pointer-events: none; }
.gu-man-chao__anh { width: min(560px, 86vw); aspect-ratio: var(--gu-anh-man-cho-ti-le); margin: 0 auto var(--gu-sp-2);
  background: var(--gu-anh-man-cho) center / cover no-repeat, var(--gu-be-mat-toi); border-radius: var(--gu-radius-lg);
  box-shadow: var(--gu-shadow-2); animation: gu-noi var(--gu-dur-2) var(--gu-ease); }
.gu-man-chao__logo { font-family: var(--gu-font-display); font-size: var(--gu-fs-hero); line-height: var(--gu-lh-display);
  letter-spacing: var(--gu-ls-display); animation: gu-noi var(--gu-dur-2) var(--gu-ease); }
.gu-man-chao__logo b { font-weight: 400; color: var(--gu-hero-nhan-do); }
.gu-man-chao__phu { font-size: var(--gu-fs-xs); letter-spacing: var(--gu-ls-eyebrow); text-transform: uppercase; color: var(--gu-text-mut); }
.gu-man-chao__bo { position: absolute; right: var(--gu-gutter); bottom: var(--gu-gutter); }

@keyframes gu-hien { from { opacity: 0; } to { opacity: 1; } }
@keyframes gu-noi { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes gu-quay { to { transform: rotate(360deg); } }
@keyframes gu-xuong { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .gu-skeleton, .gu-btn[aria-busy="true"]::after { animation: none; }
  .gu-btn, .gu-card--he, .gu-input, .gu-select { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   LUẬT KHÔNG VIỀN — LỚP TOÀN HỆ THỐNG (OWNER 29/09/2026)
   "Input/field dùng filled surface; hover/focus đổi tone hoặc glow mềm, không để viền sáng cố
   định … sửa từ design token/component chung để toàn hệ thống cùng đổi, không vá từng trang."
   Token ở trên làm mọi `border: … var(--gu-border*)` thành vô hình. Lớp này lo phần CSS riêng
   từng trang còn tự tô viền cho Ô NHẬP và NÚT: `!important` vì <style> của trang nạp SAU tệp này.
   Ngoại lệ: trang mô phỏng giao diện BÊN NGOÀI GENUP (form cửa hàng, Google Sheets — B-5) khai
   `data-ngoai-genup` trên <html>. Ô tích/radio/thanh trượt/chọn màu/tệp giữ dạng gốc.
   ═══════════════════════════════════════════════════════════════════════════════════════ */
html:not([data-ngoai-genup]) :is(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]):not(:is(.hkey, .chat-o, [data-o-ghep]) *):not([type=hidden]), select, textarea:not(:is(.hkey, .chat-o, [data-o-ghep]) *)) {
  border-color: transparent !important;
  background-color: var(--gu-input-bg) !important;
  transition: background-color var(--gu-dur-1) var(--gu-ease), box-shadow var(--gu-dur-1) var(--gu-ease);
}
html:not([data-ngoai-genup]) :is(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]):not(:is(.hkey, .chat-o, [data-o-ghep]) *), select, textarea:not(:is(.hkey, .chat-o, [data-o-ghep]) *)):hover:not(:focus):not(:disabled) {
  background-color: var(--gu-input-bg-hover) !important;
}
html:not([data-ngoai-genup]) :is(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]):not(:is(.hkey, .chat-o, [data-o-ghep]) *), select, textarea:not(:is(.hkey, .chat-o, [data-o-ghep]) *)):focus {
  border-color: transparent !important;
  background-color: var(--gu-input-bg-focus) !important;
  box-shadow: var(--gu-input-glow) !important;
  outline: 0 !important;   /* glow là dấu tiêu điểm; `none` để lại outline-width 3px vô hình mà bộ đo vẫn đọc */
}
/* hộp chọn gốc của trình duyệt: danh sách thả xuống theo nền tối/sáng của trang, chữ theo token */
html:not([data-ngoai-genup]) select { color: var(--gu-input-text); }
html:not([data-ngoai-genup]):not([data-theme="light"]) select { color-scheme: dark; }
/* NÚT: không viền bao. Nút phụ nhận ra bằng khối lấp đầy (--gu-btn-secondary-bg), nút chính bằng nền đỏ. */
html:not([data-ngoai-genup]) button:not([role=switch]) { border-color: transparent !important; }
/* `outline-style:none` nhưng `outline-width` mặc định vẫn là 3px — không vẽ gì, nhưng bộ đo tương phản
   (doTuongPhanChu) đọc chiều rộng mà không xét kiểu nét, rồi đo một đường không tồn tại (1,09–1,5).
   Đặt 0 khi KHÔNG lấy tiêu điểm bằng bàn phím: hình không đổi, vòng :focus-visible vẫn nguyên. */
html:not([data-ngoai-genup]) :is(input, select, textarea):not(:focus-visible) { outline-width: 0; }

