    /* ⓘ ĐỢT 1430 — MỌI LUẬT CỦA LỚP NỀN (ảnh trôi · video · mạng lưới hạt sáng · màn lọc tối) đã dời
       sang `NenTrinhDienTiepKhach.razor`. ⛔ Đừng chép chúng về đây: hai chỗ cùng khai một lớp thì
       thắng thua theo THỨ TỰ nạp, và lỗi đó ⛔ không có câu báo nào. */

    /* ═══ MÀN TRÌNH DIỄN ═══
       `position: fixed` để thoát khỏi khung flex căn giữa của `.dn-nen` và phủ kín màn hình — đây là
       màn hình treo tường, ⛔ không phải một thẻ nội dung. */
    .tk-man {
        position: fixed; inset: 0; z-index: 5;
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        text-align: center; color: #eaf1ff; overflow: hidden;
        font-feature-settings: "tnum";
    }

    /* ⚠ BỐN SỐ Z-INDEX DƯỚI ĐÂY ĂN KHỚP VỚI LỚP NỀN, ⛔ đừng xê dịch một mình:
         `NenTrinhDienTiepKhach` giữ 0 (ảnh) · 1 (video) · 2 (màn lọc tối) · 3 (mạng lưới + vệt quét),
         nên mọi thứ NGƯỜI TA ĐỌC phải nằm từ 4 trở lên. Hạ xuống 2 như trước đợt 1430 là chữ chui
         xuống dưới màn lọc tối và mạng lưới — mờ đi mà build vẫn sạch, test vẫn xanh. */
    .tk-lop { position: relative; z-index: 4; }

    /* ═══ ⭐ ĐỢT 1577 (việc o882) — MÀN HÌNH DỰNG LÊN THEO LỚP, ⛔ KHÔNG BẬT RA CÙNG MỘT LÚC ═══

       Anh Tiến 31/08/2026: *"anh cần thêm các hiệu ứng ấn tượng và hiện đại"*. Bốn khối của màn trình
       diễn nay hiện **lần lượt** trong ~1,2 giây đầu: dải nhận diện → bảng đồng hồ → vệt cam →
       khẩu hiệu. Đây là thứ người đứng ở sảnh nhìn thấy mỗi lượt màn hình bật lại.

       🔑 CHẠY ĐÚNG MỘT LƯỢT (`infinite` ⛔ không có ở đây) và chỉ động vào `opacity` + `transform` —
         hai thuộc tính trình duyệt hợp ảnh trên GPU. ⛔ Đừng đưa `filter`/`width`/`top` vào keyframes:
         ở khổ chữ của màn treo tường, mỗi khung hình là một lượt xếp chữ lại (bài học "giật giật"
         đợt 1464).

       🔴 `animation-fill-mode: both` LÀ BẮT BUỘC. Thiếu nó thì trong khoảng `animation-delay` khối
         vẫn hiện đủ ở trạng thái cuối rồi mới **nháy về mờ** đúng lúc hoạt hoạ bắt đầu — tức là làm
         ra đúng cái nháy mà đợt 1492 vừa đi chữa. Với `both`, khối nhận trạng thái ĐẦU ngay từ giây 0.

       ⚠ ⛔ ĐỪNG gộp bốn khối vào một hoạt hoạ đặt trên `.tk-lop`: `.tk-lop` là cha của ba trong bốn
         khối, hoạt hoạ ở đó cho cả cụm bật ra một lượt — mất hẳn nhịp "lần lượt", mà lại thêm một
         tầng xếp mới bọc quanh đồng hồ.
       ⚠ ⛔ ĐỪNG áp cho `.tk-thanh-nut`: thanh nút đã có luật hiện/ẩn riêng theo cử động chuột
         (`.tk-hien-nut`, 10 giây tự ẩn — anh chốt ở đợt 1420). Thêm hoạt hoạ vào màn ở đó là hai
         cơ chế cùng giành một thuộc tính `opacity`, và cái thua sẽ thua **trong im lặng**.
       ⚠ Máy khai "giảm chuyển động" tắt hết nhờ khối toàn cục ở `app.css` (mục 10 đợt 381) — lúc ấy
         bốn khối hiện thẳng, ⛔ không khối nào bị bỏ lại ở trạng thái mờ.

       🧨 ⛔ ĐỪNG gom bốn dòng `animation` thành một khối riêng đặt ở đây cho dễ đọc — bản đầu của
         chính đợt 1577 làm thế và **ba bài của `LuatManHinhTiepKhachTests` đỏ ngay**: chúng cắt thân
         luật theo lần khai ĐẦU TIÊN của lớp, nên một khối trùng tên đứng trước khối gốc làm bộ dò
         đọc nhầm chỗ. ⇒ Mỗi dòng `animation` nay nằm TRONG khối gốc của chính lớp ấy (tìm chữ
         "ĐỢT 1577" ở bốn khối `.tk-dinh` · `.tk-dong-ho` · `.tk-vet` · `.tk-khau-boc`). */

    @keyframes tk-vao-man {
        from { opacity: 0; transform: translateY(18px); }
        to   { opacity: 1; transform: none; }
    }
    /* Bảng đồng hồ vào bằng một nhịp PHÓNG NHẸ chứ ⛔ không trôi lên như ba khối kia — nó là khối
       lớn nhất màn hình, cho nó trôi 18px là cả mảng sáng dịch chuyển, đọc ra thành giật. */
    @keyframes tk-vao-man-phong {
        from { opacity: 0; transform: scale(.94); }
        to   { opacity: 1; transform: none; }
    }

    /* ── dải nhận diện trên cùng ── */
    .tk-dinh {
        /* ⭐ ĐỢT 1577 (việc o882) — nhịp 1/4 của lượt dựng màn hình. Xem khối "MÀN HÌNH DỰNG LÊN
           THEO LỚP" ở đầu tệp; ⛔ đừng tách dòng này ra một khối riêng. */
        animation: tk-vao-man .85s cubic-bezier(.22, .9, .3, 1) both;
        position: absolute; top: 0; left: 0; right: 0; z-index: 4;
        display: flex; align-items: center; justify-content: center; gap: clamp(.6rem, 1.4vw, 1.4rem);
        padding: clamp(.9rem, 2.2vh, 2rem) 1rem;
    }
    /* ⭐ ĐỢT 1438 (việc o634) — LOGO PHẢI NẰM TRONG CHIP SÁNG, ⛔ đừng đặt trần lên nền tối.
       Anh Tiến báo kèm ảnh 28/08/2026: *"logo trang chủ bị chìm"*. Đo tận tay tệp
       `wwwroot/logo-petrolimex.svg` (giải PNG base64 bên trong rồi đếm pixel): **0 pixel sáng**, độ
       sáng trung bình **17,1/255**, 93,4% pixel tối hơn 80 ⇒ đây là bản logo dựng cho nền SÁNG. Đặt
       trần lên màn trình diễn nền tối thì chìm, mà `drop-shadow` của bản đợt 1420 chỉ làm nó chìm
       THÊM — bóng đen viền quanh một hình vốn đã đen.
       🔑 KHUÔN CÓ SẴN, ⛔ đừng chế cách mới: thanh nav (đợt 362y — *"nền nav tối nên bọc thẻ trắng bo
       góc cho logo nổi"*), chip nav hiện đại (đợt 373 — *"logo làm nổi bật, không bị lẫn màu gốc"*) và
       hai sa bàn chiếu kín màn hình (`.sb-logo-chip` ở app.css) đều đã bọc logo trong chip sáng vì
       ĐÚNG lý do này. Màn hình tiếp khách của đợt 1430 là chỗ THỨ TƯ đặt logo trên nền tối và là chỗ
       duy nhất quên áp ⇒ đây là hồi quy của một luật đã có, ⛔ không phải yêu cầu mới. Giá trị chép
       đúng `.sb-logo-chip` để bốn chỗ nói cùng một ngôn ngữ.
       ⛔ ĐỪNG "chữa" bằng `filter: invert()` hay `brightness()`: navy + cam là BỘ NHẬN DIỆN thương
       hiệu, đảo màu ra một logo SAI MÀU mà màn hình vẫn trông có lý — anh Tiến đã một lần bác bản vẽ
       phỏng (đợt 385) đúng vì lẽ ấy. Muốn bỏ chip thì phải có tệp logo ÂM BẢN chính thức từ bộ nhận
       diện, đè vào `logo-petrolimex.svg` và GIỮ NGUYÊN TÊN. */
    .tk-logo-chip {
        display: inline-flex; align-items: center; justify-content: center;
        background: rgba(255, 255, 255, .95);
        border-radius: 12px; padding: .3rem .45rem;
        flex-shrink: 0;
        box-shadow: 0 4px 18px rgba(0, 0, 0, .45);
    }
    /* GIỮ TỶ LỆ (anh dặn 08/08): chỉ đặt CHIỀU CAO, `width: auto` + `max-width: none` để không luật
       nào ép bề ngang làm méo chữ thương hiệu. */
    .tk-logo-chip img { height: clamp(30px, 4.2vh, 58px); width: auto; max-width: none; display: block; }
    /* ═══ ⭐ ĐỢT 1999 (việc f45) — HUY HIỆU SỰ KIỆN (EURO 5 · E10) ĐỨNG KẾ CHIP LOGO, CAO BẰNG CHIP ═══
       Anh Tiến 05/09/2026: *"em tiếp tục làm chủ đề, trang chủ và trang đăng nhập"*.
       🔑 `HuyHieuChuDe.razor.css` khai tem cao 2,15rem — đó là cỡ của THANH NAV (34px, cố định). Màn
         tiếp khách là màn treo tường: chip logo cao theo khung nhìn (ảnh `clamp(30px, 4.2vh, 58px)` +
         đệm .3rem trên dưới), một con tem 34px đứng cạnh chip 68px trên màn 4K là một mảnh lọt thỏm.
       ⇒ Tem cao ĐÚNG bằng chip: cùng công thức chiều cao ảnh, cộng đúng phần đệm của chip. Sửa cỡ
         logo thì sửa CẢ HAI dòng — hàng rào `HuyHieuChuDeTrenManChieuTests` chỉ canh «`height` có
         `vh`», ⛔ không canh hai số khớp nhau; chỗ này phải nhớ bằng mắt.
       ⚠ Luật này THẮNG luật trong tệp CSS cách ly của component nhờ THỨ TỰ NẠP (tệp này nạp trong
         THÂN trang, sau `TKNB.Web.styles.css` ở đầu trang), ⛔ không nhờ độ đặc hiệu — cả hai cùng
         (0,2,0). Dời thẻ nạp lên đầu trang là luật này thua LẶNG LẼ (đúng điều
         `CssManTiepKhachTachTepTests` đang canh).
       ⚠ Hiện/ẩn ⛔ KHÔNG khai ở đây: `.hhc-mot` mặc định `display: none`, chỉ luật mang cả
         `[data-bo-mau="<mã>"]` lẫn `[data-ma="<mã>"]` trong `HuyHieuChuDe.razor.css` mới mở — MỘT chỗ
         quyết định cho cả nav lẫn màn sảnh. Dưới 900px cụm tự ẩn theo luật của chính nó. */
    .tk-dinh .hhc-hh { height: calc(clamp(30px, 4.2vh, 58px) + .6rem); }
    /* ═══ ⭐ ĐỢT 1492 (việc o698) — TRẦN CỠ CHỮ THEO **CHIỀU CAO KHUNG NHÌN**, ⛔ ĐỪNG TRẢ VỀ TRẦN `rem` ═══
       Anh Tiến 29/08/2026: *"ở màn hình xịn hơn … khó xem"*.
       🔴 GỐC BỆNH: bốn khối chữ của màn trình diễn đều khai `clamp(sàn, Xvw, TRẦN rem)`. Trần `rem` là
         một số điểm ảnh CỐ ĐỊNH, nên từ khoảng 1920px trở lên là **chạm trần và đứng yên mãi** —
         màn hình càng lớn thì chữ càng **NHỎ ĐI so với màn hình**.
       📏 ĐO trên bản chạy thật 29/08 (bản CŨ): khổ **2560×1440** và khổ **3840×2160** cho ra **cỡ chữ
         Y HỆT NHAU** (đồng hồ 240px · ngày 36,8px · khẩu hiệu 41,6px), và khối chữ giữ nguyên bề ngang
         **1014px** ⇒ chiếm **39,6%** bề ngang ở khổ 2560 nhưng chỉ còn **26,4%** ở khổ 3840. Trên một
         màn hình treo tường 4K thì đó là một mảng chữ nhỏ lọt thỏm giữa biển ảnh.
       🔑 CHỮA BẰNG `min(Xvw, Yvh)`, ⛔ không phải bằng cách nâng trần `rem` lên một số to hơn: nâng trần
         `rem` chỉ đẩy điểm chạm trần đi xa hơn, **bệnh vẫn còn nguyên** ở khổ lớn hơn nữa. Vế `vh` mới
         là thứ trả lời đúng câu hỏi *"chữ này cao bao nhiêu phần màn hình"*.
       ⚠ Vế `vh` **cũng là cái phanh cho màn SIÊU RỘNG mà THẤP** (ultrawide 3840×1080): ở đó `vw` một
         mình cho ra cỡ chữ cao hơn cả khoảng trống đứng ⇒ khối chữ tràn khỏi màn.
       📏 Hệ số chọn sao cho **khổ thường ⛔ KHÔNG đổi gì** — đây là điều kiện bắt buộc, kẻo chữa cho màn
         4K lại làm hỏng màn 1920 mà 433 tài khoản đang dùng hằng ngày:
         · 1400×900  → y hệt bản cũ · 1920×1080 → lệch dưới 8%
         · 2560×1440 → to lên ~1,33× · 3840×2160 → to lên ~2,0×
       ⛔ Trần `rem` vẫn giữ lại (40rem / 6rem / 7rem / 5rem) làm **chốt chặn cuối**, ⛔ không phải để
         chặn trong tầm dùng thật — nó chỉ chạm ở những khổ màn hình chưa tồn tại. */
    .tk-don-vi {
        font-weight: 700; letter-spacing: clamp(1px, .28vw, 4px); line-height: 1.15;
        font-size: clamp(.95rem, min(1.7vw, 2.9vh), 5rem); text-shadow: 0 2px 14px rgba(0,0,0,.6);
    }

    /* ═══ ⭐ ĐỢT 1577 (việc o882) — CHỮ ĐỒ HOẠ: MẶT CHỮ ÁNH KIM CHO TÊN ĐƠN VỊ VÀ KHẨU HIỆU ═══

       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ạ"*.

       🔴 ⛔ TUYỆT ĐỐI KHÔNG ÁP KHUÔN NÀY CHO `.tk-gio` (đồng hồ). Anh đã bác lối chữ tô bằng nền
         `background-clip: text` ở đồng hồ **HAI LẦN** (*"màu đồng hồ bị ẩn"* đợt 1457 · *"trùng màu
         nên bị ẩn"* đợt 1464) — lý do đầy đủ nằm trong khối chú thích của `.tk-gio` ngay dưới. Hai
         khối chữ ở đây thì KHÁC HẲN ba điểm, và chính ba điểm ấy là điều kiện áp được:
         ① chúng ⛔ KHÔNG có lớp chữ thứ hai nào chồng lên (bệnh của đồng hồ là hai lớp che nhau);
         ② chúng ⛔ KHÔNG dựng bề dày 3D bằng chồng `text-shadow` — thứ đã hoá vệt lem trên nền tối;
         ③ dải màu ở đây đi TRỌN trong vùng SÁNG (trắng → lam nhạt → kem), ⛔ không có mốc sẫm nào để
            mà trùng với nền ảnh kho.

       🔴 `text-shadow: none` LÀ BẮT BUỘC, ⛔ đừng giữ lại dòng bóng cũ. Mặt chữ ở đây TRONG SUỐT
         (`text-fill-color: transparent`), mà `text-shadow` vẽ theo HÌNH chữ chứ ⛔ không theo màu chữ
         ⇒ bóng lộ nguyên qua lòng chữ thành một vệt xám bẩn nằm giữa nét. Đây đúng cái bẫy đã ghi ở
         khối `.tk-gio::after` của đợt 1562. Bóng đổ thay bằng `drop-shadow` — bộ lọc ấy áp lên HÌNH
         ĐÃ VẼ nên nó ôm đúng đường viền chữ.

       🔑 Bọc trong `@supports` để chiều fail là **CHỮ ĐẶC MÀU SÁNG như trước đợt này**: trình duyệt
         ⛔ không hiểu `background-clip: text` thì bỏ qua cả khối, giữ nguyên `color` + `text-shadow`
         khai ở trên. ⛔ Đừng gỡ lớp bọc ấy rồi khai `color: transparent` ở ngoài — máy nào không hiểu
         luật cắt nền sẽ cho ra **chữ vô hình trên màn hình treo sảnh**, mà build vẫn xanh.

       ⚠ Chỉ chạy `background-position` — ⛔ không chạm `transform`/cỡ chữ, nên trình duyệt ⛔ không
         phải xếp chữ lại lần nào (bài học "giật giật" đợt 1464). Nhịp 9 giây cố ý CHẬM: đây là màn
         hình treo tường chạy suốt ngày, một vệt sáng lướt nhanh sẽ thành thứ gây mỏi mắt.
       ⚠ Máy khai "giảm chuyển động" tự tắt phần chạy nhờ khối `prefers-reduced-motion` toàn cục —
         mặt chữ ánh kim vẫn ở lại vì nó là HÌNH, ⛔ không phải chuyển động. */
    @supports (background-clip: text) or (-webkit-background-clip: text) {
        .tk-don-vi {
            background-image: linear-gradient(100deg,
                #ffffff 0%, #dbe9ff 18%, #ffffff 34%, #ffe6c9 50%, #ffffff 66%, #dbe9ff 82%, #ffffff 100%);
            background-size: 260% 100%;
            -webkit-background-clip: text; background-clip: text;
            -webkit-text-fill-color: transparent; color: transparent;
            text-shadow: none;
            filter: drop-shadow(0 2px 12px rgba(0, 0, 0, .70));
            animation: tk-chu-anh-kim 9s linear infinite;
        }
    }
    /* ⓘ Khối `@supports` cho `.tk-khau-hieu` KHÔNG đặt ở đây mà nằm NGAY SAU luật gốc của nó (tìm
       "MẶT CHỮ ÁNH KIM CHO KHẨU HIỆU" bên dưới) — lý do ghi tại chỗ, và đó là lý do THẬT chứ ⛔ không
       phải sở thích xếp mã. */

    @keyframes tk-chu-anh-kim {
        from { background-position: 0% 50%; }
        to   { background-position: 260% 50%; }
    }
    .tk-vach { width: 2px; align-self: stretch; background: linear-gradient(180deg, transparent, #F47B20, transparent); }

    /* ═══ ĐỒNG HỒ — CHỮ SÁNG KHẮC NỔI + QUẦNG SÁNG THỞ (🔴 ĐỢT 1464, việc o662) ═══

       ⭐ Anh Tiến 28/08/2026, sau khi xem bản đợt 1457 trên máy thật, nguyên văn: *"đồng hồ trang trình
         diễn hiệu ứng 3D trùng màu nên bị ẩn, em cho hiệu ứng khác, giật giật khó nhìn"*. Đây là lần
         báo **THỨ HAI** cho cùng một hiện tượng (lần đầu: *"màu đồng hồ bị ẩn"*, đã vá ở đợt 1457) ⇒
         theo đúng lệ của kho này, nhắc lại nghĩa là **lượt trước mới chữa được cái ngọn**.

       🔴 VÌ SAO BỎ HẲN LỐI 3D CHỒNG HAI LỚP, ⛔ ĐỪNG DỰNG LẠI. Bản 1438 và bản vá 1457 cùng đi theo
         một khuôn: một lớp **chữ ĐẶC màu navy** dựng bề dày bằng chồng `text-shadow`, cộng một lớp
         **mặt kim loại** `background-clip: text`. Khuôn ấy có hai tật KHÔNG chữa được bằng cách xếp
         lại thứ tự:
         ① **Trùng màu**: bề dày 3D chỉ ra hình khi nó SẪM, mà nền màn hình cũng sẫm ⇒ mọi nét chữ đều
            viền bằng một khối navy gần trùng nền. Đợt 1457 đưa mặt kim loại lên trên nên con số hiện
            ra được, nhưng khối navy vẫn nằm đó và vẫn nuốt viền — anh vẫn đọc ra là "bị ẩn".
         ② **Giật**: nhịp giây `.tk-dap` nhấc cả khối số cỡ 15rem bằng `transform: scale()`. Ở cỡ chữ
            ấy, 1px và 0,5% là **vài điểm ảnh thật** trên màn hình treo tường, lặp lại **mỗi giây,
            suốt ngày** — đúng chữ "giật giật" anh dùng.
         ⇒ Nay: **MỘT lớp chữ, màu SÁNG gần trắng**, chiều sâu bằng viền sẫm + bóng đổ; "hiệu ứng" dời
           sang một **quầng sáng thở** nằm SAU con số, chạy bằng `opacity`/`transform` nên ⛔ không
           chạm tới việc xếp chữ. ⛔ Không còn `background-clip: text`, ⛔ không còn `attr(data-gio)`,
           ⛔ không còn nhịp giây.

       ⚠ HỆ QUẢ SANG TỆP KHÁC, ⛔ đừng bỏ sót: `tiep-khach.js` nay chỉ đặt `textContent` mỗi giây —
         đã gỡ cả `setAttribute("data-gio")` lẫn khối gắn/gỡ lớp `tk-dap`.

       ⤵ NGUYÊN VĂN KHỐI CHÚ THÍCH ĐỜI 1438/1457 — GIỮ ĐỂ HIỂU VÌ SAO ⛔ ĐỪNG QUAY LẠI, ⛔ ĐÃ HẾT HIỆU
          LỰC TỪ ĐỢT 1464:

       ~~🔴 ĐỢT 1457 (việc o655) — HAI LỚP ĐÃ ĐỔI VAI, ⛔ ĐỪNG TRẢ VỀ NHƯ CŨ.~~ Anh Tiến báo kèm ảnh
          28/08/2026: *"màu đồng hồ bị ẩn"* — con số hiện ra là một khối navy sẫm gần trùng nền, mặt
          kim loại KHÔNG hề thấy.
          Gốc bệnh, ĐO tận tay bằng `elementsFromPoint` (⛔ không phải phỏng đoán): **con ĐỊNH VỊ mang
          `z-index: -1` vẽ ĐÈ LÊN NỀN của cha nó** — đúng thứ tự vẽ của CSS: nền của phần tử lập tầng
          xếp vẽ ở bước 1, con z-index ÂM vẽ ở bước 2. Mà mặt kim loại ở bản 1438 CHÍNH LÀ **nền** của
          `.tk-gio` (`background-clip: text`) ⇒ khối dày `::before` (chữ ĐẶC màu navy, cùng chuỗi, cùng
          khung) phủ kín đúng từng nét của mặt kim loại. Chú thích cũ ghi *"z-index: 0 để `::before`
          chui xuống dưới mặt chữ"* là **hiểu ngược**: lập tầng xếp ở cha chính là thứ đẩy `::before`
          lên TRÊN nền của cha.
          ⇒ ⛔ Không có cách nào nhét một lớp xuống DƯỚI nền của chính cha nó, nên **mặt kim loại buộc
          phải là lớp TRÊN CÙNG**. Hỏng LẶNG LẼ: build sạch, test xanh, chỉ mắt người mới thấy.

       HAI LỚP CHỒNG KHÍT, ⛔ đừng gộp làm một:
       ① chữ THẬT — KHỐI DÀY. Chữ đặc màu navy sâu, chồng nhiều `text-shadow` lệch dần xuống dưới để
          dựng thành BỀ DÀY của con số (kỹ thuật extrude). Đây là thứ làm nên chiều sâu 3D.
       ② `::after` — MẶT KIM LOẠI, `z-index: 1` nên vẽ SAU CÙNG. Dải chuyển sắc trắng–xanh có vệt sáng
          bò chậm qua bề mặt (9 giây một vòng), cho cảm giác kim loại đánh bóng bắt sáng chứ ⛔ không
          phải chữ phẳng tô màu.

       🔴 VÌ SAO PHẢI TÁCH LÀM HAI LỚP — chỗ dễ làm hỏng nhất: mặt chữ dùng `background-clip: text` +
          `color: transparent`, mà với chữ TRONG SUỐT thì `text-shadow` vẽ ngay bên dưới sẽ **lộ nguyên
          ra qua lòng chữ** — bóng đổ hoá thành một vệt bẩn nằm giữa con số. Khối dày vì thế phải nằm ở
          một phần tử RIÊNG có chữ ĐẶC.

       🔴 `::after` BẮT BUỘC khai `text-shadow: none` — `text-shadow` là thuộc tính **KẾ THỪA**, không
          tắt thì mặt kim loại thừa hưởng nguyên chồng bóng navy của khối dày rồi **tự bôi đen chính
          mình** (bóng vẽ theo HÌNH chữ, ⛔ không phụ thuộc `color: transparent`). Đây là anh em của cái
          bẫy `color` mà bản 1438 đã ghi — cùng một họ: thuộc tính kế thừa rơi vào lớp không cần nó.

       🔑 `content: attr(data-gio)` ⇒ `tiep-khach.js` phải đặt CẢ `textContent` LẪN `data-gio` mỗi giây.
          Quên `data-gio` là MẶT KIM LOẠI rỗng ⇒ đồng hồ tụt về đúng khối navy chìm nghỉm của lỗi 1457;
          quên `textContent` thì khối dày đứng im ở giờ cũ, hai lớp lệch nhau, đọc ra con số nhoè đôi.
          Hàng rào `Dong_ho_3D_hai_lop_phai_duoc_JS_cap_nhat_CUNG_NHIP` canh.

       ⚠ `z-index: 0` trên `.tk-gio` GIỮ NGUYÊN nhưng vì lý do KHÁC hẳn bản cũ: nó lập một tầng xếp
         riêng để `::after` (z-index 1) chỉ trèo lên trên chữ CỦA CHÍNH NÓ, ⛔ không trèo lên hộp thoại
         đăng nhập (z-index 40) hay thanh nút (z-index 5).

       ⚠ Máy khai "giảm chuyển động" tự tắt hai hiệu ứng nhờ khối `prefers-reduced-motion` toàn cục
         (mục 10 đợt 381, `* !important`) — khối 3D thì ở lại vì nó là HÌNH, ⛔ không phải chuyển động. */
    .tk-gio {
        position: relative; z-index: 0;
        font-size: clamp(3.6rem, min(15vw, 24vh), 40rem); font-weight: 200; line-height: 1;
        letter-spacing: clamp(1px, .5vw, 10px);
        font-variant-numeric: tabular-nums; font-feature-settings: "tnum";

        /* 🔑 MÀU SÁNG GẦN TRẮNG — đây chính là vế chữa lỗi "trùng màu nên bị ẩn". Nền của màn hình này
           là ảnh kho tối, nên con số phải mang màu ĐỐI CỰC với nền, ⛔ không phải một sắc navy khác của
           cùng bảng màu. Hàng rào đo độ sáng tương đối của mã màu này và bắt ĐỎ nếu nó tối lại. */
        color: #f4f9ff;

        /* Chiều sâu nay đến từ VIỀN SẪM + BÓNG ĐỔ chứ ⛔ không từ chồng bóng dựng bề dày:
           ① viền sẫm sát nét — thứ giữ con số đọc được trên mọi khung hình của ảnh nền đang trôi;
           ② một nhịp bóng ngắn ngay dưới nét, cho cảm giác chữ nổi khỏi mặt kính;
           ③ bóng đổ rộng, tách hẳn khối số khỏi nền;
           ④ quầng sáng lạnh rất nhạt — phần "hiệu ứng" nằm ở đây và ở lớp `::after` bên dưới. */
        /* ⭐ ĐỢT 1562 (việc o854) — anh Tiến 30/08/2026: *"em đồ hoạ lại đồng hồ 3D cho thật đẹp và có
           hiệu ứng"*, và nói rõ đây là *"trang bộ mặt của app"*.
           🔑 BỀ DÀY DỰNG BẰNG SÁU LỚP ĐÙN SÁNG → TỐI DẦN, ⛔ không phải một khối navy đặc như bản 1438.
             Đây chính là chỗ phân biệt với lối 3D đã bị anh bác HAI LẦN: ở bản cũ, lớp trên cùng là chữ
             SẪM nên nét chữ trùng màu nền; ở đây lớp trên cùng vẫn là chữ SÁNG `#f4f9ff`, sáu lớp đùn chỉ
             nằm BÊN DƯỚI nét và bắt đầu bằng một sắc lam sáng hơn nền rồi mới tối dần ⇒ mắt đọc ra khối
             dày, ⛔ không đọc ra một vệt lem.
           ⚠ Vẫn ⛔ KHÔNG có hoạt hoạ nào chạm tới việc xếp chữ (bài học "giật giật" đợt 1464): chiều sâu
             ở đây là hình TĨNH, phần động nằm ở vành sáng quay và mặt kính bên dưới. */
        text-shadow:
            0 1px 0 rgba(150, 190, 240, .55),
            0 2px 0 rgba(104, 146, 205, .52),
            0 3px 0 rgba(70, 106, 165, .48),
            0 4px 0 rgba(46, 76, 128, .45),
            0 5px 0 rgba(28, 52, 95, .42),
            0 6px 0 rgba(16, 34, 68, .40),
            0 8px 12px rgba(2, 10, 30, .80),
            0 18px 34px rgba(0, 0, 0, .70),
            0 0 46px rgba(120, 180, 255, .42);
    }

    /* QUẦNG SÁNG THỞ — ⛔ KHÔNG phải một lớp chữ thứ hai.
       🔑 Đây là chỗ khác hẳn bản 1438/1457: lớp này ⛔ không mang `content: attr(data-gio)`, ⛔ không
         `background-clip: text`, nên nó ⛔ không thể che mất mặt chữ dù đặt ở tầng nào. Nó chỉ là một
         vệt sáng hình bầu dục nằm SAU con số.
       ⚠ `z-index: -1` ở đây LÀNH, và lý do phải hiểu cho đúng kẻo lượt sau sửa ngược: con z-index âm
         vẽ ĐÈ LÊN NỀN của cha (đúng cái đã trả giá ở đợt 1457) — nhưng `.tk-gio` nay ⛔ KHÔNG CÓ NỀN,
         mặt chữ là `color` đặc. Nền duy nhất nó từng có là mặt kim loại `background-clip: text` của
         bản cũ, mà bản ấy đã bỏ. ⇒ Luật đúng ⛔ không phải "cấm z-index âm" mà là: **lớp con z-index
         âm chỉ được phép khi cha KHÔNG có nền**. Hàng rào canh đúng câu ấy.
       ⚠ Chỉ chạy `opacity` + `transform` — hai thuộc tính trình duyệt hợp ảnh trên GPU, ⛔ không kéo
         theo một lượt vẽ lại chữ nào. Đây là vế chữa lỗi "giật giật": bản cũ nhấc cả khối số 15rem
         bằng `transform` MỖI GIÂY, tức bắt trình duyệt xếp chữ lại 60 lần một giây, mỗi giây một lần. */
    .tk-gio::after {
        content: "";
        position: absolute; z-index: -1; pointer-events: none;
        left: 50%; top: 50%; width: 116%; height: 150%;
        transform: translate(-50%, -50%);
        background: radial-gradient(ellipse at center,
            rgba(105, 170, 255, .34) 0%, rgba(105, 170, 255, .12) 46%, rgba(105, 170, 255, 0) 72%);
        animation: tk-hao-quang 7s ease-in-out infinite;
    }

    @keyframes tk-hao-quang {
        0%, 100% { opacity: .5; transform: translate(-50%, -50%) scale(1); }
        50%      { opacity: 1;  transform: translate(-50%, -50%) scale(1.06); }
    }

    /* ═══ ⭐ ĐỢT 1562 (việc o854) — BẢNG ĐỒNG HỒ 3D: VÀNH SÁNG QUAY · MẶT KÍNH · BÓNG GƯƠNG ═══

       Anh Tiến 30/08/2026: *"em đồ hoạ lại đồng hồ 3D cho thật đẹp và có hiệu ứng"* + *"trang này là
       trang bộ mặt của app cần đồ hoạ đẹp, hiệu ứng cách mạng"*.

       🔴 ĐỌC TRƯỚC KHI SỬA — HAI ĐIỀU CẤM ĐÃ TRẢ GIÁ HAI LẦN, khối này CỐ Ý đi vòng qua cả hai:
       ① ⛔ Không lớp chữ nào được mang màu SẪM (lỗi *"trùng màu nên bị ẩn"*, đợt 1457 · 1464). Ở đây
          chiều sâu đến từ khối ĐÙN nằm dưới nét và từ một TẤM BẢNG thật sự có bệ, ⛔ không từ việc tô
          con số bằng màu của nền.
       ② ⛔ Không hoạt hoạ nào được chạm tới việc XẾP CHỮ (lỗi *"giật giật"*, đợt 1464). Ba hiệu ứng
          dưới đây chạy bằng `transform` và `opacity` trên những lớp KHÔNG mang chữ:
          · vành sáng quay quanh mép bảng;   · vệt sáng lướt qua mặt kính;   · quầng thở sau con số.
          Con số thì mỗi giây chỉ đổi đúng phần chữ, ⛔ không nhấc, ⛔ không phóng.

       🔑 VÀNH SÁNG LÀM BẰNG "CON QUAY BỊ CẮT", ⛔ đừng thay bằng `border-image` hay một `::before` âm:
          `.tk-vanh` là một hình VUÔNG lớn hơn bảng, mang `conic-gradient` và quay tròn; `.tk-dong-ho`
          cắt phần thừa (`overflow: hidden`), còn `.tk-mat` đè kín phần giữa ⇒ thứ còn nhìn thấy đúng
          bằng dải viền. Đặt nó làm lớp âm của chính `.tk-mat` là dựng lại lỗi đợt 1457 (con z-index âm
          vẽ ĐÈ LÊN NỀN của cha) — mà `.tk-mat` thì CÓ nền.
       ⚠ `aspect-ratio` giữ cho hình vuông thật vuông ở mọi khổ. Trình duyệt quá cũ ⛔ không hiểu nó ⇒
         lớp cao 0 ⇒ mất vành sáng, bảng vẫn nguyên vẹn — hỏng về phía TRANG TRÍ, đúng chiều an toàn.
       ⚠ 140% là con số ĐO ĐƯỢC chứ ⛔ không phải cho đẹp: hình vuông phải phủ hết đường chéo của bảng
         ở MỌI góc quay, mà đường chéo của một bảng rộng W cao ~0,35W là ≈1,06W. */
    .tk-dong-ho {
        /* ⭐ ĐỢT 1577 (việc o882) — nhịp 2/4, vào bằng PHÓNG NHẸ (⛔ không trôi lên: đây là khối lớn
           nhất màn hình). Xem khối "MÀN HÌNH DỰNG LÊN THEO LỚP" ở đầu tệp. */
        animation: tk-vao-man-phong .95s cubic-bezier(.22, .9, .3, 1) .18s both;
        position: relative; display: inline-block;
        padding: 3px;                                   /* đúng bề dày dải viền sáng */
        border-radius: clamp(14px, 2.2vw, 34px);
        overflow: hidden;                               /* cắt phần thừa của con quay */
    }
    .tk-vanh {
        position: absolute; left: 50%; top: 50%; z-index: 0;
        width: 140%; aspect-ratio: 1;
        pointer-events: none;
        background: conic-gradient(from 0deg,
            rgba(244, 123, 32, 0)    0deg,
            rgba(244, 123, 32, .95) 42deg,
            rgba(255, 214, 150, 1)  66deg,
            rgba(244, 123, 32, 0)  118deg,
            rgba(105, 170, 255, 0) 196deg,
            rgba(105, 170, 255, .9) 244deg,
            rgba(190, 224, 255, 1) 272deg,
            rgba(105, 170, 255, 0) 322deg,
            rgba(244, 123, 32, 0)  360deg);
        animation: tk-vanh-quay 11s linear infinite;
    }
    @keyframes tk-vanh-quay {
        from { transform: translate(-50%, -50%) rotate(0turn); }
        to   { transform: translate(-50%, -50%) rotate(1turn); }
    }

    /* MẶT KÍNH — tấm bảng thật: lưới hi-tech rất nhạt nằm trong NỀN (⛔ không thêm một lớp phủ nào lên
       chữ), gờ sáng mép trên, lòng hơi lõm, BỆ ĐẶC dựng bề dày và bóng đổ tách bảng khỏi ảnh nền.
       ⚠ Bệ phải là `box-shadow` ĐẶC (`0 10px 0`) — bóng MỜ chỉ nói "vật này lơ lửng", bóng ĐẶC mới nói
         "vật này DÀY"; đúng bài học đã ghi ở nút `.tk-nut` (đợt 1460). */
    .tk-mat {
        position: relative; z-index: 1;
        border-radius: clamp(11px, 1.9vw, 31px);
        padding: clamp(.7rem, 2vh, 1.9rem) clamp(1.1rem, 3.2vw, 3.2rem) clamp(.5rem, 1.4vh, 1.2rem);
        overflow: hidden;
        background:
            radial-gradient(ellipse at 50% 0%, rgba(120, 180, 255, .10), transparent 70%),
            repeating-linear-gradient(90deg, rgba(120, 180, 255, .05) 0 1px, transparent 1px 30px),
            repeating-linear-gradient(0deg,  rgba(120, 180, 255, .04) 0 1px, transparent 1px 30px),
            linear-gradient(180deg, rgba(14, 32, 66, .58), rgba(3, 10, 26, .80));
        backdrop-filter: blur(12px) saturate(1.15);
        box-shadow:
            inset 0 1px 0 rgba(255, 255, 255, .30),
            inset 0 -22px 44px rgba(2, 8, 24, .50),
            0 10px 0 rgba(3, 10, 26, .55),
            0 30px 60px rgba(0, 0, 0, .60);
    }

    /* VỆT SÁNG LƯỚT QUA MẶT KÍNH. Chạy bằng `transform` (GPU), ⛔ không bằng `left` — đổi `left` là
       một lượt tính lại bố cục mỗi khung hình, thứ đã trả giá ở đợt 1464.
       ⚠ Nằm DƯỚI chữ: `::before` đứng đầu trong thứ tự vẽ, còn `.tk-gio` là con ĐỊNH VỊ nên vẽ sau ⇒
         vệt sáng ⛔ không bao giờ quét xoá con số (đúng bẫy đã ghi ở nút `.tk-nut`). */
    .tk-mat::before {
        content: ""; position: absolute; top: -25%; bottom: -25%; left: 0; width: 18%;
        pointer-events: none;
        background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .17), transparent);
        animation: tk-luot-kinh 8s ease-in-out infinite;
    }
    @keyframes tk-luot-kinh {
        0%, 58% { transform: translateX(-180%) skewX(-16deg); }
        100%    { transform: translateX(640%)  skewX(-16deg); }
    }

    /* BÓNG GƯƠNG — con số phản chiếu trên mặt bảng. Đây là thứ làm tấm bảng đọc ra là VẬT THỂ chứ
       ⛔ không phải một hình vẽ phẳng.
       🔑 CÁCH LÀM, ⛔ đừng thay bằng một bản chữ mờ đặt xuôi: thẻ con cao đúng 1em bị lật quanh tâm
         của CHÍNH NÓ (`scaleY(-1)`), rồi khung ngoài chỉ chừa `.42em` trên cùng ⇒ phần lộ ra đúng là
         `.42em` CUỐI của con số, lộn ngược — tức ảnh gương thật.
       ⚠ Cỡ chữ phải chép ĐÚNG công thức của `.tk-gio` (kể cả `letter-spacing`), ⛔ không dùng `inherit`:
         `.tk-gio` khai cỡ riêng nên `inherit` ở đây lấy phải cỡ của khối cha, ảnh gương lệch hẳn khỏi
         con số. Đổi cỡ đồng hồ thì đổi CẢ HAI CHỖ — có chốt canh hai công thức phải khớp nhau.
       ⚠ `mask-image` không chạy ở trình duyệt quá cũ ⇒ ảnh gương hiện đều thay vì mờ dần; vẫn đọc được
         là bóng nhờ độ mờ nền — hỏng về phía TRANG TRÍ.
       ⓘ `aria-hidden` + `user-select: none`: đây là ảnh trang trí, ⛔ không có gì để đọc lên hay bôi đen. */
    .tk-guong {
        height: .3em; overflow: hidden; margin-top: .02em;
        font-size: clamp(3.6rem, min(15vw, 24vh), 40rem); font-weight: 200; line-height: 1;
        letter-spacing: clamp(1px, .5vw, 10px);
        font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
        pointer-events: none; user-select: none;
        mask-image: linear-gradient(to top, rgba(0, 0, 0, .8), transparent 88%);
        -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, .8), transparent 88%);
    }
    .tk-guong span {
        display: block; transform: scaleY(-1);
        color: rgba(178, 212, 255, .22);
    }

    /* Người khai "giảm chuyển động" ⇒ dừng hai lớp quay/lướt. ⛔ Đừng ẩn tấm bảng: khác ba ngôi sao ở
       khẩu hiệu (trang trí thuần), bảng này là chỗ ĐẶT ĐỒNG HỒ — bỏ nó là bỏ luôn con số. */
    @media (prefers-reduced-motion: reduce) {
        .tk-vanh, .tk-mat::before { animation: none; }
    }

    .tk-ngay {
        font-size: clamp(1rem, min(2.1vw, 3.4vh), 6rem); font-weight: 300; margin-top: clamp(.2rem, .8vh, .9rem);
        letter-spacing: clamp(.5px, .16vw, 3px); color: #dbe7ff; text-shadow: 0 2px 16px rgba(0,0,0,.6);
    }
    /* Vệt cam thương hiệu ngăn đồng hồ với khẩu hiệu */
    .tk-vet {
        /* ⭐ ĐỢT 1577 (việc o882) — nhịp 3/4 của lượt dựng màn hình. */
        animation: tk-vao-man .8s ease-out .42s both;
        height: 3px; width: clamp(120px, 22vw, 460px); margin: clamp(1rem, 3vh, 2.6rem) auto 0;
        border-radius: 3px; background: linear-gradient(90deg, transparent, #F47B20 25%, #ffb26b 50%, #F47B20 75%, transparent);
    }

    /* ── khẩu hiệu (đổi câu bằng JS — số câu do cấu hình, ⛔ không đóng đinh được vào keyframes) ── */
    .tk-khau-hieu {
        /* ⭐ ĐỢT 1464 — chữ nằm TRÊN lớp sao băng (xem khối 🩸 ở phần `.tk-sao` bên dưới): một chấm
           sáng chạy đè qua nét chữ là làm KHÓ ĐỌC, ⛔ không phải "làm nổi bật". */
        position: relative; z-index: 1;
        margin-top: clamp(.8rem, 2.4vh, 2rem); min-height: 1.6em;
        font-size: clamp(1rem, min(2.3vw, 3.9vh), 7rem); font-weight: 300;
        letter-spacing: clamp(.3px, .12vw, 2px); color: #ffd7b0;
        text-shadow: 0 2px 18px rgba(0,0,0,.7);
        /* ⭐ ĐỢT 2239 (việc o1717) — `filter: blur(0)` là MỘT PHẦN CỦA PHÉP TAN, ⛔ đừng xoá cho "gọn".
           📏 Đo sống 09/09/2026 trên chính trang này: bản cũ ⛔ không khai `filter` ở trạng thái nghỉ
           nên nó là `none`, mà `none → blur(3px)` trình duyệt **⛔ không nội suy** — `getAnimations()`
           chỉ dựng CSSTransition cho `opacity` và `transform`, ⛔ KHÔNG có cái nào cho `filter` ⇒ nét
           chữ **nhoè ĐỘT NGỘT ngay khung hình đầu** rồi mới mờ dần. Khai `blur(0)` là hai đầu cùng
           kiểu ⇒ nhoè đi cũng mượt như mờ đi.
           ⚠ Dòng này chỉ có tác dụng ở **trình duyệt ⛔ không hiểu `background-clip: text`**: máy nào
             hiểu thì khối `@supports` bên dưới đè `filter` thành `drop-shadow(…)`, và ở đó lượt tan
             đi bằng một luật RIÊNG (`.tk-khau-hieu.tk-mo-dan` trong chính khối ấy) — sửa một bên mà
             quên bên kia là chỉ chữa được nửa số máy. */
        filter: blur(0);
        /* ⚠ ⛔ ĐỪNG rút NGẮN `.6s`: `tiep-khach.js` (mục ⑤) có một lưới an toàn **900 ms** đứng sau
           `transitionend`; kéo phép tan dài quá con số ấy là lưới cướp tay trên, chữ đổi **giữa lúc
           còn nhìn thấy**. ⓘ Từ đợt 2239 thì lượt đổi chữ đi theo `transitionend` chứ ⛔ không còn
           đếm 600 ms nữa, nên hai con số ⛔ không phải bằng nhau — chỉ cần `.6s` < 900 ms. */
        transition: opacity .6s cubic-bezier(.4, 0, .2, 1), transform .6s cubic-bezier(.4, 0, .2, 1),
                    filter .6s cubic-bezier(.4, 0, .2, 1);
        opacity: 1;
    }
    /* ⭐ ĐỢT 1912 (việc o1174) — CÂU KHẨU HIỆU **TAN RA RỒI TỤ LẠI**, thay cho lượt mờ trơn.
       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"*.
       🔑 Vì sao CHỈ thêm vào đúng một lớp `tk-mo-dan`, ⛔ không dựng thêm lớp thứ hai kiểu "vào từ
         dưới": `tiep-khach.js` (mục ⑤) chỉ biết BẬT rồi TẮT một lớp duy nhất, nên hiệu ứng phải
         **đối xứng** — thu nhỏ + nhoè khi đi, phóng về + nét lại khi tới. Thêm lớp thứ hai là phải
         sửa cả tệp js đang có 96 bài hàng rào canh, đổi lấy đúng một chuyển động.
       🩸 ⭐ ĐỢT 2239 (việc o1717) — **CÂU LUẬT CŨ Ở ĐÂY ĐÃ HẾT HIỆU LỰC, ⛔ ĐỪNG THI HÀNH LẠI NÓ.**
         Nguyên văn cũ: *"⛔ ĐỪNG đổi con số `.6s`: `tiep-khach.js` chờ 600 mili giây rồi mới thay
         chữ"*. Ràng buộc ấy đã gỡ: JS nay đổi chữ theo **`transitionend`**, tức đợi phép tan chạy
         XONG THẬT, và chỉ giữ một lưới an toàn 900 ms. ⇒ Đổi `.6s` được, miễn **nhỏ hơn 900 ms**.
         🔑 Vì sao phải gỡ: đếm mi-li-giây chỉ đúng khi tab **đang được vẽ** — tab nền thì hoạt hoạ
         đứng im mà hẹn giờ vẫn chạy ⇒ chữ bị thay lúc còn hiện rõ (đo sống 09/09, xem chú thích ở
         mục ⑤ của `tiep-khach.js`). Đó chính là *"bật tắt giật giật"* anh Tiến báo.
       ⚠ Biên độ cố ý RẤT NHỎ (1,5% cỡ · nhoè 3px): đây là màn hình treo tường ở phòng khách, chữ to
         gần hết bề ngang — thu 5% là cả dòng chữ **giật một cái** ở rìa tầm mắt, đúng chữ *"nháy"*
         mà đợt 1492 vừa phải đi chữa.
       ⓘ Máy khai "giảm chuyển động" ⛔ không cần luật riêng: `transition` chỉ chạy khi lớp đổi, mà
         khối `* !important` toàn cục (app.css mục 10) đã tắt sạch cả `transition` lẫn `animation`. */
    .tk-khau-hieu.tk-mo-dan { opacity: 0; transform: scale(.985); filter: blur(3px); }

    /* ═══ ⭐ ĐỢT 1577 (việc o882) — MẶT CHỮ ÁNH KIM CHO KHẨU HIỆU ═══

       Cùng khuôn với tên đơn vị (xem khối "CHỮ ĐỒ HOẠ" ở trên) — mọi lý do và điều cấm ghi ở đó,
       ⛔ đừng đọc riêng khối này rồi chép sang chỗ khác.

       🔴 VỊ TRÍ CỦA KHỐI NÀY LÀ MỘT PHẦN CỦA LUẬT, ⛔ ĐỪNG DỜI NÓ LÊN CẠNH KHỐI KIA CHO "GỌN". Bản
         đầu của chính đợt 1577 đặt cả hai `@supports` cạnh nhau ở đầu tệp, tức **TRƯỚC** luật gốc
         `.tk-khau-hieu` — mà hai khối cùng độ đặc hiệu (0,1,0) thì thắng thua **theo THỨ TỰ**. Hậu
         quả đo được: luật gốc đè lại `color: #ffd7b0` và `text-shadow`, nhưng ⛔ KHÔNG đè
         `-webkit-text-fill-color: transparent` (nó ⛔ không khai thuộc tính ấy) ⇒ **khẩu hiệu biến mất
         khỏi màn hình** — chữ trong suốt mà nền cắt theo chữ thì đã bị luật sau vô hiệu.
         Build vẫn xanh, và trên ảnh chụp thì chỉ là "một dòng trống" rất dễ đọc nhầm thành bố cục.
       ⓘ Bắt được nhờ `LuatManHinhTiepKhachTests` — ba bài của nó cắt thân luật theo lần khai ĐẦU TIÊN
         của lớp, nên khối đặt sai chỗ làm chúng đỏ ngay. ⛔ Đừng "chữa" bằng cách dạy bộ dò bỏ qua
         khối `@supports`: chính thứ tự ấy mới là cái sai. */
    @supports (background-clip: text) or (-webkit-background-clip: text) {
        /* Khẩu hiệu giữ SẮC CAM THƯƠNG HIỆU làm màu chủ đạo của dải — nó là chữ Petrolimex, ⛔ đừng
           đổi sang dải trắng cho "đồng bộ" với tên đơn vị: hai khối cố ý khác sắc để mắt tách được
           dòng nhận diện đơn vị khỏi câu khẩu hiệu. */
        .tk-khau-hieu {
            /* ⚠ MỐC SÁNG NHẤT DỪNG Ở `#ffe6cc`, ⛔ ĐỪNG NÂNG LÊN GẦN TRẮNG. Bản đầu của chính đợt
               1577 để `#fff2e2` và **đo sống bác bỏ**: ở pha ấy câu khẩu hiệu ra gần TRẮNG, mất hẳn
               sắc cam thương hiệu — nhìn ra thành "cùng màu với tên đơn vị ở dải trên", tức là bỏ
               đúng thứ dùng để tách hai khối chữ. Tương phản ⛔ không phải lý do (cả dải đều ≥ 10:1
               trên nền tối); đây là chuyện NHẬN DIỆN. */
            background-image: linear-gradient(100deg,
                #ffd7b0 0%, #ffb98a 20%, #ffe6cc 38%, #ffd7b0 56%, #ffb98a 76%, #ffd7b0 100%);
            background-size: 260% 100%;
            -webkit-background-clip: text; background-clip: text;
            -webkit-text-fill-color: transparent; color: transparent;
            text-shadow: none;
            filter: drop-shadow(0 2px 16px rgba(0, 0, 0, .72));
            animation: tk-chu-anh-kim 11s linear infinite;
        }

        /* 🩸 ⭐ ĐỢT 2239 (việc o1717) — LƯỢT TAN PHẢI GIỮ NGUYÊN `drop-shadow` RỒI MỚI **CỘNG THÊM**
           `blur`, ⛔ TUYỆT ĐỐI ĐỪNG VIẾT `filter: blur(3px)` TRẦN Ở ĐÂY.
           🔑 Trình duyệt chỉ nội suy được hai danh sách bộ lọc khi **cùng thứ tự hàm**, hoặc khi danh
             sách ngắn là **phần đầu** của danh sách dài (chỗ thiếu được đệm bằng giá trị gốc). Nền
             `drop-shadow(…)` mà đích là `blur(3px)` là **hai danh sách khác hẳn nhau** ⇒ trình duyệt
             **nhảy thẳng** sang giá trị đích ở khung hình đầu: chữ **mất bóng và nhoè ĐỘT NGỘT**, rồi
             mới mờ dần. Đó là một nửa của cái *"giật giật"* anh Tiến báo 09/09/2026.
           📏 Đo sống 09/09 trên bản trước khi vá: `getAnimations()` của `.tk-khau-hieu` chỉ dựng
             CSSTransition cho `opacity` và `transform` — **⛔ KHÔNG có cái nào cho `filter`**, đúng
             dấu hiệu của một lượt đổi RỜI RẠC.
           ⚠ Con số bóng phải chép **Y HỆT** luật ngay trên: lệch một chữ số là hai danh sách lại
             khác nhau ở phần đầu ⇒ về đúng chỗ vừa chữa, mà ⛔ không câu báo nào. */
        .tk-khau-hieu.tk-mo-dan {
            filter: drop-shadow(0 2px 16px rgba(0, 0, 0, .72)) blur(3px);
        }
    }

    /* ═══ ⭐ ĐỢT 1464 (việc o662) — SAO BĂNG BAY UỐN LƯỢN QUANH KHẨU HIỆU ═══
       Anh Tiến 28/08/2026: *"có thêm hiệu ứng sao băng bay uốn lượn quanh các chữ khẩu hiệu để làm
       nổi bật"*.

       🔑 ĐƯỜNG BAY GHÉP TỪ HAI CHUYỂN ĐỘNG LỒNG NHAU, ⛔ đừng cố gộp làm một:
         · thẻ NGOÀI (`.tk-sao`) trôi NGANG hết bề rộng khối khẩu hiệu — nó rộng đúng 100% khối cha nên
           `translateX` tính theo phần trăm ra đúng quãng đường cần đi;
         · thẻ TRONG (`i`) đưa lên đưa xuống theo một nhịp KHÁC — chính chỗ hai chu kỳ lệch nhau mới
           dựng ra nét "uốn lượn". Ba ngôi sao mang ba cặp chu kỳ khác nhau nên ⛔ không bao giờ vẽ
           trùng đường.
       ⚠ CẢ HAI đều chỉ chạy `transform`/`opacity` — hai thuộc tính trình duyệt hợp ảnh trên GPU. Đây là
         điều kiện bắt buộc ở màn hình treo tường chạy suốt ngày, và cũng là bài học vừa trả giá ở chính
         đồng hồ ngay trên (nhịp giây `tk-dap` xếp lại chữ mỗi giây ⇒ anh đọc ra là "giật giật").
       ⛔ ĐỪNG dùng `offset-path`/`path()` cho đẹp: trình duyệt cũ bỏ qua trong im lặng ⇒ ba ngôi sao
         ĐỨNG YÊN thành ba chấm sáng vô nghĩa nằm cạnh câu khẩu hiệu.
       🩸 SAO NẰM DƯỚI CHỮ (`z-index` 0 so với 1): khẩu hiệu là chữ NGƯỜI TA ĐỌC, ⛔ không được để một
         chấm trắng chạy đè qua nét chữ. "Làm nổi bật" ở đây là ánh sáng chạy quanh, ⛔ không phải chạy đè. */
    /* ⭐ ĐỢT 1577 (việc o882) — nhịp 4/4. Hoạt hoạ đặt ở THẺ BỌC chứ ⛔ không ở `.tk-khau-hieu`:
       chữ khẩu hiệu đã mang hoạt hoạ ánh kim riêng, và một phần tử ⛔ không khai hai `animation`
       shorthand chồng nhau được — cái sau nuốt cái trước, trong im lặng. */
    .tk-khau-boc { position: relative; animation: tk-vao-man .9s ease-out .6s both; }

    .tk-sao {
        position: absolute; top: 50%; left: 0; z-index: 0;
        width: 100%; height: 0;
        pointer-events: none;
        animation: tk-sao-bay 9s linear infinite;
    }
    .tk-sao-2 { animation-duration: 12.5s; animation-delay: -5.2s; }
    .tk-sao-3 { animation-duration: 7.5s;  animation-delay: -2.6s; }

    /* Đầu sao: một chấm sáng nhỏ, quầng cam thương hiệu. `position: relative` là BẮT BUỘC — cái đuôi
       ở `::after` neo vào chính nó. */
    .tk-sao i {
        display: block; position: relative;
        width: .42rem; height: .42rem; border-radius: 50%;
        background: #fff;
        box-shadow: 0 0 8px 3px rgba(255, 214, 150, .85), 0 0 22px 8px rgba(244, 123, 32, .45);
        animation: tk-sao-luon 2.6s ease-in-out infinite;
    }
    .tk-sao-2 i { animation-duration: 3.4s; animation-delay: -1.1s; }
    .tk-sao-3 i { animation-duration: 2.1s; animation-delay: -.7s; }

    /* ⭐ ĐỢT 1793 (việc o1065) — QUẦNG THỞ QUANH ĐẦU SAO. `z-index: -1` đẩy nó xuống DƯỚI cái chấm
       trắng: nằm trên thì lớp cam phủ mờ ngay cái lõi sáng nhất, mà lõi sáng mới là thứ mắt bám vào.
       ⓘ Chỉ chạy `opacity` — rẻ nhất trong mọi cách làm một vật thể "thở". */
    .tk-sao i::before {
        content: ""; position: absolute; inset: -.36rem; z-index: -1;
        border-radius: 50%;
        background: radial-gradient(circle,
                    rgba(255, 236, 206, .5) 0%, rgba(244, 123, 32, .2) 46%, rgba(244, 123, 32, 0) 74%);
        animation-name: tk-sao-tho;
        animation-timing-function: ease-in-out;
        animation-iteration-count: infinite;
        animation-duration: inherit;   /* ⛔ đừng chép tay nhịp — xem khối ⚠ ở `::after` ngay dưới */
        animation-delay: inherit;
    }

    /* Đuôi sao kéo về phía SAU đường bay (sao bay sang phải ⇒ đuôi nằm bên trái).
       ⚠ Dải màu đi từ đặc ở mép PHẢI (sát đầu sao) tan dần sang trái — đảo chiều là ra một vệt sáng
         chạy TRƯỚC ngôi sao, đọc ra thành "sao đang lùi".

       🔴 ĐỢT 1793 (việc o1065) — ANH TIẾN BÁO 02/09/2026: *"hiệu ứng pháo hoa và sao băng đang xấu
         cần cải thiện"*. Cái đuôi đời trước sai HAI chuyện, và cả hai đều nằm ngay ở chỗ mắt nhìn:
           ① **ĐUÔI LUÔN NẰM NGANG TRONG KHI SAO ĐANG BAY CHÉO.** Đường bay ghép từ hai chuyển động
              (trôi ngang + lượn lên xuống) nên phần lớn thời gian ngôi sao đi CHÉO, mà cái đuôi thì
              đóng đinh `height: 2px` nằm ngang ⇒ mắt đọc ra một **gạch ngang** cắt qua câu khẩu
              hiệu, ⛔ không phải một vệt sao.
              📏 Đo sống 02/09 NGAY TRÊN APP DEV (cổng 5270, trang `/dang-nhap`) — đọc vận tốc thật
              của đầu sao qua `getAnimations()` rồi quét cả chu kỳ lấy đỉnh, ⛔ không ước chừng:
                · khổ **1.920px** (màn treo tường): khối khẩu hiệu rộng 1.194px ⇒ góc bay lớn nhất
                  **18,2° · 19,2° · 18,7°**
                · khổ **1.400px** (màn bàn làm việc): khối rộng 900px ⇒ **23,5° · 24,8° · 24,2°**
              ⇒ đuôi phải nghiêng chừng ấy, ⛔ không phải 0°. Nay `::after` mang thêm nhịp
              `tk-sao-nghieng` đưa đuôi qua lại **±20°** ĐÚNG PHA với nhịp lượn.
              ⓘ 20° là MỘT con số chọn chung cho mọi khổ chứ ⛔ không phải góc đúng của một khổ: khối
                khẩu hiệu càng rộng thì sao trôi ngang càng nhanh nên góc bay càng nhỏ. Nó bám sát
                khổ màn treo tường (19°) và lệch ~4° ở khổ 1.400px — sai vài độ thì ⛔ không ai thấy;
                đuôi nằm NGANG trong lúc sao lao xuống thì ai cũng thấy, đó mới là thứ đợt này chữa.
              🔴 Lượt đầu của chính đợt này đặt **15°** theo số đo của BÀN THỬ tĩnh (khối 1.203px, cỡ
                chữ 14px ⇒ ~16°). Đo lại trên app thật thì cỡ chữ là **16px** chứ ⛔ không phải 14px
                ⇒ biên độ lượn `1,15em` lớn hơn, góc bay thật vọt lên 19–24°. ⛔ Đừng lấy lại số của
                bàn thử: nó ⛔ không mang cỡ chữ thật của màn hình tiếp khách.
           ② **ĐUÔI LÀ MỘT THANH CHỮ NHẬT, ⛔ KHÔNG THON.** `clip-path` cắt nó thành hình tam giác:
              đáy rộng ở sát đầu sao, nhọn dần về cuối — đó là dáng của một vệt sao chổi.
              ⓘ Trình duyệt ⛔ không hiểu `clip-path` thì đuôi trở lại hình chữ nhật, tức là **đúng
                bằng đời cũ** — hỏng về phía an toàn, ⛔ không mất cái đuôi.
       ⚠ `transform-origin: 100% 50%` là BẮT BUỘC: điểm xoay phải nằm ở ĐẦU SAO. Để mặc định (giữa
         thân đuôi) thì mỗi lần nghiêng, cái đuôi rời khỏi đầu sao một quãng — thành một vệt sáng
         trôi lơ lửng cạnh ngôi sao.
       ⚠ `animation-duration`/`-delay` khai `inherit` — CỐ Ý, và đây là chỗ dễ hỏng lặng lẽ nhất của
         cả khối: nhịp lượn thật nằm ở hai dòng `.tk-sao-2 i` / `.tk-sao-3 i` phía trên. Chép tay lại
         nhịp ấy xuống đây là dựng thêm một chỗ phải nhớ sửa cùng lúc, mà lệch pha thì đuôi nghiêng
         NGƯỢC hướng bay — xấu hơn cả đời cũ, và ⛔ không một câu lỗi nào. */
    .tk-sao i::after {
        content: ""; position: absolute; top: 50%; right: .28rem;
        width: 3.4rem; height: .34rem;
        transform-origin: 100% 50%;
        transform: translateY(-50%) rotate(0deg);
        clip-path: polygon(0 50%, 100% 0, 100% 100%);
        background: linear-gradient(270deg,
                    rgba(255, 236, 206, .92), rgba(255, 214, 150, .5) 38%, rgba(255, 214, 150, 0));
        animation-name: tk-sao-nghieng;
        animation-timing-function: ease-in-out;
        animation-iteration-count: infinite;
        animation-duration: inherit;
        animation-delay: inherit;
    }

    /* Mờ ở hai đầu quãng bay — ngôi sao ⛔ không được "hiện ra" rồi "tắt phụt" ở giữa không trung. */
    @keyframes tk-sao-bay {
        0%        { transform: translateX(-6%);  opacity: 0; }
        8%, 90%   { opacity: 1; }
        100%      { transform: translateX(106%); opacity: 0; }
    }
    @keyframes tk-sao-luon {
        0%, 100% { transform: translateY(-1.15em); }
        50%      { transform: translateY(1.15em); }
    }

    /* ⭐ ĐỢT 1793 — ĐUÔI NGHIÊNG THEO HƯỚNG BAY. Bốn mốc dưới đây ⛔ KHÔNG được đặt tuỳ ý, chúng bám
       theo `tk-sao-luon` ở ngay trên: nhịp lượn đi XUỐNG trong nửa đầu và đi LÊN trong nửa sau, nên
       vận tốc dựng đứng lớn nhất rơi vào mốc 25% và 75%, còn ở 0% · 50% · 100% ngôi sao đang ở đỉnh
       hoặc đáy sóng và bay NGANG thật.
       ⚠ CHIỀU XOAY: cái đuôi trỏ sang TRÁI, mà xoay dương trong CSS là xoay thuận chiều kim đồng hồ
         ⇒ một vật trỏ trái xoay dương thì đầu mút NGÓC LÊN. Lúc 25% ngôi sao đang lao XUỐNG, đuôi
         phải ngóc LÊN sau lưng nó ⇒ **+15°**. Đảo dấu là đuôi quét ngược hướng bay, trông như ngôi
         sao đang bị kéo lê.
       ⚠ Phải viết lại cả `translateY(-50%)` ở từng mốc: `transform` trong `@keyframes` GHI ĐÈ trọn
         chuỗi ở luật tĩnh, ⛔ không cộng dồn vào nó. Bỏ quên là cái đuôi tụt xuống nửa thân, ⛔ không
         còn cắm vào đầu sao. */
    @keyframes tk-sao-nghieng {
        0%, 50%, 100% { transform: translateY(-50%) rotate(0deg); }
        25%           { transform: translateY(-50%) rotate(20deg); }
        75%           { transform: translateY(-50%) rotate(-20deg); }
    }
    /* Quầng sáng thở đúng một nhịp mỗi vòng lượn — ⛔ đừng cho nó nhấp nhanh hơn: nhanh là ra đèn báo. */
    @keyframes tk-sao-tho {
        0%, 100% { opacity: .5; }
        50%      { opacity: 1; }
    }

    /* Người khai "giảm chuyển động" ⇒ ẨN HẲN ba ngôi sao, ⛔ không chỉ dừng chúng lại: khối
       prefers-reduced-motion toàn cục (`* !important`, mục 10 đợt 381) tắt mọi hoạt hoạ, mà sao đứng
       yên là ba chấm sáng nằm chết ở mép trái câu khẩu hiệu — trông như giao diện vỡ. Đây là thứ trang
       trí thuần, bỏ đi ⛔ không mất một thông tin nào. */
    @media (prefers-reduced-motion: reduce) {
        .tk-sao { display: none; }
    }

    /* ── thanh nút Đăng nhập: ẩn, động vào chuột mới hiện, 10 giây sau tự ẩn ── */
    .tk-thanh-nut {
        position: absolute; left: 0; right: 0; bottom: clamp(1.6rem, 6vh, 5rem); z-index: 5;
        display: flex; justify-content: center;
        opacity: 0; transform: translateY(14px); pointer-events: none;
        /* ⭐ ĐỢT 2239 (việc o1717) — đường cong đổi từ `ease` sang một nhịp có độ nảy rất nhẹ: khối
           đi — ở đây là khối nút — trượt lên rồi **dừng hẳn** trong `ease` trông như bị cắt ngang.
           ⚠ Hệ số vượt mốc 1 cố ý giữ **rất nhỏ** (1,16): đây là màn hình treo tường, một cú nảy rõ là
             đúng chữ *"giật"* đợt 1492 vừa phải đi chữa. ⛔ Đừng thêm `animation` vào hai khối này —
             điều cấm ở đầu tệp vẫn nguyên: hai cơ chế cùng giành một `opacity` thì cái thua **thua trong im lặng**. */
        transition: opacity .45s cubic-bezier(.34, 1.16, .44, 1),
                    transform .45s cubic-bezier(.34, 1.16, .44, 1);
    }
    .tk-man.tk-hien-nut .tk-thanh-nut { opacity: 1; transform: none; pointer-events: auto; }

    /* ═══ NÚT ĐĂNG NHẬP 3D, NỀN TRONG SUỐT (⭐ ĐỢT 1460, việc o658 — anh Tiến 28/08/2026:
           *"nút đăng nhập đồ hoạ 3D có hiệu ứng và nền trong suốt"*) ═══

       🔑 BA THỨ LÀM NÊN KHỐI 3D, ⛔ đừng bỏ thứ nào rồi bảo "vẫn thấy nổi":
       ① **BỆ DƯỚI** — `box-shadow` ĐẶC, ⛔ không mờ (`0 7px 0`): đây là bề dày của nút nhìn nghiêng.
          Bóng MỜ chỉ nói "vật này lơ lửng", còn bóng ĐẶC mới nói "vật này DÀY".
       ② **LÚN KHI BẤM** — `:active` tụt xuống đúng bằng bề dày và bệ mỏng lại. Thiếu nhịp này thì nút
          trông như một hình vẽ 3D chứ ⛔ không phải một vật bấm được.
       ③ **VỆT SÁNG CHẠY QUA** (`::before`, 4,5 giây một vòng) — bề mặt bắt sáng.

       🔴 NỀN TRONG SUỐT NHƯNG ⛔ KHÔNG ĐƯỢC CHÌM. Anh chốt "nền trong suốt", mà đây vẫn là **đường
          vào phần mềm** — nên phần bù lại nằm ở VIỀN cam dày, CHỮ cam sáng và QUẦNG sáng quanh nút,
          ⛔ không nằm ở nền. Nền chỉ còn một lớp kính rất mỏng (`backdrop-filter`) để chữ đọc được
          trên mọi khung hình của ảnh nền đang trôi — bỏ hẳn lớp kính là có ảnh sáng chạy qua thì chữ
          biến mất, mà lỗi ấy chỉ hiện ra ở ĐÚNG một vài giây trong mỗi vòng ảnh.

       🧨 CHỮ PHẢI BỌC TRONG MỘT THẺ CON có `z-index` dương — xem khối markup. `::before` của vệt sáng
          là con ĐỊNH VỊ nên nó vẽ ở bước 6, tức **TRÊN chữ** của chính nút (chữ vẽ ở bước 5) ⇒ để chữ
          trần là vệt sáng quét qua **xoá chữ** mỗi vòng. Đây đúng họ cái bẫy vừa trả giá ở đợt 1457
          (thứ tự vẽ của CSS), chỉ khác chiều. */
    .tk-nut {
        position: relative; overflow: hidden;
        border: 2px solid rgba(244, 123, 32, .95); border-radius: 999px;
        background: rgba(244, 123, 32, .14); color: #ffd7b0;
        font-size: clamp(.95rem, 1.35vw, 1.4rem); font-weight: 700; letter-spacing: .6px;
        padding: clamp(.55rem, 1.1vh, .95rem) clamp(1.6rem, 3.2vw, 3rem);
        cursor: pointer; text-decoration: none;
        backdrop-filter: blur(6px);
        text-shadow: 0 1px 0 rgba(0, 0, 0, .55), 0 0 18px rgba(244, 123, 32, .45);
        box-shadow:
            0 7px 0 rgba(120, 52, 4, .85),                /* ① BỆ — đặc, chính là bề dày */
            0 14px 30px rgba(0, 0, 0, .5),                /*    bóng đổ xuống nền */
            inset 0 1px 0 rgba(255, 255, 255, .45),       /*    gờ sáng mép trên */
            inset 0 -6px 12px rgba(0, 0, 0, .28);         /*    lòng nút hơi lõm */
        transition: transform .12s ease-out, box-shadow .12s ease-out,
                    background-color .2s ease, border-color .2s ease;
    }
    .tk-nut:hover {
        background: rgba(244, 123, 32, .3); border-color: #fff; color: #fff;
        transform: translateY(-2px);
        box-shadow:
            0 9px 0 rgba(120, 52, 4, .9), 0 18px 38px rgba(0, 0, 0, .55),
            inset 0 1px 0 rgba(255, 255, 255, .55), inset 0 -6px 12px rgba(0, 0, 0, .28);
    }
    /* ② LÚN — tụt đúng bằng bề dày, bệ mỏng lại còn 2px. */
    .tk-nut:active {
        transform: translateY(5px);
        box-shadow:
            0 2px 0 rgba(120, 52, 4, .9), 0 6px 14px rgba(0, 0, 0, .45),
            inset 0 2px 6px rgba(0, 0, 0, .35);
    }
    .tk-nut:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

    /* ③ VỆT SÁNG CHẠY QUA. `pointer-events: none` để nó ⛔ không nuốt cú bấm — nó phủ kín mặt nút,
       mà `closest("[data-tk]")` của tiep-khach.js thì vẫn tìm ngược lên được; nhưng thẻ neo dự phòng
       lúc JS chết thì ⛔ KHÔNG có cơ chế ấy, bấm trúng vệt sáng là mất luôn cú bấm. */
    .tk-nut::before {
        content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
        pointer-events: none;
        background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .38), transparent);
        transform: skewX(-18deg);
        animation: tk-nut-loe 4.5s ease-in-out infinite;
    }
    @keyframes tk-nut-loe {
        0%, 62% { left: -60%; }
        100%    { left: 130%; }
    }
    /* Chữ nằm TRÊN vệt sáng — xem khối chú thích 🧨 ở trên. */
    .tk-nut-chu { position: relative; z-index: 1; }

    /* ═══ NÚT TRÌNH DIỄN — GÓC TRÊN CÙNG BÊN PHẢI, NỀN TRONG SUỐT (⭐ ĐỢT 1460, việc o658) ═══
       Anh Tiến 28/08/2026: *"nút trình diễn làm trong nền và đưa ra góc trên cùng bên phải"*.
       Đợt 1458 đặt nó cạnh nút Đăng nhập ở ĐÁY và tô nền navy đặc — hai nút to bằng nhau nằm cạnh
       nhau ở giữa đáy màn hình, mà chỉ một trong hai là việc người ta tới đây để làm.

       🔑 Nay nó **tách hẳn ra góc**, kích thước nhỏ hơn và **nền TRONG SUỐT thật** (⛔ không màu nền,
          chỉ một lớp kính mỏng) — trên màn hình treo tường thì đây là nút của người vận hành, ⛔ không
          phải của khách đứng xem.
       ⚠ ⛔ ĐỪNG dùng lại `.tk-nut`: nút kia nay là khối 3D có bệ dày và vệt sáng chạy (đợt 1460) —
         đắp bộ ấy lên một nút góc nhỏ là hai thứ tranh nhau làm trọng tâm, đúng thứ vừa đi sửa.
       ⚠ Đi theo cùng nhịp hiện/ẩn 10 giây của thanh nút (lớp `tk-hien-nut` trên `.tk-man`) — màn hình
         trình chiếu phải SẠCH khi ⛔ không ai đụng tới, đúng luật anh chốt ở đợt 1420.
       🧨 ⛔ ĐỪNG gõ tên thẻ neo kèm hai dấu ngoặc nhọn vào chú thích này: chú thích CSS ⛔ KHÔNG che
          được bộ phân tích Razor, nó đọc thấy một thẻ mở ⛔ không có thẻ đóng và ném `RZ9980: Unclosed
          tag 'a'`. Đã dính đúng một lượt build khi viết đợt 1458. */
    .tk-goc-phai {
        position: absolute; top: clamp(.9rem, 2.2vh, 2rem); right: clamp(.9rem, 2vw, 2rem); z-index: 6;
        opacity: 0; transform: translateY(-10px); pointer-events: none;
        /* ⭐ ĐỢT 2239 (việc o1717) — đường cong đổi từ `ease` sang một nhịp có độ nảy rất nhẹ: khối
           đi — ở đây là khối nút — trượt lên rồi **dừng hẳn** trong `ease` trông như bị cắt ngang.
           ⚠ Hệ số vượt mốc 1 cố ý giữ **rất nhỏ** (1,16): đây là màn hình treo tường, một cú nảy rõ là
             đúng chữ *"giật"* đợt 1492 vừa phải đi chữa. ⛔ Đừng thêm `animation` vào hai khối này —
             điều cấm ở đầu tệp vẫn nguyên: hai cơ chế cùng giành một `opacity` thì cái thua **thua trong im lặng**. */
        transition: opacity .45s cubic-bezier(.34, 1.16, .44, 1),
                    transform .45s cubic-bezier(.34, 1.16, .44, 1);
    }
    .tk-man.tk-hien-nut .tk-goc-phai { opacity: 1; transform: none; pointer-events: auto; }

    /* ═══ ⭐ ĐỢT 2153 (việc o1574) — NÚT NÀY NAY LÀ KHỐI 3D, VÀ BIỂU TƯỢNG VẼ BẰNG NÉT ═══
       Anh Tiến 07/09/2026, gửi ảnh chụp chính nút này: *"đồ họa lại và thay Icon cho nút này, nút này
       3D và có hiệu ứng"*.

       🔴 ĐÂY LÀ LƯỢT NỚI CÂU CẤM CỦA ĐỢT 1460 ngay phía trên (*"⛔ ĐỪNG dùng lại `.tk-nut`"*) — ⛔ đừng
          đọc hai khối này là mâu thuẫn. Điều đợt 1460 lo là **hai nút tranh nhau làm trọng tâm**, và
          điều ấy VẪN ĐÚNG: nút Đăng nhập giữ nguyên cỡ chữ, bệ 7px, viền cam đặc. Nút góc này chỉ mượn
          NGÔN NGỮ khối 3D ở cỡ nhỏ hơn — bệ **4px**, viền trắng mỏng, nền **vẫn TRONG SUỐT** (câu anh
          chốt 28/08 *"nút trình diễn làm trong nền"* ⛔ không bị đảo, hàng rào
          `Nut_trinh_dien_o_goc_tren_phai_va_hai_nut_deu_nen_trong_suot` vẫn canh chữ `transparent`).

       🧨 CHỮ + BIỂU TƯỢNG PHẢI BỌC TRONG `.tk-nut-phu-chu` có z-index DƯƠNG — `::before` của vệt sáng là
          con ĐỊNH VỊ nên nó vẽ TRÊN nội dung của chính nút; để trần là vệt sáng quét qua **xoá chữ**
          mỗi vòng. Đúng bẫy đã trả giá ở `.tk-nut` (đợt 1460). */
    .tk-nut-phu {
        position: relative; overflow: hidden;
        display: inline-flex; align-items: center;
        border: 1px solid rgba(255, 255, 255, .45); border-radius: 999px;
        background: transparent;                       /* ⛔ KHÔNG màu nền — anh chốt "trong nền" */
        backdrop-filter: blur(5px);
        color: #dbe7ff; text-decoration: none;
        font-size: clamp(.8rem, 1vw, 1.05rem); font-weight: 600; letter-spacing: .4px;
        padding: clamp(.35rem, .7vh, .6rem) clamp(.8rem, 1.5vw, 1.3rem);
        text-shadow: 0 1px 8px rgba(0, 0, 0, .7);
        box-shadow:
            0 4px 0 rgba(8, 22, 54, .8),                 /* ① BỆ mỏng — bề dày của một nút phụ */
            0 9px 20px rgba(0, 0, 0, .45),
            inset 0 1px 0 rgba(255, 255, 255, .38),
            inset 0 -4px 8px rgba(0, 0, 0, .22);
        transition: transform .12s ease-out, box-shadow .12s ease-out,
                    background-color .2s ease, border-color .2s ease, color .2s ease;
    }
    .tk-nut-phu:hover {
        background: rgba(244, 123, 32, .75); border-color: #fff; color: #fff;
        transform: translateY(-2px);
        box-shadow:
            0 6px 0 rgba(120, 52, 4, .85), 0 13px 26px rgba(0, 0, 0, .5),
            inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -4px 8px rgba(0, 0, 0, .22);
    }
    /* ② LÚN — tụt đúng bằng bề dày, bệ mỏng lại còn 1px. */
    .tk-nut-phu:active {
        transform: translateY(3px);
        box-shadow:
            0 1px 0 rgba(8, 22, 54, .85), 0 4px 10px rgba(0, 0, 0, .4),
            inset 0 2px 5px rgba(0, 0, 0, .32);
    }
    .tk-nut-phu:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

    /* ③ VỆT SÁNG CHẠY QUA — `pointer-events: none` để nó ⛔ không nuốt cú bấm: đây là THẺ NEO dự phòng
       lúc JS chết, mà thẻ neo thì ⛔ không có cơ chế `closest` nào cứu lại một cú bấm bị nuốt. */
    .tk-nut-phu::before {
        content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
        pointer-events: none;
        background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .3), transparent);
        transform: skewX(-18deg);
    }
    /* 🔴 CHỈ QUÉT KHI RÊ CHUỘT / VÀO TIÊU ĐIỂM, và CHỈ MỘT LƯỢT — ⛔ đừng chép cái `infinite` của
       `.tk-nut`. Đây chính là điều đợt 1460 lo: hai vệt sáng cùng chạy vô tận trên một màn hình là hai
       thứ TRANH NHAU làm trọng tâm, mà nút góc thì ⛔ không được phép giành. Vệt sáng ở đây là phần
       thưởng cho người ĐANG ĐỊNH BẤM, ⛔ không phải một nhịp nháy suốt ngày. */
    .tk-nut-phu:hover::before,
    .tk-nut-phu:focus-visible::before { animation: tk-nut-phu-loe .85s ease-out 1; }
    @keyframes tk-nut-phu-loe {
        from { left: -60%; }
        to   { left: 130%; }
    }
    .tk-nut-phu-chu { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: .45rem; }
    /* Biểu tượng vẽ bằng NÉT, ăn theo `currentColor` — thay ký tự 🖥 của đợt 1458: mỗi hệ điều hành vẽ
       emoji một kiểu (và Windows vẽ nó XANH ĐẶC, lạc hẳn khỏi bảng màu của màn hình), mà đây là màn
       hình treo tường ⛔ không ai sửa được tại chỗ. */
    .tk-nut-phu-hinh {
        width: 1.15em; height: 1.15em; flex-shrink: 0;
        fill: none; stroke: currentColor; stroke-width: 1.9;
        stroke-linecap: round; stroke-linejoin: round;
    }

    /* ═══ ⭐ ĐỢT 1500 (việc o705) — KHUNG NHÌN THẤP: DẢI NHẬN DIỆN, KHỐI GIỮA VÀ THANH NÚT CHỒNG NHAU ═══

       🩸 CHUYỆN ĐANG HỎNG — đo tận tay 29/08/2026 trên bản tĩnh dựng từ chính `/dang-nhap`:
          · 900×260  ⇒ dải nhận diện chồng khối giữa **11px**
          · 640×280  ⇒ chồng **4px**
          · 667×310 · 812×300 · 1280×300 ⇒ ⛔ không chồng (ngưỡng nằm quanh **~290px**).

       🔑 GỐC BỆNH, ⛔ không phải "quên đặt chiều cao": `.tk-dinh` và `.tk-thanh-nut` đều là
          `position: absolute` neo vào hai mép, nên chúng **⛔ KHÔNG tham gia dòng chảy** — khối giữa
          `.tk-lop` được `justify-content: center` căn giữa trọn chiều cao màn hình **như thể hai thứ
          kia không tồn tại**. Màn hình càng THẤP thì phần chồng càng lớn. Đây là thiết kế ĐÚNG cho
          màn hình treo tường (thứ trang này sinh ra để phục vụ) và chỉ vỡ ở khổ thấp.

       📱 KHỔ THẤP LÀ THẬT, ⛔ đừng bỏ qua: điện thoại XOAY NGANG. Máy 640×360 trong Chrome, trừ thanh
          địa chỉ (~56px) và thanh dưới, còn ~250–300px — mà `/dang-nhap` là màn hình **duy nhất** để
          433 tài khoản vào phần mềm, ⛔ không phải một trang phụ ai cũng có thể bỏ qua.

       🧨 CHÚ THÍCH NÀY CỐ Ý GỌI NÓ LÀ "CÂU MEDIA" BẰNG CHỮ, ⛔ không gõ thẳng cú pháp: Razor phân
          tích dấu @@ ngay cả BÊN TRONG chú thích CSS nằm trong thẻ style, nên gõ thẳng là
          `CS0103: The name 'media' does not exist` — đã dính đúng một lượt build khi viết khối này.
          Cùng họ bẫy "chú thích CSS ⛔ không che được bộ phân tích Razor" ghi ở khối `.tk-hop` dưới.

       ⛔ VÌ SAO PHẢI LÀ MỘT CÂU MEDIA, ⛔ KHÔNG PHẢI ĐỆM DỌC KHAI THẲNG TRÊN `.tk-man`: đệm dọc đổi luôn
          hộp căn giữa ở MỌI khổ ⇒ khối chữ trên màn hình treo tường 1920 · 2560 · 3840 **xê dịch
          theo** — tức lấy một lỗi ở khổ hiếm đi đổi lấy một thay đổi trên đúng những màn hình anh
          Tiến đang nhìn hằng ngày (quy tắc #18: kiểm soát rủi ro lan truyền). Khối này vì thế
          **⛔ không chạm một pixel nào** khi chiều cao > 400px — có số đo chốt ngược.

       🔑 HẠ SÀN CỠ CHỮ chứ ⛔ KHÔNG ẩn bớt nội dung: khẩu hiệu và ngày tháng là thứ anh Tiến đặt ra
          (đợt 1454 · 1464); `display: none` là lặng lẽ lấy đi nội dung của người ta. Ba con số sàn
          dưới đây chỉ thay **vế THỨ NHẤT** của `clamp()`; hai vế sau giữ nguyên nên khổ cao ⛔ không
          đổi. ⚠ Cỡ chữ vẫn bám `vh`/`vw` (⛔ không phải `dvh` — xem `LuatDonViKhungNhin`: `dvh` đổi
          giá trị trong lúc cuộn ⇒ chữ xếp lại theo từng khung hình, đúng chữ "giật giật" đợt 1464). */
    @media (max-height: 400px) {
        /* Dải nhận diện mỏng lại — đo được nó chiếm 68px ở khổ thấp, gần bằng 1/4 màn hình. */
        .tk-dinh { padding: .3rem 1rem; }
        .tk-logo-chip img { height: 1.5rem; }
        /* ⭐ ĐỢT 1999 (việc f45) — tem sự kiện theo chip ở khổ thấp: 1.5rem ảnh + .6rem đệm chip. */
        .tk-dinh .hhc-hh { height: 2.1rem; }

        /* Hạ SÀN ba cỡ chữ. ⛔ Đừng hạ trần: trần là thứ phục vụ màn hình lớn. */
        .tk-gio { font-size: clamp(2rem, min(15vw, 24vh), 40rem); }
        /* ⭐ ĐỢT 1562 — tấm bảng mỏng lại và BỎ bóng gương ở khổ thấp: gương ăn thêm .42em chiều cao,
           đúng thứ đang thiếu. ⛔ Đừng bỏ tấm bảng — nó là chỗ đặt con số, khác hẳn gương (trang trí). */
        .tk-mat { padding: .35rem .8rem .3rem; }
        .tk-guong { display: none; }
        .tk-ngay { font-size: clamp(.8rem, min(2.1vw, 3.4vh), 6rem); }
        .tk-khau-hieu { font-size: clamp(.8rem, min(2.3vw, 3.9vh), 7rem); min-height: 1.3em; }

        /* Chừa chỗ cho hai thứ neo mép. Lệch nhau vì thanh nút dày hơn dải nhận diện.
           📏 Đo 29/08 sau khi đã làm mỏng dải nhận diện: `.tk-dinh` cao **43px** ⇒ đệm trên phải
              LỚN HƠN con số đó, ⛔ không phải xấp xỉ. Bản đầu đặt 2,4rem (38,4px) và ở khổ 800×240
              vẫn chồng **3px** — thiếu đúng phần chênh. Nay 3,4rem = 54,4px.
           ⚠ `position: absolute` neo theo HỘP ĐỆM của khối cha, nên đệm này ⛔ KHÔNG đẩy dải nhận
              diện hay thanh nút đi đâu cả — nó chỉ thu nhỏ hộp căn giữa của khối chữ. Đó chính là
              điều cần: hai thứ kia đứng yên ở mép, khối giữa lùi vào. */
        .tk-man { padding-top: 3.4rem; padding-bottom: 4.2rem; }
        .tk-thanh-nut { bottom: .7rem; }
    }

    /* ═══ HỘP THOẠI ĐĂNG NHẬP ═══
       ⚠ MẶC ĐỊNH HIỆN — xem khối chú thích đầu tệp. Chỉ khi thẻ gốc của tài liệu mang dấu `tk-js`
         (JS chạy được) thì hai luật dưới mới giấu nó đi, và chỉ mở khi có thêm dấu `tk-mo`.
       🧨 ⛔ ĐỪNG gõ tên thẻ gốc kèm hai dấu ngoặc nhọn vào chú thích này: chú thích CSS ⛔ KHÔNG che
         được bộ phân tích Razor — khối `else` ở trên là code block, Razor đọc thấy một thẻ mở không
         có thẻ đóng và ném `RZ9980: Unclosed tag 'html'`. Đã dính đúng một lượt build khi viết tệp
         này (cùng họ bẫy chú thích Razor trong thẻ, quy tắc #5 CLAUDE.md). */
    .tk-hop {
        position: fixed; inset: 0; z-index: 40;
        display: flex; align-items: center; justify-content: center; padding: 1rem;
        background: rgba(2,10,28,.62); backdrop-filter: blur(6px);
        overflow-y: auto;
    }
    html.tk-js .tk-hop { display: none; }
    html.tk-js .tk-hop.tk-mo { display: flex; animation: tk-hien-hop .28s ease-out; }
    @keyframes tk-hien-hop {
        from { opacity: 0; }
        to   { opacity: 1; }
    }

    /* ═══ ⭐ ĐỢT 1577 (việc o882) — TẤM NỀN MỜ DẦN, CÒN THẺ THÌ BUNG RA CÓ ĐỘ NẢY ═══

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

       🔴 HAI HOẠT HOẠ, ⛔ ĐỪNG GỘP LẠI LÀM MỘT NHƯ TRƯỚC ĐỢT NÀY. Bản cũ đặt cả `scale(.94)` lẫn
         `blur(7px)` lên chính `.tk-hop` — mà `.tk-hop` là **TẤM NỀN PHỦ TOÀN MÀN HÌNH** (`inset: 0`),
         nên trong 0,28 giây đầu nó co lại 6% ⇒ **hở một viền màn hình quanh bốn mép** đúng lúc người
         ta vừa bấm nút, và lớp `backdrop-filter` của nó cũng bị nhoè theo. Nay: nền chỉ **mờ dần**,
         còn cú bung dời xuống `.tk-hop-boc` — thẻ thật.
       🔑 Độ nảy đến từ đường cong `cubic-bezier` vượt mốc 1 (`.34, 1.56, .48, 1`), ⛔ không phải từ
         một keyframe phóng quá cỡ rồi thu lại: đường cong thì trình duyệt nội suy trên GPU, còn thêm
         mốc keyframe là thêm chỗ cho hoạt hoạ lệch nhịp giữa `transform` và `opacity`.
       ⚠ Thời lượng .42s là mức đã cân: đây vẫn là **đường vào phần mềm của 433 tài khoản**, ⛔ đừng
         kéo dài hơn cho "ấn tượng" — mỗi lượt đăng nhập phải chờ thêm là một khoản có thật.
       ⚠ `blur` giữ lại nhưng chỉ trên THẺ và chỉ ở khung hình đầu: bộ lọc ấy đắt, đặt trên tấm nền
         phủ toàn màn hình là bắt máy nhoè cả ảnh nền đang trôi bên dưới. */
    .tk-hop-boc {
        animation: tk-bung-the .42s cubic-bezier(.34, 1.56, .48, 1) both;
    }
    @keyframes tk-bung-the {
        from { opacity: 0; transform: scale(.9) translateY(22px); filter: blur(6px); }
        60%  { filter: blur(0); }
        to   { opacity: 1; transform: none;                       filter: none; }
    }

    /* ═══ 🩸 ⭐ ĐỢT 2239 (việc o1717) — LƯỢT **ĐÓNG** CŨNG PHẢI CÓ HOẠT HOẠ ═══

       Anh Tiến 09/09/2026: *"trang đăng nhập đang hiển thị các biểu ngữ theo kiểu bật tắt giật giật
       rất khó chịu, em đổi kiểu ẩn hiện mềm mại có hiệu ứng đẹp"*.

       📏 **GỐC BỆNH, đo sống 09/09 trên app dev 5270**: hai khối ngay trên dựng hẳn hai hoạt hoạ cho
         lượt MỞ (nền `.28s` + thẻ `.42s`), còn lượt ĐÓNG thì `tiep-khach.js` chỉ gỡ lớp `tk-mo` ⇒ luật
         `html.tk-js .tk-hop { display: none }` áp **ngay khung hình kế** ⇒ cả tấm nền mờ lẫn thẻ đăng
         nhập **biến mất trong MỘT khung hình**. Vào thì bung ra, ra thì bốc hơi — chính là cái "bật
         tắt" ấy, và nó giật mạnh nhất ở lượt **tự đóng 30 giây** vì lúc đó ⛔ không ai vừa bấm gì cả.

       🔑 **VÌ SAO PHẢI LÀ MỘT LỚP RIÊNG, ⛔ KHÔNG PHẢI "gỡ `tk-mo` muộn hơn"**: phần tử đã
         `display: none` thì trình duyệt ⛔ không chạy hoạt hoạ nào trên nó nữa — muốn thấy nó tan thì
         phải còn có thứ giữ cho nó được VẼ. Lớp `tk-dang-dong` ở **(0,4,0)** thắng luật ẩn (0,3,0)
         đúng quãng ấy rồi tự rời đi (`animationend` + lưới an toàn 700 ms trong js).
       🔴 **CHIỀU FAIL-OPEN CÒN NGUYÊN, và đó là điều kiện để lớp này được phép tồn tại**: luật đóng
         thuần CSS `#tk-an-hop:target ~ .tk-hop { display: none }` mang ID nên **(1,0,1)** — nó vẫn
         THẮNG lớp này. Người ⛔ không có JavaScript bấm ✕ vẫn đóng được hộp, ⛔ không kẹt lại.
       ⚠ `pointer-events: none` là BẮT BUỘC: trong 0,3 giây ấy hộp vẫn còn trong luồng bấm, ⛔ không
         chặn là cú bấm tiếp theo của người dùng rơi vào một tấm nền **đang biến mất**. */
    html.tk-js .tk-hop.tk-dang-dong {
        display: flex; pointer-events: none;
        animation: tk-tan-hop .3s ease-in both;
    }
    html.tk-js .tk-hop.tk-dang-dong .tk-hop-boc { animation: tk-thu-the .3s ease-in both; }
    @keyframes tk-tan-hop {
        from { opacity: 1; }
        to   { opacity: 0; }
    }
    /* ⓘ Đối xứng với `tk-bung-the` nhưng NGẮN hơn (0,3s so với 0,42s) và ⛔ không có độ nảy: đi ra thì
       dứt khoát, đi vào mới cần chào hỏi. ⛔ Đừng thêm `blur` ở đây — nhoè một tấm đang mờ dần là tốn
       máy mà mắt ⛔ không đọc ra thêm gì. */
    @keyframes tk-thu-the {
        from { opacity: 1; transform: none; }
        to   { opacity: 0; transform: scale(.94) translateY(16px); }
    }

    /* ═══ ⏳ ⭐ ĐỢT 2239 (việc o1717) — DÒNG ĐẾM NGƯỢC TRƯỚC KHI HỘP TỰ ĐÓNG ═══

       Anh Tiến 09/09/2026: *"em kiểm tra hộp thoại đăng nhập cứ tự động tắt vào lượt đầu mở ra"*.
       📏 Đo sống 09/09: mở hộp rồi ⛔ không đụng gì ⇒ hộp tắt ở giây **30,3** — cơ chế chạy ĐÚNG con
         số anh chốt ở đợt 1562, thứ thiếu là **một lời báo trước**. ⇒ ⛔ Không gỡ luật 30 giây (nó là
         chỉ đạo cho màn hình sảnh), chỉ bày ra mấy giây cuối để người đang dùng kịp giữ hộp lại.
       ⚠ Đây là **CẢNH BÁO** — một trong hai ngoại lệ được giữ chữ thường trực trên màn hình (luật
         ngôn từ 30/07); ⛔ đừng đọc nó thành một câu hướng dẫn rồi đem nhét vào `title`.
       ⓘ Số giây do js đóng vào biến `--tk-canh-giay` (suy ra từ `GiayTuDongHop`), ⛔ đừng gõ số vào
         đây: hai nơi nói hai chuyện thì vạch chạy hết mà hộp vẫn còn, hoặc ngược lại. */
    .tk-canh-tu-dong {
        display: flex; align-items: center; gap: .5rem;
        width: 100%; max-width: 400px; margin: .55rem auto 0;
        padding: .35rem .6rem; border-radius: 10px;
        background: rgba(2, 10, 28, .55); border: 1px solid rgba(244, 123, 32, .38);
        color: #ffd7b0; font-size: .78rem; line-height: 1.3; text-align: left;
        animation: tk-canh-hien .35s ease-out both;
    }
    @keyframes tk-canh-hien {
        from { opacity: 0; transform: translateY(-6px); }
        to   { opacity: 1; transform: none; }
    }
    .tk-canh-vach {
        flex: 0 0 46px; height: 4px; border-radius: 999px;
        background: rgba(255, 255, 255, .18); overflow: hidden;
    }
    .tk-canh-vach > i {
        display: block; height: 100%; width: 100%; border-radius: 999px;
        background: linear-gradient(90deg, #f47b20, #ffcf9b);
        transform-origin: left center;
    }
    .tk-hop.tk-sap-dong .tk-canh-vach > i {
        animation: tk-canh-vet var(--tk-canh-giay, 8s) linear both;
    }
    @keyframes tk-canh-vet {
        from { transform: scaleX(1); }
        to   { transform: scaleX(0); }
    }
    .tk-canh-so { font-weight: 600; color: #fff; }

    /* ═══ ⭐ ĐỢT 1562 (việc o854) — ĐỒ HOẠ HỘP THOẠI ĐĂNG NHẬP ═══

       Anh Tiến 30/08/2026: *"trang này là trang bộ mặt của app cần đồ hoạ đẹp, hiệu ứng cách mạng,
       em làm cả hộp thoại đăng nhập"*.

       🔴 CHỈ ĐỔI LỚP TRÌNH BÀY, ⛔ TUYỆT ĐỐI KHÔNG ĐỔI BIỂU MẪU và ⛔ KHÔNG ĐỔI BẢNG MÀU. Mọi luật
          dưới đây bám tiền tố `.tk-hop` ⇒ chúng chỉ áp khi thẻ đăng nhập nằm TRONG hộp thoại của màn
          tiếp khách. Tắt cờ `TiepKhach:Bat` là thẻ trở về đúng dáng cũ ở giữa `.dn-nen`, ⛔ không một
          luật nào ở đây chạm tới nó — đường lui vẫn nguyên vẹn (quy tắc #18).
       🔴 VÌ SAO ⛔ KHÔNG ĐỘNG TỚI MÀU CHỮ / MÀU Ô NHẬP: xem khối chú thích 🔴 ở phần markup của hộp
          (mục "ĐẢO SÁNG"). Ba thứ ở đây là KHUNG, BÓNG và NÚT — ⛔ không thứ nào đụng tới mười luật
          tương phản đã đo của đợt 588. */

    /* Nền phủ sâu hơn — thẻ nổi hẳn khỏi màn trình diễn đang chạy phía sau. */
    .tk-hop {
        background: radial-gradient(ellipse at center, rgba(6, 16, 40, .55), rgba(2, 8, 22, .88));
        backdrop-filter: blur(10px) saturate(1.1);
    }

    /* VÀNH SÁNG QUAY quanh thẻ — cùng kỹ thuật "con quay bị cắt" của bảng đồng hồ (xem `.tk-vanh`).
       ⚠ 210% là con số ĐO: thẻ rộng 400px cao ~560px ⇒ đường chéo ≈688px ≈ 172% bề rộng; hình vuông
         phải lớn hơn thế ở MỌI góc quay. */
    .tk-vien-the {
        position: absolute; inset: -3px; z-index: 0;
        border-radius: 23px; overflow: hidden; pointer-events: none;
    }
    .tk-vien-the i {
        display: block; position: absolute; left: 50%; top: 50%;
        width: 210%; aspect-ratio: 1;
        background: conic-gradient(from 0deg,
            rgba(244, 123, 32, 0)    0deg,
            rgba(244, 123, 32, .9)  46deg,
            rgba(255, 214, 150, 1)  70deg,
            rgba(244, 123, 32, 0)  124deg,
            rgba(105, 170, 255, 0) 200deg,
            rgba(105, 170, 255, .85) 248deg,
            rgba(190, 224, 255, 1) 276deg,
            rgba(105, 170, 255, 0) 326deg,
            rgba(244, 123, 32, 0)  360deg);
        animation: tk-vanh-quay 14s linear infinite;
    }
    @media (prefers-reduced-motion: reduce) { .tk-vien-the i { animation: none; } }

    /* Thẻ: vẫn là KÍNH TRẮNG (⛔ không đổi màu — xem khối 🔴 ở markup), chỉ dày dặn hơn: bo góc lớn
       hơn, kính mờ sâu hơn, bóng đổ tách hẳn khỏi ảnh nền đang trôi. */
    .tk-hop .dn-the {
        position: relative; z-index: 1;
        border-radius: 20px;
        backdrop-filter: blur(16px) saturate(1.2);
        box-shadow: 0 34px 84px rgba(0, 0, 0, .66), inset 0 1px 0 rgba(255, 255, 255, .9);
    }
    .tk-hop .dn-the .dn-vet { border-radius: 20px 20px 0 0; }

    /* Chip bọc logo — trên thẻ trắng thì chip trắng, tức vô hình; nó là lưới đỡ cho ngày ai đó đổi
       nền thẻ. ⛔ Đừng gỡ: `logo-petrolimex.svg` đo được **0 pixel sáng** (đợt 1438), đặt trần lên
       một nền tối là chìm ngay. */
    .tk-hop .dn-logo-chip { border-radius: 12px; padding: .2rem .4rem; }

    /* Ô nhập: chỉ bo tròn hơn và PHÁT SÁNG khi đang gõ.
       ⚠ `:focus` BẮT BUỘC dùng longhand `border-color` — Bootstrap đặt viền lúc focus bằng longhand,
         mà longhand ⛔ không đọc biến `--bs-border-color`. Chép ngược khuôn là mất viền focus, và mất
         LẶNG LẼ. Đây là bài học đã trả giá ở đợt 838 · 840 · 850.
       ⚠ Độ đặc hiệu phải cao hơn khối "ĐẢO SÁNG" (0,4,0) của app.css, nên có `:root[data-theme]`. */
    .tk-hop .dn-the .form-control { border-radius: 12px; padding: .7rem .9rem; }
    :root[data-theme] .tk-hop .dn-the .form-control:focus,
    .tk-hop .dn-the .form-control:focus {
        border-color: #F47B20;
        box-shadow: 0 0 0 .22rem rgba(244, 123, 32, .26);
    }

    /* ═══ NÚT ĐĂNG NHẬP 3D — cùng ba thứ làm nên khối 3D của `.tk-nut` (đợt 1460) ═══
       ① BỆ ĐẶC (`0 6px 0`) = bề dày · ② LÚN khi bấm, tụt đúng bằng bề dày · ③ VỆT SÁNG chạy qua mặt.
       🧨 Chữ BẮT BUỘC bọc trong một thẻ con có `z-index` dương (xem markup DangNhap.razor): `::after`
          là con định vị nên nó vẽ SAU chữ của chính nút ⇒ để chữ trần là mỗi vòng vệt sáng lại xoá chữ
          một lượt. Đúng bẫy đã ghi ở `.tk-nut`.
       🔑 Màu CAM chứ ⛔ không giữ navy: nút Đăng nhập ngoài màn trình diễn đã là khối 3D cam (đợt
          1460) ⇒ hai nút cùng một tiếng nói, người ta bấm cái nào cũng thấy quen tay. Chữ `#241708`
          trên nền cam `#F47B20` đo được **6,4:1**, vượt ngưỡng 4,5:1 của chữ thường. */
    .tk-hop .dn-the .btn-primary {
        position: relative; overflow: hidden;
        border: 0; border-radius: 12px; padding: .72rem;
        background: linear-gradient(120deg, #F47B20, #ff9d4d 55%, #F47B20);
        color: #241708; font-weight: 800; letter-spacing: .6px;
        box-shadow:
            0 6px 0 rgba(140, 62, 6, .92),
            0 14px 28px rgba(0, 0, 0, .45),
            inset 0 1px 0 rgba(255, 255, 255, .5);
        transition: transform .12s ease-out, box-shadow .12s ease-out, filter .2s ease;
    }
    .tk-hop .dn-the .btn-primary:hover {
        transform: translateY(-2px); filter: brightness(1.06);
        background: linear-gradient(120deg, #F47B20, #ff9d4d 55%, #F47B20);
        box-shadow:
            0 8px 0 rgba(140, 62, 6, .95),
            0 18px 34px rgba(0, 0, 0, .5),
            inset 0 1px 0 rgba(255, 255, 255, .55);
    }
    .tk-hop .dn-the .btn-primary:active {
        transform: translateY(4px);
        box-shadow: 0 2px 0 rgba(140, 62, 6, .95), 0 5px 12px rgba(0, 0, 0, .4),
                    inset 0 2px 6px rgba(0, 0, 0, .3);
    }
    .tk-hop .dn-the .btn-primary::after {
        content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 36%;
        pointer-events: none;
        background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .42), transparent);
        animation: tk-nut-luot 5s ease-in-out infinite;
    }
    @keyframes tk-nut-luot {
        0%, 62% { transform: translateX(-180%) skewX(-18deg); }
        100%    { transform: translateX(330%)  skewX(-18deg); }
    }
    .tk-hop .dn-the .dn-nut-chu { position: relative; z-index: 1; }
    @media (prefers-reduced-motion: reduce) { .tk-hop .dn-the .btn-primary::after { animation: none; } }

    /* ═══ 🔴 ĐỢT 1460 (việc o657) — LỐI ĐÓNG KHÔNG CẦN JAVASCRIPT ═══
       Anh Tiến báo kèm ảnh máy triển khai 28/08/2026: *"chuyển từ trình diễn về đăng nhập thì không
       tắt được trang đăng nhập"*.

       🔴 LỖ THIẾT KẾ, ⛔ không phải một lỗi vặt: trước đợt này **CẢ BA** lối đóng (nút ✕ · phím Esc ·
          bấm ra ngoài hộp) đều đi qua `tiep-khach.js`, và phép ẩn thì đi qua dấu `tk-js`. Thiếu một
          trong hai — tệp js không tải được, khối nội tuyến ⛔ không chạy, một lỗi JS ở tệp khác cắt
          ngang — là hộp thoại **KẸT VĨNH VIỄN**: nó vẫn hiện (đúng chiều fail-open, cố ý) nhưng
          ⛔ KHÔNG còn cách nào tắt. Trên màn hình DUY NHẤT để 433 tài khoản vào phần mềm, hỏng theo
          kiểu ấy là hỏng nặng nhất.
       📏 ĐO 28/08 trên bản dev (nhúng thẳng `tiep-khach.js` vào tài liệu rồi bấm thật): bấm Đăng nhập
          ⇒ `display: flex`, bấm ✕ ⇒ `display: none` — tức đường JS **⛔ không hỏng ở đây**. Vì thế bản
          vá này ⛔ KHÔNG đụng đường JS; nó chỉ **thêm một lối thứ hai** cho ca JS chết.

       🔑 CÁCH LÀM — `:target` thuần CSS, ⛔ không thêm một dòng JS nào:
          · nút ✕ là thẻ neo trỏ `#tk-an-hop` ⇒ bấm là `:target` khớp ⇒ hộp ẩn, kể cả khi JS chết;
          · nút Đăng nhập trỏ `#tk-hop` ⇒ hash đổi ⇒ `:target` thôi khớp ⇒ hộp hiện lại.
       ⚠ Luật này mang **ID** nên độ đặc hiệu (1,0,1) **THẮNG** `html.tk-js .tk-hop.tk-mo` (0,3,1).
         Hệ quả BẮT BUỘC nhớ: khi JS SỐNG, `mo()` phải **XOÁ HASH** — không thì người từng bấm ✕ lúc
         JS chết, sau đó JS sống lại, bấm Đăng nhập sẽ ⛔ không mở được hộp. `tiep-khach.js` làm việc
         đó bằng `history.replaceState`; có hàng rào canh. */
    .tk-neo { position: absolute; width: 0; height: 0; overflow: hidden; }
    #tk-an-hop:target ~ .tk-hop { display: none; }

    /* Nút ✕ nằm NGOÀI khối `card-body` của thẻ đăng nhập — cố ý: hàng rào `HopThoaiKhungChungTests`
       bắt ĐỎ mọi nút đóng nằm trong thẻ mang lớp `card`, và `card-body` khớp dấu hiệu đó. */
    .tk-hop-boc { position: relative; }
    .tk-dong {
        position: absolute; top: -14px; right: -14px; z-index: 2;
        width: 38px; height: 38px; border-radius: 50%; cursor: pointer;
        border: 1px solid rgba(255,255,255,.5); background: rgba(10,25,60,.92); color: #fff;
        font-size: 1.05rem; line-height: 1; box-shadow: 0 6px 20px rgba(0,0,0,.5);
        /* Là thẻ NEO từ đợt 1460 (xem khối `:target` ở trên) ⇒ phải tự dựng lại dáng nút. */
        display: inline-flex; align-items: center; justify-content: center; text-decoration: none;
    }
    .tk-dong:hover { background: #F47B20; border-color: #fff; color: #fff; }

    /* ─────────── ⭐ o1276 (05/09/2026) — NÚT «🖥 Trình diễn» Ở GÓC PHẢI: VÙNG CHẠM 44px ───────────
       📏 Đo sống 05/09/2026 (Chrome thật, 390×844, cảm ứng, `do-song-khung-hep.mjs --toan-app`):
          `/dang-nhap` còn đúng MỘT vùng bấm dưới ngưỡng — `a.tk-nut-phu` đo **114,7 × 33px**. Đệm
          `clamp()` ở luật gốc co theo chiều cao khung, nên ở khổ điện thoại nút thấp hơn ngón tay.
       🔑 Chỉ thêm `min-height` đọc biến `--cham-toi-thieu` của `app.css` (khối đợt 1518; tệp này nạp
          SAU app.css nên biến có mặt) — luật gốc đã là `inline-flex` canh giữa, ⛔ không chép lại.
       🔒 Trong `@media (pointer: coarse)` — màn hình tiếp khách ở máy tính/TV ⛔ không đổi một pixel.
       ⚠ Ngưỡng đọc từ BIẾN, ⛔ không gõ số 44px vào đây.
       🚧 Hàng rào: TKNB.Tests/VungChamPhanTrangVaThongKeTests.cs */
    @media (pointer: coarse) {
        .tk-nut-phu { min-height: var(--cham-toi-thieu); }
    }

    /* ═══ 📱 ĐỢT 2194 (việc o1632) — Ở KHỔ ĐIỆN THOẠI, NÚT «TRÌNH DIỄN» ĐANG ĐÈ LÊN TÊN ĐƠN VỊ ═══

       Anh Tiến 07/09/2026: *"rà soát sắp xếp bố cục các màn hình tại thiết bị điện thoại, dạo này
       thiết kế app web có vẻ xấu hơn nhiều"*. Màn hình đầu tiên ai cũng thấy chính là chỗ hỏng nặng
       nhất, và nó hỏng vì **cả tệp này ⛔ KHÔNG có một mốc `max-width` nào** — mọi thứ ở đây thiết
       kế cho màn treo tường, khổ hẹp chưa từng được tính.

       📏 ĐO SỐNG 375×812 trên bản chạy 5270 (trang chào và `/dang-nhap` dùng chung khối này):
         · `.tk-don-vi` «TỔNG KHO XĂNG DẦU NHÀ BÈ» — x 150 → 359, y 22 → 57
         · `a.tk-nut-phu` «Trình diễn»              — x 247 → 361, y 13 → 57
         ⇒ **chồng nhau 112 × 35px**: chữ nút nằm ĐÈ giữa hai dòng tên đơn vị, cả hai cùng ⛔ không
           đọc được. `.tk-dinh` là flex căn GIỮA chiếm trọn bề ngang, còn `.tk-goc-phai` là
           `position: absolute` neo mép phải ⇒ ở màn rộng hai bên còn chỗ trống nên ⛔ không ai thấy,
           ở 375px tên đơn vị nở ra tới sát mép là đè.

       🔑 CHỮA BẰNG HAI VẾ, thiếu vế nào cũng còn đè:
         ① nút co về Ô VUÔNG `--cham-toi-thieu` (44px) — bỏ 114px bề ngang mà cái nhãn chữ đang ăn;
         ② `.tk-dinh` chừa `padding-right` ĐÚNG bằng chỗ nút đứng (44px nút + .55rem lề + thở) ⇒ chữ
            căn giữa trong phần CÒN LẠI, ⛔ không bao giờ bò vào vùng nút nữa.

       ⚠ Nhãn chữ giấu khỏi MẮT chứ ⛔ KHÔNG `display: none` — máy đọc màn hình phải còn đọc được
         «Trình diễn». Đây cũng đúng chỗ quy tắc #23 CHO PHÉP `title`: thẻ `<a>` đã mang
         `title="Trình diễn"` sẵn, và nay chữ ấy bị ẩn thật nên `title` thành đúng vai của nó.

       🔒 Khối bọc trong `max-width: 576px` — mốc điện thoại chung của dự án
         (`LuatHaiCotDanhSachTrangChu.KhoDienThoaiToiDaPx`), để mọi khung của app đổi dáng ở CÙNG một
         bề ngang. Màn treo tường và máy tính ⛔ không đổi một pixel. */
    @media (max-width: 576px) {
        .tk-goc-phai { top: .55rem; right: .55rem; }
        .tk-nut-phu {
            min-width: var(--cham-toi-thieu); min-height: var(--cham-toi-thieu);
            justify-content: center; padding: .5rem;
        }
        .tk-nut-phu-nhan {
            position: absolute; width: 1px; height: 1px; margin: -1px;
            padding: 0; border: 0; overflow: hidden; white-space: nowrap; clip-path: inset(50%);
        }
        .tk-dinh { padding-right: 3.6rem; }
    }
