/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   🏠 BỘ LUẬT GIAO DIỆN CỦA TRANG CHỦ (`/`, `Components/Pages/TongQuan.razor`)
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   ⭐ ĐỢT 1572 (việc o878) — TÁCH RA TỪ KHỐI `<style>` NỘI TUYẾN CỦA CHÍNH TRANG CHỦ.
   Anh Tiến 30/08/2026: *"tiếp tục đồ hoạ và phát triển trang đăng nhập, hộp đăng nhập, hộp đổi mật
   khẩu và trang chủ"*.

   📏 VÌ SAO TÁCH — số đo, ⛔ không phải cảm tính:
   Khối `<style>` nội tuyến nằm TRONG thân HTML nên nó **⛔ không nhớ đệm được**: mỗi lượt mở trang
   chủ, mỗi người, mỗi ngày đều tải lại từ đầu. Đo 31/08/2026: **31.514 ký tự**, trong đó **18.543
   là chú thích** (58,8%) — tức phần lớn thứ gửi xuống trình duyệt là chữ viết cho lập trình viên
   đọc. Trang chủ là màn hình mở nhiều nhất của **433 tài khoản**.
   ⇒ Sang tệp riêng thì trình duyệt nhớ đệm **30 ngày** (`Program.cs` đặt `max-age` cho tài nguyên
   tĩnh có `?v=`) và tải **nén brotli**. Chú thích vì thế ⛔ không còn phải trả giá mỗi lượt mở trang
   — nên chúng được **giữ NGUYÊN VĂN** ở đây, ⛔ đừng rút gọn: đó là tri thức *"vì sao làm thế"*,
   và quy tắc #14 của CLAUDE.md cấm dọn chú thích mã nguồn.

   ⚠ VỊ TRÍ NẠP LÀ MỘT PHẦN CỦA LUẬT — `App.razor` nạp tệp này **SAU CÙNG**. Khối `<style>` đời cũ
   render trong `<body>`, tức sau MỌI thẻ `<link>`, nên nó thắng theo THỨ TỰ ở mọi cặp luật cùng độ
   đặc hiệu; và chính chú thích của luật `.trang-chu .card:not(.tt3d)` bên dưới đã dặn rõ điều đó
   (*"khối style nội tuyến này nằm TRONG trang nên nạp SAU app.css"*). Đưa tệp lên trước là đổi cán
   cân ấy một cách **lặng lẽ** — build xanh, test xanh, chỉ vài thẻ đổi bóng đổ ở nền tối.

   ⚰ CÙNG LƯỢT NÀY ĐÃ XOÁ 22 LUẬT CHẾT của khối chào `.tc-hero` (chết từ đợt 667, 14/08/2026 — xem
   chú thích ⚰ trong `TongQuan.razor`). Đo sống trước khi xoá: 11/11 lớp ấy ⛔ không trúng một phần
   tử nào trên trang, ở cả hai chủ đề.

   🔒 CHỨNG MINH KHÔNG LỆCH: `node cong-cu/do-song-trang-chu.mjs --luu <tệp>` chụp bản nền rồi
   `--so <tệp>` đối chiếu lại — **2 chủ đề × 39 khối × 28 thuộc tính** cộng bề rộng/cao thật, tràn
   ngang và chiều cao toàn trang. ⛔ Đừng verify bằng ảnh chụp màn hình: trang chủ có nền động và
   ảnh nền gieo theo phiên nên hai ảnh KHÔNG BAO GIỜ trùng nhau.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ⚰ ĐỢT 1572 (việc o878) — ĐÃ XOÁ 15 LUẬT CỦA KHỐI CHÀO `.tc-hero` (3.744 ký tự) + 7 luật
   cổ điển đè lên chúng (562 ký tự). Chúng CHẾT từ **đợt 667** (14/08/2026), khi anh Tiến bảo
   *"ở trang chủ, đưa dòng chào đó lên thanh nav"* — khối chào dời sang `Layout/DaiChaoNav.razor`,
   component ấy có **CSS cách ly riêng** nên ⛔ không dùng một dòng nào ở đây.
   🔑 Chú thích đời 667 hẹn *"giữ lại vì chúng cũng nuôi phần nền động của trang, dọn ở đợt riêng
     nếu thật sự thừa"* — nay ĐÃ ĐO và câu ấy SAI: nền động của trang là `.tc-nen-kho` +
     `.tc-nen-phu` (khai bên dưới), hai lớp khác hẳn. Đo sống 31/08/2026 bằng Chrome thật trên
     `/`: **11/11 lớp `.tc-*` của khối chào ⛔ không trúng một phần tử nào**, ở CẢ hai chủ đề.
   ⚠ `.tc-logo-chip` vẫn sống ở `Pages/TrangChieu.razor` — nhưng trang ấy **tự khai luật riêng**
     trong khối `<style>` của chính nó, ⛔ không ăn theo đây. Đã kiểm trước khi xoá.
   ↩ Cần dựng lại thì lấy ở `git show <commit trước 1572>:…/TongQuan.razor`. */

/* ⭐ ĐỢT 931 (việc o150) — chừa `.tt3d`: bốn ô thẻ thống kê nay mang khối 3D riêng (khai ở app.css).
   🔴 Vì sao phải chừa TẠI ĐÂY chứ không nâng độ đặc hiệu bên app.css: khối style nội tuyến này nằm TRONG
     trang nên nạp SAU app.css, mà luật nền tối `:root[data-theme="dark"] .trang-chu .card` có cùng
     (0,4,0) với luật thẻ 3D ⇒ nó thắng nhờ thứ tự. Đo sống 21/08: ở nền SÁNG bóng inset của thẻ 3D
     ăn đúng, ở nền TỐI thì bị luật này nuốt, trả về `0 6px 22px rgba(0,0,0,.35)` — hỏng LẶNG LẼ,
     chỉ một trong hai giao diện. ⛔ Đừng gỡ `:not(.tt3d)` ra. */
/* Thẻ dữ liệu kiểu kính — CHỈ trong trang chủ, không đụng card toàn app */
.trang-chu .card:not(.tt3d) { border: 1px solid rgba(10, 61, 145, .14); border-radius: 14px;
          box-shadow: 0 6px 22px rgba(0, 23, 68, .07);
          transition: transform .18s ease, box-shadow .18s ease; }
.trang-chu .card:not(.tt3d):hover { transform: translateY(-2px); box-shadow: 0 12px 30px rgba(0, 23, 68, .13); }
.trang-chu .card-header { font-weight: 600;
          background: linear-gradient(90deg, rgba(10, 61, 145, .07), transparent);
          border-bottom-color: rgba(10, 61, 145, .10); }

/* Nền tối hiện đại */
:root[data-theme="dark"] .trang-chu .card:not(.tt3d) { border-color: rgba(120, 180, 255, .18);
          box-shadow: 0 6px 22px rgba(0, 0, 0, .35); }
:root[data-theme="dark"] .trang-chu .card-header {
          background: linear-gradient(90deg, rgba(120, 180, 255, .10), transparent);
          border-bottom-color: rgba(120, 180, 255, .15); }

/* CỔ ĐIỂN (mặc định của anh): dáng phẳng chữ nhỏ — hero thu phẳng, tắt animation + hover lift */
          background: linear-gradient(90deg, #002169, #0a3d91); box-shadow: none; }
:root[data-theme^="co-dien"] .trang-chu .card { border-radius: 4px; box-shadow: none; transition: none; }
:root[data-theme^="co-dien"] .trang-chu .card:hover { transform: none; box-shadow: none; }

/* ═══════════ ĐỢT 450 — DẢI NÚT BẤM NHANH (ô LỐI TẮT) ═══════════
   Anh Tiến 11/08/2026: *"đây là sẽ trang thống kê nhiệm vụ và danh sách các nút bấm nhanh dẫn đến
   các trang khác nhau, nút bấm cần đồ hoạ 3D có hiệu ứng, đẹp, hiện đại"*.
   Khung xương (lưới, cỡ chữ) để NGOÀI cổng giao diện — cổ điển vẫn phải xếp hàng ngay ngắn;
   chỉ phần TRANG TRÍ (khối nổi, vệt sáng, nhún) mới bọc :root:not([data-theme^="co-dien"]).
   ⚠ Tên lớp cố ý KHÔNG dùng `.nut-nhanh` — tên đó đã thuộc về cụm nút trên thanh trên (MainLayout
   + co-dien.css); trùng tên là hai nơi giành nhau kiểu dáng. */
/* ⭐ ĐỢT 684 — `auto-fit` THAY `auto-fill` (anh Tiến 15/08/2026: *"danh sách các nút đến các app
   phân bố đều sang 2 bên"*).
   📏 Khác nhau đúng ở chỗ anh thấy: `auto-fill` GIỮ LẠI các cột rỗng cuối hàng, mỗi cột rỗng ăn một
     phần `1fr` ⇒ hàng có 4 nút trên màn hình rộng thì 4 nút đứng túm bên trái, phần phải bỏ trắng.
     `auto-fit` XẸP các cột rỗng ⇒ số nút có thật chia đều trọn bề ngang, mép trái và mép phải cân nhau.
   ⚠ `minmax(10.5rem, 1fr)` giữ nguyên: đó là bề ngang tối thiểu để chữ trong ô không vỡ dòng. */
/* ĐỢT 684d — cột hẹp lại (10,5rem → 9rem) vì ô nay xếp NGANG và không còn dòng mô tả:
   9 ô của nhóm "Việc hằng ngày" về đúng MỘT hàng ở khổ 1400 px trở lên. */
.dai-loi-tat { display: grid; gap: .55rem; perspective: 1000px;
               grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
/* opacity .7 chứ không .62: đo đợt 463 thấy .62 chỉ còn 4,45:1 ở giao diện sáng — hụt ngưỡng 4,5. */
.lt-nhan { font-size: .78rem; letter-spacing: .04em; text-transform: uppercase;
           opacity: .7; margin: 1rem 0 .35rem; }
.lt-nhan:first-child { margin-top: 0; }
.o-loi-tat { display: flex; flex-direction: column; align-items: flex-start;
             padding: .7rem .75rem; min-height: 6.3rem; position: relative; overflow: hidden;
             text-decoration: none; color: inherit; }
.o-loi-tat:hover, .o-loi-tat:focus { text-decoration: none; color: inherit; }
/* ⛔ ĐỢT 463 — CHỮ PHẢI NẰM TRÊN LỚP TRANG TRÍ. Vệt sáng quét ngang là `::after` position:absolute,
   còn ba lớp chữ dưới đây là static ⇒ theo thứ tự vẽ của CSS, phần tử absolute vẽ SAU, tức vệt sáng
   phủ ĐÈ LÊN CHỮ lúc rê chuột (ước lượng dưới vệt: .lt-mo 1,49–1,53:1 · .lt-ten 1,81–1,87). Cho chữ
   `position: relative; z-index: 1` và vệt `z-index: 0` là chữ lên trên, vệt vẫn quét như cũ.
   ⓘ Con số dưới vệt là SUY LUẬN từ quy tắc thứ tự vẽ + độ trong của vệt, CHƯA đo bằng mắt (khung
   trình duyệt không dựng được trạng thái :hover để chụp). Vá vẫn đúng vì chữ phải nằm trên trang trí
   trong mọi trường hợp. */
.lt-icon { width: 2.3rem; height: 2.3rem; margin-bottom: .4rem; border-radius: .65rem;
           display: inline-flex; align-items: center; justify-content: center;
           font-size: 1.3rem; line-height: 1; position: relative; z-index: 1; }
.lt-ten { font-weight: 600; font-size: .95rem; line-height: 1.2; position: relative; z-index: 1; }
/* ⚠ ĐỢT 537 — `.lt-mo` để .7 thì RỚT NGƯỠNG RIÊNG Ở GIAO DIỆN CỔ ĐIỂN (đo sống 3,91:1 · 15 ô),
   ba giao diện kia vẫn đạt. Chỉ cổ điển dính vì ở đó chữ trong ô lối tắt lấy màu LIÊN KẾT
   (≈rgb(6,69,173)) chứ không phải màu chữ thân trang ⇒ CÙNG một độ mờ cho kết quả khác hẳn.
   ⇒ Nâng .7 → .85: cổ điển 3,91 → 5,53. Đúng vết xe `.lt-nhan` ngay bên trên (463 phải nâng .62 → .7):
   độ mờ đặt trên chữ nhỏ là chỗ tương phản hay rơi nhất, và nó rơi KHÁC NHAU theo từng giao diện. */
.lt-mo { font-size: .75rem; line-height: 1.25; opacity: .85; margin-top: .12rem;
         position: relative; z-index: 1; }

/* Màu chip biểu tượng theo NHÓM việc — chỉ để quét mắt cho nhanh, không mang nghĩa lợi/bất lợi. */
.lt-xanh { --lt1: #3d7ad6; --lt2: #0a3d91; }
.lt-luc  { --lt1: #3fc088; --lt2: #12794b; }
.lt-cam  { --lt1: #ffa85c; --lt2: #F47B20; }
.lt-tim  { --lt1: #a98cf0; --lt2: #5b3fc0; }
.lt-do   { --lt1: #f4818a; --lt2: #c62b3a; }
.lt-xam  { --lt1: #a3adba; --lt2: #5b6672; }

/* ── Khối 3D (ba giao diện hiện đại) ── nền dốc + gờ sáng trên + bóng đổ dưới = ô nhô khỏi mặt trang.
   ⛔ KHÔNG dùng translateZ cho chip biểu tượng: ô có overflow:hidden (để cắt vệt sáng), mà overflow
      khác `visible` thì trình duyệt DẸP PHẲNG không gian 3D con — thẻ vẫn chạy nhưng không nhô. */
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat {
    border: 1px solid rgba(10, 61, 145, .16); border-radius: .85rem;
    background: linear-gradient(180deg, #ffffff, #eef2f9);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .95) inset,
                0 6px 14px rgba(0, 23, 68, .13), 0 1px 2px rgba(0, 23, 68, .16);
    transition: transform .18s ease-out, box-shadow .18s ease-out;
}
/* Vạch màu chạy trên đỉnh ô — vừa là chỉ dấu nhóm, vừa làm mép trên trông có bề dày. */
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat::before {
    content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--lt1), var(--lt2));
}
/* Vệt sáng quét ngang khi rê chuột — thứ làm mặt ô trông như kính bóng. */
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat::after {
    content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .7), transparent);
    transform: skewX(-18deg); opacity: 0; z-index: 0;   /* ĐỢT 463: xuống DƯỚI chữ (xem .lt-* ở trên) */
    transition: left .55s ease-out, opacity .25s ease-out;
}
:root:not([data-theme^="co-dien"]) .dai-loi-tat .lt-icon {
    background: linear-gradient(160deg, var(--lt1), var(--lt2));
    box-shadow: 0 1px 0 rgba(255, 255, 255, .45) inset, 0 4px 9px rgba(0, 23, 68, .28);
    transition: transform .18s ease-out, box-shadow .18s ease-out;
}
/* Nhô lên + ngả nhẹ ra sau (perspective ở lưới cha) — "3D có hiệu ứng" anh Tiến yêu cầu. */
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover {
    transform: translateY(-4px) rotateX(6deg) scale(1.015);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .95) inset,
                0 16px 28px rgba(0, 23, 68, .22), 0 2px 5px rgba(0, 23, 68, .18);
}
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover::after { left: 115%; opacity: 1; }
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover .lt-icon {
    transform: scale(1.08) translateY(-1px);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 7px 14px rgba(0, 23, 68, .34);
}
/* LÚN XUỐNG khi bấm — cùng ngôn ngữ với dải tab và nút Xin nghỉ phép (đợt 447). */
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:active {
    transform: translateY(1px) scale(.995);
    box-shadow: 0 2px 6px rgba(0, 23, 68, .3) inset;
}

/* Nền TỐI: hạ nền ô xuống, gờ sáng mảnh lại, vệt quét dịu đi (nền tối mà quét trắng gắt là chói).
   Đặt SAU khối trên vì cùng độ ưu tiên — thắng nhau bằng thứ tự dòng. */
:root[data-theme="dark"] .dai-loi-tat .o-loi-tat {
    border-color: #3a3f47; color: #dde1e6;
    background: linear-gradient(180deg, #2c313a, #23272e);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .07) inset, 0 6px 16px rgba(0, 0, 0, .45);
}
:root[data-theme="dark"] .dai-loi-tat .o-loi-tat::after {
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .16), transparent);
}
:root[data-theme="dark"] .dai-loi-tat .o-loi-tat:hover {
    box-shadow: 0 1px 0 rgba(255, 255, 255, .08) inset, 0 16px 30px rgba(0, 0, 0, .6);
}

/* CỔ ĐIỂN (mặc định của anh): ô phẳng, khung mảnh, xếp khít — CỐ Ý trông như phần mềm đời cũ.
   ⚠ Vẫn giữ ĐỦ chữ (tên + mô tả): bỏ trang trí thì được, bỏ NỘI DUNG thì người dùng cổ điển mất
   thông tin — hai giao diện chỉ được khác nhau ở cái áo. */
/* ĐỢT 684 — cũng đổi sang `auto-fit` (lý do ở luật `.dai-loi-tat` phía trên): hai giao diện chỉ
   được khác nhau ở CÁI ÁO, không được khác ở chỗ nút dồn về một bên hay dàn đều. */
:root[data-theme^="co-dien"] .dai-loi-tat { gap: .35rem; perspective: none;
               grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); }
:root[data-theme^="co-dien"] .dai-loi-tat .o-loi-tat {
    border: 1px solid #b7b7b7; border-radius: 3px; background: #f3f3f3;
    min-height: 0; padding: .35rem .5rem; box-shadow: none; }
:root[data-theme^="co-dien"] .dai-loi-tat .o-loi-tat:hover { background: #e8eef7; }
:root[data-theme^="co-dien"] .dai-loi-tat .lt-icon {
    width: auto; height: auto; margin-bottom: .1rem; font-size: 1rem;
    background: none; border-radius: 0; box-shadow: none; }
:root[data-theme="co-dien-toi"] .dai-loi-tat .o-loi-tat {
    border-color: #4a4a4a; background: #2a2a2a; color: #d8d8d8; }
:root[data-theme="co-dien-toi"] .dai-loi-tat .o-loi-tat:hover { background: #343434; }

/* ═══════════ ⭐ ĐỢT 684 — TRANG CHỦ VỪA KHUNG MÀN HÌNH ═══════════
   Anh Tiến 15/08/2026: *"ở trang chủ bố trí theo hướng thể hiện đúng trong khung màn hình không cần
   cuộn để xem… tối ưu cho màn hình 23-27inch, với màn hình nhỏ hơn thì cho phép cuộn, với màn hình
   lớn hơn thì cho phép phóng to theo tỷ lệ"*.

   📏 ĐO TRƯỚC KHI SỬA (máy dev, cửa sổ 1280×721, tài khoản quản trị — người thấy NHIỀU khối nhất):
     trang cao **1.844 px**. Ba khoản lớn nhất: bảng chấm công **668** · dải lối tắt **469** ·
     dải 3 ảnh kho **126**. ⇒ Đợt này cắt hai khoản đầu bằng cách ĐÚNG NGHĨA (dời ảnh lên nav, thu
     bảng chấm công lại) chứ không phải bằng cách thu nhỏ chữ — thu nhỏ chữ là đẩy cái giá sang mắt
     người đọc, mà bảng chấm công là thứ nhìn cả ngày.
   📏 Ba mức lề dưới đây bù nốt phần còn lại: mỗi khối bớt ~.5rem lề là trang ngắn thêm ~40–60 px.

   📐 NỚI BỀ NGANG Ở MÀN HÌNH RỘNG — đây mới là thứ làm trang VỪA KHUNG ở 24":
     cột nội dung của app khóa ở 1400 px (`.content` trong MainLayout) nên trên màn 1920 px dải lối
     tắt chỉ xếp được **7 cột cho 9 ô ⇒ tràn sang hàng thứ hai (+85 px)**, trong khi hai bên còn
     **260 px bỏ trắng**. Cho riêng trang chủ dùng tới 1680 px là 9 ô về **một hàng** — vừa ngắn lại
     vừa đúng câu *"phân bố đều sang 2 bên"* anh giao cùng lượt.
     ⚠ NỚI Ở CHÍNH CỘT NỘI DUNG (`.content:has(.trang-chu)`), KHÔNG kéo `.trang-chu` rộng hơn cha
       bằng lề âm: cột nội dung có `padding-left 56px / padding-right 24px` (lệch nhau 32 px, dấu vết
       của rail biểu tượng cũ) ⇒ căn giữa bằng lề âm là trang lệch phải 16 px. Nới ở cột cha thì phép
       `margin-inline: auto` sẵn có tự căn, và trang chủ lệch **y như mọi trang khác** — nhất quán.
     ⚠ Cũng KHÔNG dùng `transform: translateX` để căn: `transform` biến khối thành KHỐI CHỨA của mọi
       hậu duệ `position: fixed` — đúng bẫy đã trả giá ở đợt 649/679 (hộp hội thoại của bàn làm việc).
     ⓘ `:has()` chưa hỗ trợ (trình duyệt quá cũ) thì luật rơi về 1400 px như trước — không vỡ gì.

   🔍 PHÓNG TO THEO MÀN HÌNH — dùng `zoom` chứ KHÔNG phải `transform: scale`:
     `zoom` phóng cả HỘP (chiều cao thật đổi theo) nên bố cục và phép cuộn vẫn đúng; `scale` chỉ kéo
     hình, để lại đúng chỗ cũ một khoảng trống và làm chuột bấm lệch.
     · dưới 2000 px : 1,00 — **đây là khổ 23–24" (1920×1080), khổ anh chốt phải VỪA KHÔNG CUỘN** ⇒
                      tuyệt đối không phóng, phóng là đẩy trang dài ra đúng chỗ đang vừa khít.
     · 2000–2999 px : 1,10 — 27" 2K (2560×1440): cao 1.440 px nên còn thừa chỗ, chữ to lên cho dễ đọc.
     · từ 3000 px   : 1,22 — 4K / màn siêu rộng, không để trang chủ thành dải chữ nhỏ giữa biển trắng.
   ⛔ KHÔNG khóa `overflow: hidden` để "ép vừa màn hình": màn hình nhỏ hơn PHẢI cuộn được — ép vừa là
     cắt mất phần dưới, đúng thứ anh không muốn. Ở đây chỉ làm trang NGẮN LẠI, còn cuộn thì để nguyên. */
.trang-chu > .card, .trang-chu > .row { margin-bottom: .75rem !important; }
.trang-chu .lt-nhan { margin-top: .6rem; }

/* ⚖ HAI MÉP PHẢI BẰNG NHAU (anh Tiến: *"phân bố đều sang 2 bên"*). Cột nội dung đang có
   `padding-left: 56px !important` (app.css) — lề chừa cho RAIL BIỂU TƯỢNG bên trái, mà rail ĐÃ BỎ ở
   đợt 645 ⇒ nay chỉ còn là 32 px lệch: đo thật ở 1920 px là mép trái 136 px / mép phải 104 px.
   ⇒ Trả về đều nhau CHO RIÊNG TRANG CHỦ. ⛔ Cố ý KHÔNG sửa luật gốc trong app.css: nó áp cho MỌI
     trang của mọi phân hệ — đúng loại "chỗ dùng chung" mà quy tắc #18 dặn đừng đụng nhân tiện.
     Việc dọn lề thừa cho toàn app đã ghi vào VIEC-SAP-LAM để làm thành đợt riêng, có đo đủ. */
.content:has(.trang-chu) { padding-left: 1.5rem !important; }

/* ⭐ ĐỢT 1481 (việc o684) — NỚI CỘT BẰNG BIẾN `--tran-cot-noi-dung`, ⛔ KHÔNG đặt thẳng `max-width`.
   Anh Tiến 29/08/2026: *"băng rôn 2 bên bị vỡ to với màn hình lớn hơn 27 inch"*.
   🔴 Lượt nới của đợt 684d ĐÚNG việc nó phải làm, nhưng nó nới cột nội dung mà **⛔ không ai báo cho
     hai tấm biểu ngữ dọc hai bên hông** — chúng vẫn tính dải trống theo 1400px ⇒ ĐÈ LÊN nội dung
     **164px mỗi bên** ở khổ 1920px, **120px** ở khổ 2048px (đo tận tay 29/08 trên bản tĩnh).
     Hỏng LẶNG LẼ: build xanh, test xanh, chỉ mắt người mới thấy.
   ⇒ Nay đặt lại chính con số ấy trên `:root` để MỌI nơi cùng đọc. ⛔ Đừng trả về `.content:has(…)`:
     biểu ngữ là `position: fixed` nằm ngoài cây con của `.content` nên biến khai ở đó nó ⛔ không
     bao giờ thấy — mà "không thấy" thì rơi về giá trị lui, ⛔ không một câu lỗi nào.
   ⓘ Trình duyệt không hiểu `:has()` thì luật rơi về 1400px như trước — ⛔ không vỡ gì, và ngưỡng ẩn
     1528px của biểu ngữ khi ấy lại là con số đúng.

   🩸 ⭐ ĐỢT 1580 (việc o885) — VẾ `calc(100vw - 128px)` LÀ CHỖ CHỪA CHO HAI BIỂU NGỮ, ⛔ ĐỪNG BỎ.
     Anh Tiến 31/08/2026: *"ở trang chủ mất băng rôn 2 bên"*.
     🔴 Đợt 1481 chữa vế "biểu ngữ ĐÈ LÊN nội dung" bằng cách cho trang chủ một NGƯỠNG ẨN riêng
       1888px. Nó đúng phần đè, nhưng cái giá là **trang chủ mất hẳn hai tấm ở mọi khổ dưới 1888px** —
       tức ở đúng khổ màn phổ biến nhất. Đo sống 31/08 (Chrome thật, tài khoản `tienvm`, so trang chủ
       với `/cong-viec` ở cùng khổ):
         · 1528px … `/cong-viec` treo 2 tấm 40px · trang chủ **0 tấm**
         · 1536px … `/cong-viec` treo 2 tấm 44px · trang chủ **0 tấm**   ← màn 1920 tỉ lệ 125% Windows
         · 1700px … `/cong-viec` treo 2 tấm 96px · trang chủ **0 tấm**
         · 1888px … cả hai treo — trang chủ chỉ bắt đầu có từ đây
     🔑 **Dải 1528–1599px là chỗ luật cũ SAI hẳn, ⛔ không phải chỉ khắt khe**: nhánh nới cột này bắt
       đầu từ 1600px, nên dưới 1600 trang chủ có cột **y hệt** mọi trang thường (1400px) — dải trống
       ở 1536px đo được **68px**, thừa chỗ — mà hai tấm vẫn bị ẩn.
     ⇒ Chữa ở GỐC: cột nội dung của trang chủ tự **chừa lại 128px** = 2 × (40px dải tối thiểu + 24px
       khe thở) — khớp `LuatBieuNguHong.RongDaiToiThieuPx` + `.KheThoPx`, hàng rào đối chiếu tận nơi.
       Nhờ thế trang chủ **luôn còn đủ dải trống từ 1528px trở lên**, dùng chung ĐÚNG MỘT ngưỡng với
       mọi trang khác ⇒ nhánh ẩn riêng 1888px và hằng số `RongManHinhToiThieuTrangChuPx` đã BỎ.
     📏 Giá phải trả, đo tận tay trước khi chốt: cột nội dung hẹp lại **≤64px** và CHỈ ở dải
       1600–1887px (1600: 1536→1472 · 1700: 1632→1572 · 1800: 1728→1672 · 1887: 1760→1759 · từ
       1888px trở lên **⛔ không đổi một pixel**). Chốt ngược ở đúng thứ đợt 684d dựng ra vế nới này:
       ba dải lối tắt vẫn **7 ô / 2 ô / 4 ô đều MỘT HÀNG** ở cả sáu khổ đo, chiều cao trang ⛔ không
       đổi, tràn ngang 0.
     ⚠ `100vw` kể cả bề rộng thanh cuộn dọc (~15px) nên khe thật có thể chỉ còn ~8,5px thay vì 16px —
       đúng bằng khe mà trang thường đã chạy từ đợt 1419, ⛔ không phải nấc mới. ⛔ Đừng hạ 128 xuống
       cho cột rộng thêm: cái mất là hai tấm biểu ngữ, hoặc dòng chữ đầu tiên bị che. */
@media (min-width: 1600px) {
    :root:has(.trang-chu) { --tran-cot-noi-dung: min(96vw, 1760px, calc(100vw - 128px)); }
}

/* ═══ ⭐ ĐỢT 684d — Ô LỐI TẮT XẾP NGANG, GỌN LẠI ═══
   Anh Tiến 15/08/2026 (kèm ảnh chụp trang chủ đang phải cuộn): *"lối tắt em làm gọn các nút cho vừa
   trang nhìn, không cần cuộn xuống để xem"*.

   📏 ĐO TRƯỚC: ô cũ xếp DỌC (chip 2,3rem → tên → mô tả 2–3 dòng) cao **117 px**; 9 ô nhóm "Việc hằng
     ngày" tràn xuống hàng thứ hai ⇒ riêng thẻ Lối tắt đã **453 px**, và trang chủ ở giao diện SÁNG
     (giao diện anh đang dùng — thấy trong ảnh) là **1.056 px** trên màn 1920×950 ⇒ vẫn phải cuộn.
   ⇒ Xếp NGANG: chip nhỏ bên trái, tên một dòng ⇒ ô còn ~**46 px**, cột hẹp hơn nên 9 ô về **một hàng**.

   ⛔ MÔ TẢ ẨN KHỎI MÀN HÌNH, KHÔNG XÓA: nó vẫn nằm trong `title` của ô (`OLoiTat` bắt buộc có `Title`)
     — đúng luật giao diện của dự án *"hướng dẫn nghiệp vụ nằm trong title, không in thường trực"*.
     Rê chuột vào ô là đọc được đủ như cũ. ⚠ Đừng xóa tham số `Mo`: nó nuôi câu mô tả đó.
   ⓘ ĐỒ HỌA 3D anh yêu cầu ở đợt 450 GIỮ NGUYÊN: khối nổi, vệt sáng quét, nhún khi nhấn — chỉ đổi
     cách XẾP bên trong ô, không đụng lớp `.nut-noi`. */
.dai-loi-tat .o-loi-tat {
    flex-direction: row; align-items: center; gap: .55rem;
    min-height: 0; padding: .5rem .7rem;
}
.dai-loi-tat .lt-icon {
    width: 1.85rem; height: 1.85rem; font-size: 1.05rem; margin-bottom: 0; flex: none;
}
.dai-loi-tat .lt-ten {
    font-size: .9rem; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dai-loi-tat .lt-mo { display: none; }

@media (min-width: 2000px) {
    .trang-chu { zoom: 1.10; }
}

@media (min-width: 3000px) {
    .trang-chu { zoom: 1.22; }
}

/* ═══ ⭐ ĐỢT 687 — BA TẤM ẢNH KHO LÀM NỀN MỜ CỦA TRANG CHỦ ═══
   Anh Tiến 15/08/2026: *"ba tấm hình anh đưa em, em thử làm hình nền mờ cho trang chủ xem sao"*.

   ⓘ Đúng ba tệp anh gửi, vẫn nằm nguyên ở `wwwroot/hinh/kho/` — không thêm tệp mới, và cũng không
     thêm lượt tải nào so với trước: chính ba tấm này đang là nền màn hình đăng nhập nên trình duyệt
     phần lớn đã có sẵn trong đệm.
     🔁 **ĐỢT 878 đổi cỡ tệp**: câu cũ ở đây ghi *"bản `-nho`, 800px / 50–68 KB"*. Nay trang chủ
       dùng **bản GỐC 1600×900** vì một tấm phải kéo hết bề ngang chứ không còn là một phần ba — lý do
       đầy đủ + số đo ở khối `.tc-nen-kho` bên dưới.

   📐 CÁCH LÀM — bốn chốt an toàn, mỗi chốt vì một lý do đo được:
   ① `position: fixed` + `z-index: -1`: nền **không chiếm một pixel chiều cao nào**. Đợt 684 anh vừa
      chốt "trang chủ gọn trong một khung màn hình (950 px)" — dựng nền bằng khối thường là phá đúng
      việc đó. Fixed cũng làm nền **đứng yên khi cuộn**, mắt không bị kéo theo.
      ⚠ Đặt NGOÀI `.trang-chu` vì khối đó có `zoom` ở màn ≥2000px; `zoom` co cả hậu duệ `fixed`.
   ② **Rất mờ + rất nhạt**: `blur(22px)` và độ đục **.16** (tối: .13). Chữ trên trang chủ là số liệu
      chấm công — nền phải là *cảm giác*, không được là *hình*. Kèm một lớp phủ trắng/đen ở trên để
      tương phản chữ **không đổi một nấc nào** so với trước.
   ③ **KHÔNG chuyển động**: bài học đợt 674 — thứ động ở rìa tầm mắt làm người ta liếc theo, mà cạnh
      nó là các nút cần tập trung.
      🔁 **ĐỢT 878 ĐỔI CÁCH ĐẠT ĐIỀU ③ NÀY, không đổi chính điều ③.** Đợt 687 bày **ba tấm cùng
        lúc**, mỗi tấm một phần ba bề ngang; nay là **một tấm phủ kín**, đổi theo **lượt đăng nhập**
        (anh Tiến 19/08: *"mỗi lần chỉ hiển thị 1 ảnh"*). Vẫn **không có gì nhấp nháy** trong một
        phiên — chỉ số ảnh nằm trong thẻ xác thực nên nó đứng yên tới lượt đăng nhập sau.
   ④ **Màn hẹp dưới 992px thì TẮT HẲN**:
      ⚠ Đừng gõ dấu bé-hơn trần trong chú thích CSS của tệp `.razor` — Razor đọc nó thành MỞ THẺ và
        ném RZ9980/RZ10007 (đã dính đúng lúc viết mục này). Viết chữ "dưới" hoặc dùng `&lt;`.
      Trên điện thoại các thẻ xếp thành một cột kín màn hình, nền gần như không lộ ra ⇒ tải một tấm
      ảnh về để không ai nhìn thấy là trả tiền băng thông cho hư không, mà đó lại đúng là nơi băng
      thông đắt nhất. *(Lý do CŨ ghi ở đây — "mỗi phần ba chỉ còn ~100px" — đã hết nghĩa từ đợt 878:
      nay chỉ còn MỘT tấm phủ kín, không còn phần ba nào.)*
      ⓘ Nhánh cổ điển bên dưới **giữ nguyên chữ, cố ý không dọn** — quy tắc #20: đóng băng phát
        triển, KHÔNG xóa. Từ đợt 808 `data-theme` chỉ còn `light`/`dark` nên chúng không khớp ai nữa.
   ⛔ Không dùng `backdrop-filter` trên thẻ: nó buộc trình duyệt vẽ lại vùng dưới mỗi thẻ ở MỌI lượt
      cuộn — trang chủ là trang 433 tài khoản đều mở (nguyên tắc X). Làm mờ MỘT LẦN ở chính lớp nền
      thì rẻ hơn hẳn. */
/* 📏 ĐỘ ĐỤC .60 — CHỐT BẰNG CÁCH ĐO TẬN MẮT, không đoán.
   Đăng nhập thật bằng `tienvm` trên máy dev (màn 1400×860, giao diện cổ điển — đúng giao diện anh
   Tiến đang dùng) rồi thử ba nấc:
     · .16 kèm lớp phủ trắng 62–86%  ⇒ **KHÔNG THẤY GÌ** (mã chạy, màn hình trống — đèn xanh giả)
     · .38 kèm lớp phủ 30–62%        ⇒ vẫn gần như không thấy
     · **.60 kèm lớp phủ 8–28%**     ⇒ thấy rõ mà không chối: trời xanh ở dải trên, sắc ấm ở hai mép
   ⓘ Vì sao phải cao thế mới thấy: trang chủ **gần kín thẻ trắng đục**, nền chỉ lộ ra ở khe giữa các
     thẻ và hai mép — tổng diện tích nhìn thấy rất nhỏ, nên độ đục thấp là mất hút.
   ⚠ Chính vì chữ đều nằm TRÊN THẺ, nâng độ đục **không hạ độ đọc của một dòng nào**. */
/* 🔁 ANH TIẾN CHỈNH NGAY SAU KHI XEM BẢN ĐẦU: *"hình mờ quá anh muốn thấy thêm chi tiết"*
   ⇒ **hạ độ nhòe 22px → 6px** và **nâng độ đục .60 → .78**, lớp phủ nhẹ thêm một nấc.
   ⓘ Độ nhòe mới vẫn đủ để nền KHÔNG tranh chữ (6px làm nhòe hết nét chữ/vật nhỏ trên ảnh, chỉ còn
     hình khối lớn: bồn, mái nhà, hàng cây, mặt nước), nhưng anh nhận ra được đang là cảnh gì.
   ⚠ Đừng hạ xuống 0: ảnh nét thì mọi đường viền trong ảnh cắt ngang khe giữa các thẻ, mắt tự bám vào
     đó thay vì vào con số. */
/* ⭐ ĐỢT 878 (việc o109) — MỘT ẢNH PHỦ KÍN, ĐỔI THEO LƯỢT ĐĂNG NHẬP (anh Tiến 19/08/2026:
   *"mỗi lần chỉ hiển thị 1 ảnh, và làm nó rõ hơn một tí"*). Thay cho ba tấm chia ba cột của đợt 687.
   🔑 **Ảnh gieo theo PHIÊN ĐĂNG NHẬP, ⛔ không theo lượt tải trang** — chỉ số nằm trong THẺ XÁC
     THỰC (`LuatAnhNenTheoLuot.TenClaim`, đóng một lần ở `Program.cs`) nên nó **đứng yên suốt phiên**.
     Đây là chỗ dễ làm ngược nhất: trang chủ dựng TƯƠNG TÁC ⇒ `OnInitializedAsync` chạy **hai lượt**
     (dựng sẵn rồi dựng lại). Gieo bằng một bộ đếm là ảnh **NHẢY ngay trước mắt** ở lượt thứ hai —
     đúng cái nhấp nháy mà yêu cầu của anh cấm. *(Trang đăng nhập thì ngược lại: nó dựng TĨNH và
     chưa có phiên nào để gieo, nên ở đó mốc xoay là LƯỢT MỞ TRANG — xem `LayoutTrong.razor`.)*
   📏 **Dùng bản GỐC 1600×900, không còn bản `-nho`** — và đây là phép đo, không phải sở thích:
     · Lý do cũ của `-nho` là *"ảnh đã mờ 22px nên bản lớn không thêm một nét nào"*. Độ nhòe nay chỉ
       còn **3px**, mà một tấm phải kéo hết bề ngang thay vì một phần ba ⇒ bản 800px bị phóng gấp
       đôi, nhòe thành vệt — tức là **làm ngược đúng chữ "rõ hơn" của anh**.
     · Cái giá gần như bằng không: trước đây **cả ba** bản `-nho` đều được tải mỗi lượt mở trang
       (**173,5 KB**); nay **một** bản gốc (158,4 · 174,8 · 221,8 KB — **trung bình 181,0 KB**), và
       là **một** lượt tải thay vì ba. Đo bằng `ls -l wwwroot/hinh/kho/` ngày 19/08/2026.
   ⓘ Ảnh nền nằm ở thuộc tính `style` nội tuyến nên không mang `?v=` — cùng lý do đã ghi ở
     `LayoutTrong.razor`: tên tệp cố định, ảnh không đổi theo bản phát hành. */
.tc-nen-kho { position: fixed; inset: 0; z-index: -1; pointer-events: none;
              background-position: center; background-size: cover; background-repeat: no-repeat;
              filter: blur(3px) saturate(1.12); opacity: .88; }
/* Lớp phủ giữ TƯƠNG PHẢN CHỮ: sáng dần về giữa trang, nơi có nhiều chữ nhất */
.tc-nen-phu { position: fixed; inset: 0; z-index: -1; pointer-events: none;
              background: radial-gradient(ellipse at 50% 40%,
                          rgba(255,255,255,.22) 0%, rgba(255,255,255,.12) 55%, rgba(255,255,255,.05) 100%); }
/* ⭐ ĐỢT 878 — nền tối cũng "rõ hơn một tí": .46 → .58. ⚠ KHÔNG nâng ngang bằng nền sáng
   (.88): nền tối làm ảnh nổi hơn hẳn, để bằng nhau là ảnh át cả chữ — đúng lý do đợt 687 đã
   tách riêng hai con số này. */
:root[data-theme="dark"] .tc-nen-kho { opacity: .58; }
:root[data-theme="dark"] .tc-nen-phu {
              background: radial-gradient(ellipse at 50% 40%,
                          rgba(16,18,24,.46) 0%, rgba(16,18,24,.30) 55%, rgba(16,18,24,.18) 100%); }
/* CỔ ĐIỂN — vẫn CÓ nền, chỉ NHẠT HƠN (.10).
   ⚠ Bản đầu của đợt 687 tắt hẳn ở cổ điển theo luật "cổ điển phẳng nguyên trạng". ĐO THẬT ngay sau
     đó: tài khoản `tienvm` (chính anh Tiến) đang chạy `data-theme="co-dien"` ⇒ anh bấm vào trang chủ
     sẽ KHÔNG THẤY GÌ, mà đây lại đúng là thứ anh vừa bảo "thử xem sao". Tắt ở đúng người đặt hàng là
     một kiểu đèn xanh giả: mã có chạy, màn hình thì trống.
   ⓘ Luật "cổ điển phẳng" nhắm vào KHỐI NỔI · BÓNG ĐỔ · HOẠT HOẠ — một tấm nền tĩnh, mờ, không bóng
     không chuyển động thì không phá cái phẳng. Vẫn hạ độ đục để cổ điển nhạt hơn hai giao diện kia. */
/* Cổ điển SÁNG dùng đúng .60 như trên (đây là bản đã đo tận mắt). Hai giao diện TỐI thì hạ xuống:
   nền tối làm ảnh nổi hơn hẳn, để .60 là ảnh át cả chữ. */
:root[data-theme="co-dien-toi"] .tc-nen-kho { opacity: .46; }
:root[data-theme="co-dien-toi"] .tc-nen-phu {
              background: radial-gradient(ellipse at 50% 40%,
                          rgba(26,26,26,.46) 0%, rgba(26,26,26,.30) 55%, rgba(26,26,26,.18) 100%); }
@media (max-width: 991.98px) {
    .tc-nen-kho, .tc-nen-phu { display: none; }
}

/* ═══ ⭐ ĐỢT 1577 (việc o882) — TRANG CHỦ DỰNG LÊN THEO LỚP, VÀ NHÃN NHÓM CÓ VẠCH ĐỒ HOẠ ═══

   Anh Tiến 31/08/2026: *"anh cần thêm các hiệu ứng ấn tượng và hiện đại, chữ cũng cần đồ hoạ"*.

   🔴 CHỪNG MỰC Ở ĐÂY LÀ MỘT YÊU CẦU KỸ THUẬT, ⛔ không phải sự dè dặt. Hai màn hình đăng nhập là
     BỘ MẶT — người ta nhìn vài giây rồi đi; trang chủ thì **mở hàng chục lượt mỗi ngày, suốt tám
     tiếng, cho 433 tài khoản**. Vì thế mọi thứ thêm vào đây đều phải thoả ba điều:
       ① chạy **đúng một lượt** khi mở trang (⛔ không `infinite` — một vệt sáng chạy vô tận trên trang
          làm việc là thứ kéo mắt cả ngày);
       ② tổng thời gian **dưới 0,75 giây** kể cả ô cuối cùng — quá mức đó là người ta cảm thấy phải CHỜ;
       ③ chỉ động vào `opacity` + `transform`, hai thuộc tính hợp ảnh trên GPU.

   🔴 `animation-fill-mode` PHẢI LÀ `backwards`, ⛔ TUYỆT ĐỐI KHÔNG `both`/`forwards`. Đây là chỗ dễ
     làm hỏng nhất và nó hỏng LẶNG LẼ: khai báo trong hoạt hoạ **thắng luật thường** ở tầng cascade,
     nên `forwards` giữ lại `transform: none` của khung hình cuối và **đè chết** luật nhấc ô khi rê
     chuột (luật `hover` của ô lối tắt) — ô thôi nhấc lên, mà build vẫn xanh,
     test vẫn xanh, chỉ tay người rê vào mới biết. `backwards` chỉ áp trạng thái ĐẦU trong lúc chờ
     `animation-delay` rồi nhả hẳn quyền cho luật thường.
   ⚠ Máy khai "giảm chuyển động" tắt sạch nhờ khối toàn cục `* !important` ở `app.css` (mục 10 đợt
     381) — lúc ấy các khối hiện thẳng, ⛔ không khối nào bị bỏ lại ở trạng thái mờ.
   ⚠ Dãy thẻ bám lớp mốc TỰ KHAI `.tt-dai` (khai ở `KhoiTheThongKe.razor`), ⛔ không bám lớp lưới
     Bootstrap: trang chủ có nhiều `.row`, đoán theo `.col-*` là trúng cả dãy khác trong im lặng. */
.trang-chu .tt-dai > [class*="col-"] { animation: tc-vao-khoi .5s ease-out backwards; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(1) { animation-delay: .04s; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(2) { animation-delay: .11s; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(3) { animation-delay: .18s; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(4) { animation-delay: .25s; }

/* Ô lối tắt vào theo làn — bảy ô đầu đủ để mắt đọc ra nhịp; ô thứ tám trở đi vào cùng ô thứ bảy,
   ⛔ đừng kéo dài chuỗi delay: dải có lúc hơn 20 ô, ô cuối sẽ hiện sau cả giây (vi phạm điều ② trên). */
.dai-loi-tat > .o-loi-tat { animation: tc-vao-khoi .42s ease-out backwards; }
.dai-loi-tat > .o-loi-tat:nth-child(1) { animation-delay: .06s; }
.dai-loi-tat > .o-loi-tat:nth-child(2) { animation-delay: .10s; }
.dai-loi-tat > .o-loi-tat:nth-child(3) { animation-delay: .14s; }
.dai-loi-tat > .o-loi-tat:nth-child(4) { animation-delay: .18s; }
.dai-loi-tat > .o-loi-tat:nth-child(5) { animation-delay: .22s; }
.dai-loi-tat > .o-loi-tat:nth-child(6) { animation-delay: .26s; }
.dai-loi-tat > .o-loi-tat:nth-child(n+7) { animation-delay: .30s; }

@keyframes tc-vao-khoi {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

/* NHÃN NHÓM có vạch chuyển sắc dẫn trước chữ — phần "đồ hoạ" của trang chủ nằm ở ĐÂY chứ ⛔ không
   nằm ở mặt chữ.
   🔴 ⛔ TUYỆT ĐỐI ĐỪNG tô `.lt-nhan` bằng `background-clip: text` như tên app ở màn đăng nhập: chữ
     này đã mang `opacity: .7`, và con số ấy là **kết quả đo** của đợt 463 — hạ xuống .62 thì tương
     phản còn 4,45:1, hụt ngưỡng 4,5. Một dải chuyển sắc đặt lên đó là hạ tương phản thêm một lần nữa
     ở đúng chỗ vừa phải nâng lên. Vạch thì ⛔ không phải chữ ai đó đọc, nên nó tự do mang màu. */
.lt-nhan { display: flex; align-items: center; gap: .45rem; }
.lt-nhan::before {
    content: "";
    flex: 0 0 auto;
    width: 16px; height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, #F47B20, rgba(244, 123, 32, 0));
}

/* ═══ ⭐ ĐỢT 1912 (việc o1174) — NHỊP VÀO TRANG PHỦ HẾT MÀN HÌNH, VÀ HAI PHẢN HỒI TAY MỚI ═══

   Anh Tiến 03/09/2026: *"tiếp tục làm tất cả công việc tại trang chủ và trang đăng nhập hãy phát
   triển các hiệu ứng đẹp hơn"*.

   🔴 BA ĐIỀU KIỆN CỦA ĐỢT 1577 VẪN LÀ LUẬT Ở ĐÂY — ⛔ đừng đọc chữ *"đẹp hơn"* thành *"được phép
     động nhiều hơn"*: ① chạy ĐÚNG MỘT LƯỢT khi mở trang (⛔ không `infinite`) · ② tổng thời gian
     dưới **0,75 giây** kể cả ô cuối · ③ chỉ động vào `opacity` + `transform`.
     ⇒ Từ đợt này ba điều ấy **CÓ MÁY CANH**: `HieuUngTrangChuTests` đọc chính tệp này và làm build
       ĐỎ khi ai đó phá một trong ba. Tới trước đợt 1912 chúng chỉ nằm trong chú thích, tức chỉ sống
       bằng trí nhớ của phiên kế tiếp.

   📏 ĐO TRƯỚC KHI SỬA (Chrome THẬT qua khung CDP, tài khoản `tienvm`, khổ 1400×900, giao diện sáng):
     nhịp vào trang chỉ phủ **18 phần tử** — 4 thẻ thống kê + 14 ô lối tắt. Ba nút của bàn làm việc
     và dải sinh nhật **hiện phựt ngay**, vì chúng nằm NGOÀI `<div class="trang-chu">` (đứng ngoài là
     CỐ Ý — khối ấy có `zoom` ở màn ≥2000px, xem chú thích trong `TongQuan.razor`), nên bộ chọn
     `.trang-chu …` của đợt 1577 ⛔ không với tới. Mắt đọc ra ngay chỗ lệch: phần TRÊN đứng sẵn còn
     phần DƯỚI mới trôi vào — nhịp chạy ngược từ dưới lên.
   ⇒ Bù đúng chỗ thiếu, và bù bằng lớp RIÊNG của hai khối ấy (`.blv-*` · `.sn-dai`) chứ ⛔ không nới
     bộ chọn ra `body > *`: đã grep 03/09 — ⛔ KHÔNG trang nào khác dựng `KhoiBanLamViec` hay
     `KhoiSinhNhat`, nên luật vẫn nằm gọn trong trang chủ dù tệp CSS này được nạp cho mọi trang.
   ⚠ Delay của hai khối mới phải NHỎ HƠN bộ số cũ (thẻ .04–.25 · ô lối tắt .06–.30): chúng nằm TRÊN
     màn hình, mà nhịp phải chạy từ trên xuống — ⛔ đừng để nó nhảy cóc.

   🔴 HOẠT HOẠ ĐẶT TRÊN **NÚT**, ⛔ TUYỆT ĐỐI KHÔNG TRÊN THẺ `.blv-the`. Đây là chỗ hỏng lặng lẽ đã
     có sẵn lời cảnh báo trong mã: `.blv-the.mo .blv-than` (hộp khai đơn) là `position: fixed`, mà
     một tổ tiên **đang mang `transform`** thì trở thành KHỐI CHỨA của mọi hậu duệ `fixed` ⇒ hộp khai
     đơn neo theo thẻ thay vì theo màn hình (đúng bẫy đã trả giá ở đợt 649 · 679). Hoạt hoạ vào-trang
     có `translateY`, tức trong 0,42 giây đầu thẻ THẬT SỰ mang transform. `.blv-dau` là **anh em**
     của `.blv-than`, ⛔ không phải tổ tiên, nên đặt ở đó là an toàn tuyệt đối.
   🔴 `backwards` chứ ⛔ không `both`/`forwards` — lý do đầy đủ ở khối ĐỢT 1577 ngay trên: khai báo
     trong hoạt hoạ thắng luật thường ở tầng cascade, nên `forwards` ghim `transform: none` của khung
     hình cuối và ĐÈ CHẾT luật nhấc ô khi rê chuột. */
.blv-day > .nut-mo-bang,
.blv-day > .blv-the > .blv-dau,
.sn-dai { animation: tc-vao-khoi .42s ease-out backwards; }
.blv-day > .nut-mo-bang { animation-delay: .02s; }
.blv-day > .blv-the:nth-of-type(1) > .blv-dau { animation-delay: .06s; }
.blv-day > .blv-the:nth-of-type(2) > .blv-dau { animation-delay: .10s; }
.sn-dai { animation-delay: .14s; }

/* ── CON SỐ CỦA BỐN THẺ THỐNG KÊ NẢY LÊN MỘT NHỊP SAU THẺ ──
   🔑 Vì sao đặt trên `.tt3d-so` chứ ⛔ không trên cả thẻ: thẻ đã có nhịp riêng (đợt 1577) và đang
     mang khối 3D + vệt quét của `app.css`; chồng thêm một `transform` lên chính nó là hai hoạt hoạ
     tranh nhau MỘT thuộc tính — thứ thắng là thứ khai sau, mà "sau" ở đây do THỨ TỰ NẠP TỆP quyết
     định. `.tt3d-so` là thẻ bọc RIÊNG của con số (khai ở `app.css`, đợt 931), ⛔ không mang hoạt hoạ
     nào khác.
   ⚠ Delay = delay của thẻ cha **+ 0,08s**, và thời lượng rút còn .38s để ô cuối cùng vẫn về đích
     trước mốc 0,75s của điều ②: 0,25 + 0,08 + 0,38 = **0,71s**. ⛔ Đừng nới thời lượng cho "mượt
     hơn" — mốc ấy là điều kiện, ⛔ không phải sở thích.
   ⚠ ⛔ KHÔNG động vào cỡ chữ (`font-size`): đổi cỡ chữ là bắt trình duyệt xếp lại chữ ở từng khung
     hình (điều ③), và con số nhảy cỡ giữa lúc đọc là thứ làm người ta đọc nhầm. `scale` chỉ phóng
     ảnh đã vẽ. */
.trang-chu .tt-dai > [class*="col-"] .tt3d-so { animation: tc-so-nay .38s cubic-bezier(.2, .9, .3, 1) backwards; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(1) .tt3d-so { animation-delay: .12s; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(2) .tt3d-so { animation-delay: .19s; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(3) .tt3d-so { animation-delay: .26s; }
.trang-chu .tt-dai > [class*="col-"]:nth-child(4) .tt3d-so { animation-delay: .33s; }
@keyframes tc-so-nay {
    from { opacity: 0; transform: scale(.86); }
    to   { opacity: 1; transform: none; }
}

/* ── VẠCH DẪN TRƯỚC NHÃN NHÓM TỰ VẼ RA ──
   Vạch chuyển sắc của đợt 1577 đang hiện sẵn ở khung hình đầu; cho nó **kéo dài ra từ mép trái** là
   phần "đồ hoạ chữ" ấy có nhịp giống ô lối tắt ngay dưới nó, mà vẫn ⛔ không đụng tới MẶT CHỮ (khối
   1577 đã cấm tô chữ nhãn nhóm — nó mang `opacity: .7`, con số đo của đợt 463).
   ⚠ `transform-origin: left center` là phần bắt buộc: mặc định `50% 50%` thì vạch nở ra từ GIỮA, tức
     nó rời khỏi mép trái rồi quay lại — trông như một lỗi vẽ chứ ⛔ không phải một nét dẫn. */
.lt-nhan::before { transform-origin: left center; animation: tc-vach-ra .45s ease-out .08s backwards; }
@keyframes tc-vach-ra {
    from { opacity: 0; transform: scaleX(0); }
    to   { opacity: 1; transform: none; }
}

/* ── Ô LỐI TẮT: VIỀN NHẬN MÀU CỦA NHÓM KHI TAY CHẠM TỚI ──
   Ô lối tắt đã nhô lên + có vệt sáng quét (đợt 450/463), nhưng VIỀN thì đứng nguyên một màu navy mờ
   cho cả sáu nhóm màu ⇒ lúc rê chuột, thứ duy nhất nói *"ô này thuộc nhóm nào"* vẫn chỉ là vạch 3px
   trên đỉnh. Cho viền mượn đúng `--lt2` của nhóm là ô sáng lên **đúng màu của chính nó**.
   🔑 `color-mix` chứ ⛔ không gõ sáu màu mờ bằng tay: sáu nhóm × hai nền = 12 giá trị phải nuôi tay,
     mà `--lt2` đã là nguồn sự thật sẵn có ngay trên.
   ⚠ Trình duyệt ⛔ không hiểu `color-mix` thì **cả khai báo bị vứt** ⇒ viền giữ nguyên màu cũ, ⛔
     không vỡ gì — đây là chiều fail đúng, và cũng là lý do ⛔ đừng viết nó vào `border` shorthand
     (vứt shorthand là mất luôn `border-style`, viền biến mất — bài học đợt 831).
   ⚠ Luật này phải đứng SAU luật `:hover` của đợt 450 ở trên: cùng độ đặc hiệu (0,5,0) thì thắng thua
     theo THỨ TỰ. ⛔ Đừng dời nó lên đầu tệp cho "gần họ hàng". */
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover,
:root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:focus-visible {
    border-color: color-mix(in srgb, var(--lt2) 42%, transparent);
}

/* Người khai "giảm chuyển động" trong Windows: tắt mọi animation, giữ nguyên màu */
@media (prefers-reduced-motion: reduce) {
    .trang-chu .card { transition: none; }
    /* Ô lối tắt: bỏ phần NHÚN/QUÉT, giữ nguyên khối nổi (đó là hình dạng nút, không phải hiệu ứng) */
    :root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat,
    :root:not([data-theme^="co-dien"]) .dai-loi-tat .lt-icon { transition: none; }
    :root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover { transform: none; }
    :root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover .lt-icon { transform: none; }
    :root:not([data-theme^="co-dien"]) .dai-loi-tat .o-loi-tat:hover::after { left: -60%; opacity: 0; }
}