  /* ============ ĐĂNG NHẬP ============ */
  /* 🏛 06/08/2026 — TRANG ĐĂNG NHẬP bản doanh nghiệp.
     Bản cũ: một ô trắng nhỏ nổi giữa nền teal→CAM, xung quanh trống hoác (cô Quỳnh:
     "bị thiếu trống không có gì trên màn hình"). Nay chia HAI KHOANG: trái giới thiệu
     trung tâm, phải ô đăng nhập — bố cục chuẩn của phần mềm quản trị.
     Nền đổi sang xanh sâu một tông cho khớp thanh tên trong app, bỏ hẳn cam. */
  .man-dn { position:fixed; inset:0; display:flex; align-items:center; justify-content:center;
            background:linear-gradient(118deg, #072A31 0%, #0E545C 52%, #12808A 105%);
            z-index:100; padding:24px; overflow:auto; }
  /* ══════════════════════════════════════════════════════════════════════════
     SẢNH ĐĂNG NHẬP KIỂU "AUTH SWITCH" — Boss chốt 10/09/2026
     Mẫu: https://21st.dev/@appvibed01/components/auth-switch (#9345), dịch từ
     React + Tailwind sang CSS thuần vì app này không có React.

     Cách chạy: hai form xếp CHỒNG cùng một ô lưới, cả cụm trượt trái ↔ phải;
     phía sau là một vòng tròn màu khổng lồ (2000px) cũng trượt ngược lại. Ảo
     giác "hai nửa đổi chỗ cho nhau" sinh ra từ hai chuyển động ngược chiều ấy.

     ⛔ MÀU LẤY TỪ LOGO TRUNG TÂM, không phải màu tím của mẫu — Boss dặn thẳng
        *"lấy màu của trung tâm"*: teal #14A0A0 và xanh lá #00793A.
     ⛔ VÒNG TRÒN PHẢI NẰM DƯỚI FORM. `z-index` của nó thấp hơn `.dn-truot`, nếu
        không thì nó phủ kín ô gõ mật khẩu và không ai đăng nhập được.
     ⛔ Bo góc ghi số thẳng, ĐỪNG dùng `--r-xl` — biến ấy là 0px cho toàn app
        theo kiểu Google Sheets Boss đã chốt; sửa nó là đổi dáng mọi panel.
     ══════════════════════════════════════════════════════════════════════════ */
  .dn-khung {
    position:relative; overflow:hidden;
    width:min(96vw, 1000px); min-height:560px;
    border-radius:16px; background:#fff;
    box-shadow:0 26px 70px rgba(4,26,30,.5);
  }

  /* ---- Vòng tròn màu chạy phía sau ---- */
  .dn-vong {
    position:absolute; height:2000px; width:2000px;
    top:-10%; right:48%; transform:translateY(-50%);
    /* ⛔⛔ ĐỪNG GÕ CỨNG MÀU Ở ĐÂY. App này chạy cho NHIỀU trung tâm; màn đăng
       nhập là thứ nhân viên trung tâm khác nhìn thấy ĐẦU TIÊN mỗi sáng, và một
       vòng tròn teal MyPAS chiếm nửa màn thì họ tưởng vào nhầm app. Hai biến
       dưới đây để server/thuong-hieu.js đè theo màu của từng trung tâm; giá
       trị lùi là màu MyPAS, nên bản gốc không đổi một pixel nào. */
    background:linear-gradient(-45deg,
      var(--th-vong-1, #14A0A0) 0%,
      var(--th-vong-2, #00793A) 100%);
    border-radius:50%; z-index:1;
    transition:transform 1.5s ease-in-out, right 1.5s ease-in-out;
  }
  .dn-khung.dn-che-do-dk .dn-vong { transform:translate(100%, -50%); right:52%; }

  /* ---- Cụm hai form, trượt ngang ---- */
  .dn-truot {
    position:absolute; top:50%; left:75%; transform:translate(-50%, -50%);
    width:50%; z-index:5;
    display:grid; grid-template-columns:1fr;
    transition:left 1s .55s ease-in-out;
  }
  .dn-khung.dn-che-do-dk .dn-truot { left:25%; }

  /* ⛔ ĐÈ `[hidden]` CHO HAI FORM NÀY — và chỉ hai form này.
     `css/nen.css` khai `[hidden] { display:none !important }`, mà
     `hienMan()` thì bật `hidden` cho form không dùng tới. Để nguyên là form
     biến mất hẳn giữa lúc đang trượt, hiệu ứng đứt phựt. Chúng phải NẰM YÊN
     ĐÓ và chỉ mờ đi. Đè một `!important` thì buộc phải dùng `!important`. */
  .dn-truot > .dn-form,
  .dn-truot > .dn-form[hidden] {
    display:flex !important;
    grid-column:1 / 2; grid-row:1 / 2;
    flex-direction:column; align-items:stretch; justify-content:center;
    padding:0 3rem; overflow:hidden;
    transition:opacity .25s .55s;
  }
  .dn-truot > .dn-form-vao { opacity:1; z-index:2; }
  .dn-truot > .dn-form-moi { opacity:0; z-index:1; pointer-events:none; }
  .dn-khung.dn-che-do-dk .dn-truot > .dn-form-vao { opacity:0; z-index:1; pointer-events:none; }
  .dn-khung.dn-che-do-dk .dn-truot > .dn-form-moi { opacity:1; z-index:2; pointer-events:auto; }

  .dn-form-logo { margin-bottom:14px; }
  .dn-form-logo .logo-mypas .ten { font-size:30px; }
  .dn-tieu { margin:0 0 16px; font-size:22px; font-weight:700; color:var(--chu); }

  /* ---- Hai khoang mời ---- */
  .dn-khoang-boc {
    position:absolute; inset:0; z-index:6;
    display:grid; grid-template-columns:repeat(2, 1fr);
    pointer-events:none;
  }
  /* ⛔⛔ PHẢI CÓ z-index Ở ĐÂY. Vòng tròn màu là ANH EM CÙNG CHA với hai
     khoang này, và nó có z-index 1 còn khoang thì không khai gì — nên vòng
     tròn nằm TRÊN, phủ kín chữ mời và nút "Tạo tài khoản". Nhìn ảnh chụp thì
     nửa trái trống trơn một mảng xanh, trong khi mọi phép đo đều báo chữ nằm
     đúng chỗ và màu trắng rõ ràng. Bắt được 10/09 nhờ nhìn ảnh, không nhờ số. */
  .dn-khoang {
    position:relative; z-index:2;
    display:flex; flex-direction:column; justify-content:center;
    text-align:center; padding:3rem 2rem;
  }
  .dn-khoang-trai { pointer-events:all; }
  .dn-khoang-phai { pointer-events:none; }
  .dn-khung.dn-che-do-dk .dn-khoang-trai { pointer-events:none; }
  .dn-khung.dn-che-do-dk .dn-khoang-phai { pointer-events:all; }

  .dn-khoang-noi { color:#fff; transition:transform .9s .5s ease-in-out; }
  .dn-khoang-phai .dn-khoang-noi { transform:translateX(800px); }
  .dn-khung.dn-che-do-dk .dn-khoang-trai .dn-khoang-noi { transform:translateX(-800px); }
  .dn-khung.dn-che-do-dk .dn-khoang-phai .dn-khoang-noi { transform:translateX(0); }

  .dn-khoang-noi h3 { margin:0 0 10px; font-size:21px; font-weight:600; line-height:1.25; }
  .dn-khoang-noi p { margin:0 0 18px; font-size:13.5px; line-height:1.6;
    color:rgba(255,255,255,.86); }
  /* ⛔ Đích bấm tối thiểu 44px (Apple) / 48dp (Google) — nút này là đường duy
     nhất sang nửa bên kia, hụt vài pixel là người dùng bấm trượt hoài. */
  .dn-nut-doi {
    min-height:44px; padding:0 22px; border-radius:44px;
    background:none; border:2px solid #fff; color:#fff;
    font-size:13.5px; font-weight:600; cursor:pointer;
    transition:background .25s, transform .18s;
  }
  .dn-nut-doi:hover { background:rgba(255,255,255,.14); transform:translateY(-2px); }

  /* ---- Quên / đặt lại mật khẩu: lớp phủ đè lên (Boss chốt) ---- */
  .dn-phu {
    position:absolute; inset:0; z-index:20;
    display:flex; align-items:center; justify-content:center;
    padding:24px; background:rgba(6, 34, 38, .5);
    backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
    opacity:0; pointer-events:none; transition:opacity .22s;
  }
  .dn-khung.dn-che-do-phu .dn-phu { opacity:1; pointer-events:auto; }
  .dn-form-phu {
    width:min(100%, 400px); background:#fff; border-radius:14px;
    padding:26px 24px; box-shadow:0 18px 50px rgba(4,26,30,.4);
    flex-direction:column;
  }

  /* 📱 MÀN HẸP — mẫu gốc xếp dọc và cho vòng tròn chạy lên xuống thay vì ngang.
     ⛔ ĐỪNG chỉ thu nhỏ bản ngang lại. Ở 390px thì hai khoang cạnh nhau còn
        chưa tới 180px mỗi bên, chữ vỡ thành từng chữ một. */
  @media (max-width:900px) {
    .man-dn { padding:14px; }
    .dn-khung { width:min(96vw, 460px); min-height:min(88vh, 760px); }
    .dn-vong {
      width:1500px; height:1500px;
      left:30%; bottom:68%; right:auto; top:auto;
      transform:translateX(-50%);
      transition:transform 1.6s ease-in-out, bottom 1.6s ease-in-out;
    }
    .dn-khung.dn-che-do-dk .dn-vong { transform:translate(-50%, 100%); bottom:32%; right:auto; }
    .dn-truot {
      width:100%; left:50%; top:92%; transform:translate(-50%, -100%);
      transition:top 1s .6s ease-in-out;
    }
    .dn-khung.dn-che-do-dk .dn-truot { left:50%; top:8%; transform:translate(-50%, 0); }
    .dn-truot > .dn-form,
    .dn-truot > .dn-form[hidden] { padding:0 1.4rem; }
    .dn-khoang-boc { grid-template-columns:1fr; grid-template-rows:1fr 2fr 1fr; }
    .dn-khoang { padding:1.6rem 1.4rem; grid-column:1 / 2; }
    .dn-khoang-trai { grid-row:1 / 2; }
    .dn-khoang-phai { grid-row:3 / 4; }
    .dn-khoang-noi h3 { font-size:17px; }
    .dn-khoang-noi p { font-size:12px; margin-bottom:12px; }
    .dn-khoang-phai .dn-khoang-noi { transform:translateY(300px); }
    .dn-khung.dn-che-do-dk .dn-khoang-trai .dn-khoang-noi { transform:translateY(-300px); }
    .dn-khung.dn-che-do-dk .dn-khoang-phai .dn-khoang-noi { transform:translateY(0); }
    .dn-form-logo .logo-mypas .ten { font-size:26px; }
  }

  /* ⛔ Ai đã tắt hiệu ứng chuyển động trong hệ điều hành thì phải tôn trọng —
     vòng tròn 2000px trượt qua màn là thứ gây chóng mặt đúng nghĩa. */
  @media (prefers-reduced-motion: reduce) {
    .dn-vong, .dn-truot, .dn-khoang-noi, .dn-truot > .dn-form { transition:none; }
  }

  /* ============ LOGO MyPAS ============
     Dựng bằng chữ theo đúng logo trên website: "My" cam + "PAS" teal, dưới có
     dòng "Perseverance and Success". Chưa có file ảnh logo gốc nên tạm dựng bằng
     CSS — có file .png/.svg thì thay vào đây là xong, không phải sửa chỗ khác. */
  /* ☰ 08/09/2026 — NÚT BA GẠCH cạnh logo, mở ngăn kéo công cụ. Boss: *"ở bên trái
     ở logo đó sẽ có 1 cái 3 gạch ngang như bên Facebook ấy"*.
     ⛔ MÁY TÍNH ẨN HẲN. Bên ấy đã có thanh dọc bày sẵn mọi công cụ; thêm nút này là
        hai đường vào cùng một thứ, người dùng phải đoán xem hai cái khác nhau chỗ nào.
        Luật hiện nó nằm trong khối `@media (max-width:820px)` ở css/lop.css. */
  .tt-bagach { display:none; }
  .logo-mypas { display:flex; flex-direction:column; line-height:1; }
  .logo-mypas .ten { font-size:26px; font-weight:800; letter-spacing:-.02em; }
  .logo-mypas .ten .my  { color:var(--cam); }
  .logo-mypas .ten .pas { color:var(--xanh); }
  .logo-mypas .cham { font-size:8.5px; font-weight:600; letter-spacing:.055em;
                      color:var(--xanh); margin-top:3px; text-transform:none; white-space:nowrap; }
  /* bản dùng trên nền teal (màn đăng nhập) */
  .logo-mypas.tren-nen .ten .pas, .logo-mypas.tren-nen .cham { color:#fff; }
  .logo-mypas.bam-duoc { cursor:pointer; border-radius:var(--r-md); padding:4px 8px; margin-left:-8px;
                         transition:background .15s; }
  .logo-mypas.bam-duoc:hover { background:var(--xanh-nhat); }
  .logo-mypas.bam-duoc:focus-visible { outline:2px solid var(--xanh); outline-offset:2px; }

  .logo-dn { display:flex; align-items:center; gap:12px; margin-bottom:20px;
             padding-bottom:14px; border-bottom:2px solid var(--xanh-nhat); }
  .logo-dn .doc { border-left:2px solid var(--vien); padding-left:12px; }
  .logo-dn b { font-size:15px; display:block; }
  .logo-dn small { display:block; color:var(--mo); font-weight:400; font-size:11.5px; margin-top:2px; }
  .o-nhap { margin-bottom:12px; }
  .o-nhap label { display:block; font-size:12px; font-weight:700; color:var(--mo); margin-bottom:5px; }
  .o-nhap input { width:100%; height:42px; border:1px solid var(--vien); border-radius:var(--r-o, 8px);
                  padding:0 12px; font-size:14px; }
  .o-nhap input:focus { outline:2px solid var(--xanh); border-color:transparent; }
  /* Ô mật khẩu có nút con mắt — người dùng gõ tiếng Việt hay bị bộ gõ biến chữ
     ngay trong ô mật khẩu mà không thấy; bấm mắt ra chữ là biết ngay gõ sai đâu. */
  .o-mk { position:relative; }
  .o-mk input { padding-right:44px; }
  .nut-mat { position:absolute; right:6px; bottom:5px; width:32px; height:32px; border:none;
             background:transparent; font-size:17px; color:var(--mo); border-radius:var(--r-md); }
  .nut-mat:hover { background:#EEF3F5; }
  .nut-chinh { width:100%; height:44px; border:none; border-radius:var(--r-lg); background:var(--xanh);
               color:#fff; font-size:15px; font-weight:700; }
  .nut-chinh:hover { background:var(--xanh-dam); }
  .nut-chinh:disabled { opacity:.6; }
  /* ⭐ BO TRÒN RIÊNG TRONG SẢNH ĐĂNG NHẬP — Boss chốt 03/09/2026.
     ⛔ PHẢI KẸP TRONG `.man-dn`. `.o-nhap` và `.nut-chinh` được dùng khắp app
        (đọc khối chú thích ngay dưới `.nut-chinh`), bo trần là bo luôn mọi ô
        nhập và mọi nút chính của cả app — đúng thứ Boss đã chê là "lộ ra ui AI".
     Ba dòng này chỉ chạm màn đăng nhập / đăng ký / quên mật khẩu. */
  .man-dn .o-nhap input { border-radius:var(--r-o, 8px); }
  .man-dn .nut-chinh { border-radius:10px; }
  .man-dn .nut-mat { border-radius:8px; }
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ `width:100%` Ở TRÊN LÀ DI SẢN CỦA Ô ĐĂNG NHẬP — 21/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     `.nut-chinh` sinh ra cho nút "Đăng nhập" trong một khung hẹp 340px, nên kéo
     hết bề ngang là đúng. Nhưng nay nó được dùng khắp app, kể cả trong các THANH
     CÔNG CỤ nằm ngang giữa màn hình rộng — ở đó `width:100%` biến một cái nút
     thành DẢI MÀU TEAL 1.280px chạy suốt màn hình, và đẩy mấy nút bên cạnh xuống
     hàng dưới.
     Tôi chụp màn và bắt được hai chỗ: "Tạo block nhân viên" ở công cụ Công việc,
     "Lưu quyền" ở trang Quyền theo chức vụ. Đúng loại lỗi cô Quỳnh gọi là
     *"các nút sắp xếp rất xấu"* và *"lộ rõ ui AI"*.

     ⛔ KHÔNG SỬA LUẬT GỐC Ở TRÊN. Bỏ `width:100%` là mọi nút trong hộp thoại và
        khung đăng nhập co lại thành nút con con giữa khung — hỏng hàng chục màn
        cùng lúc để chữa hai màn. Thay vào đó khai đích danh từng THANH NGANG ở
        dưới: trong thanh thì nút rộng theo chữ, ngoài thanh thì vẫn như cũ.
     ⛔ Dựng thanh nút NGANG mới thì thêm tên nó vào danh sách này, không thì lại
        mọc thêm một dải teal nữa. */
  .nv-thanh > .nut-chinh,
  .pq-day > .nut-chinh,
  .pq-day > .nut-nho { width:auto; flex:none; padding:0 16px; }
  .dn-loi { color:var(--do); font-size:13px; min-height:18px; margin:8px 0 2px; }
  .dn-doi { text-align:center; margin-top:12px; font-size:13px; color:var(--mo); }
  .dn-doi a { color:var(--xanh); font-weight:700; cursor:pointer; text-decoration:none; }

  /* ============ KHUNG APP ============ */
  /* 🏷 Khung MyPAS bo tròn + căn giữa (cô Quỳnh 03/08). Trước là thanh trắng full
     bề ngang; nay thành thẻ bo góc nổi giữa trang, viền teal mảnh giữ nhận diện. */
  /* 🎨 22/08/2026 — VẠCH NHẬN DIỆN TEAL GIỮ LẠI, chỉ mảnh đi.
     Ban đầu tôi bỏ hẳn vạch teal 2px cho "sạch". Cô Quỳnh nhắc ngay: *"ko được để
     trắng quá nhiều nên cho 1 số chỗ có màu nhận diện thương hiệu là tốt nhất"*.
     Đúng — đây là thanh trên cùng, nơi hợp lý nhất để đặt màu trung tâm.
     ⛔ 2px (không phải 1px, không phải 3px): 1px lẫn vào viền thường không ai thấy,
        3px thành một dải màu kẻ ngang cả màn hình.
     ⛔ Bóng vẫn dùng `--bong-1`, đừng trả lại bóng toả 18px cũ. */
  .thanh-tren { position:sticky; top:0; z-index:50; background:var(--the);
                display:flex; align-items:center; gap:12px; padding:9px 20px;
                /* ⛔ 22/08/2026 — BỎ TRẦN 1680px. Xem khối lý do ngay trên: trần này
                   là phần sót lại của lần bỏ trần ngày 21/08, và nó làm thanh trên
                   hụt 116px mỗi bên so với nội dung bên dưới.
                   ⛔ `margin:0 14px 8px` chứ KHÔNG `0 auto 8px`: đã bỏ trần thì
                      `auto` không còn căn giữa cái gì nữa (không có chỗ thừa để
                      chia), nó chỉ thành mép 0 — tức dán sát viền màn hình. */
                /* 🔗 02/09/2026 — LỀ VỀ 0 để thanh này dán liền bảng bên dưới.
                   Khối lý do ngay trên vẫn đúng: đã bỏ trần thì auto vô nghĩa.
                   Nay bỏ nốt 14px hai bên và 8px dưới — chính vệt trắng cô Quỳnh
                   chỉ. Vạch teal 2px ở đáy GIỮ NGUYÊN, không liên quan. */
                max-width:none; margin:0;
                border-radius:0 0 var(--r-xl) var(--r-xl);
                border:1px solid var(--vien); border-top:none;
                /* 🟢 02/09/2026 — cô Quỳnh: *"cái dọc màu xanh in đậm hơn để rõ được
                   vạch kẻ ngăn cách giữa thanh trên cùng và bên dưới app, in đậm nhưng
                   không được quá in đậm"*. 2px → 3px, đúng một bậc.
                   ⛔ PHẢI ĐỔI CẢ HAI CHỖ: dòng này (thanh lúc ở trong lớp / màn hẹp) và
                      dòng trong khối @media màn rộng bên dưới. Sửa một chỗ là vạch đổi
                      độ đậm khi vào lớp, nhìn như app lỗi. */
                border-bottom:5px solid var(--xanh);
                box-shadow:var(--bong-1); }
  .thanh-tren .logo-mypas .ten { font-size:23px; }
  .thanh-tren .ten-app { font-size:15.5px; padding-left:12px; border-left:1px solid var(--vien);
                         color:var(--chu); }
  /* ---- Chữ "Điểm danh" bấm được để đổi phần (26/07/2026) ---- */
  .ten-app-nut { font-weight:700; background:none; border:none; cursor:pointer;
                 display:flex; align-items:center; gap:5px; border-radius:var(--r-md);
                 padding:5px 9px 5px 12px; border-left:1px solid var(--vien); }
  .ten-app-nut:hover { background:var(--xanh-nhat); }
  .ten-app-nut .mui-phan { font-size:11px; color:var(--mo); }
  .phan-menu { position:absolute; top:52px; left:150px; z-index:60; background:#fff;
               border:1px solid var(--vien); border-radius:var(--r-lg); padding:6px;
               box-shadow:0 10px 28px rgba(0,0,0,.14); min-width:210px; }
  .phan-menu button { display:block; width:100%; text-align:left; border:none;
                      background:none; padding:10px 12px; border-radius:var(--r-md);
                      font-size:14.5px; cursor:pointer; }
  .phan-menu button:hover { background:var(--nen); }
  .phan-menu button.dang { background:var(--xanh-nhat); font-weight:700; }

  /* ---- PROGRESS TEST ---- */
  .pt-luoi { display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
             gap:11px; margin-top:14px; }
  .pt-o { position:relative; background:#fff; border:1px solid var(--vien); border-radius:12px;
          padding:13px 14px; cursor:pointer; text-align:left; transition:.15s; }
  .pt-o:hover { border-color:var(--xanh); box-shadow:0 4px 14px rgba(0,0,0,.07); }
  .pt-o b { display:block; font-size:14.5px; margin-bottom:4px; }
  .pt-o small { color:var(--mo); font-size:12.5px; }
  .pt-o .xong { color:var(--o-tot); font-weight:700; }
  .pt-o .chua { color:var(--cam-dam); font-weight:700; }
  .pt-hai-cot { display:grid; grid-template-columns:290px 1fr; gap:16px; margin-top:12px;
                align-items:start; }
  @media (max-width:820px) { .pt-hai-cot { grid-template-columns:1fr; } }
  .pt-diem { background:#fff; border:1px solid var(--vien); border-radius:12px; padding:14px; }
  .pt-diem h4 { margin:0 0 10px; font-size:13px;
                color:var(--mo); }
  .pt-diem .d { display:flex; justify-content:space-between; padding:7px 0;
                border-bottom:1px dashed var(--vien); font-size:14px; }
  .pt-diem .d:last-child { border-bottom:none; }
  .pt-diem .d b { font-size:15px; }
  .pt-form { background:#fff; border:1px solid var(--vien); border-radius:12px; padding:16px; }
  /* ⛔⛔ `.pt-muc` LÀ TÊN DÙNG CHUNG CỦA HAI THỨ KHÁC HẲN NHAU — bắt được 21/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     Ở ĐÂY (`pt-` = "progress test") nó là MỘT MỤC TRONG FORM CHẤM ĐIỂM: bên trong có
     `<label>`, `<textarea>`, `<select>` — xem mấy luật ngay dưới.
     Ở DƯỚI, trong khối `.pt-to` (`pt-` = "phiếu trả"), CŨNG có `.pt-muc` nhưng là
     TIÊU ĐỀ MỤC trên tờ gửi phụ huynh.

     Hôm nay tôi thiết kế lại tờ phiếu và suýt ghi đè luật này bằng luật của tờ phiếu
     — làm thế thì form chấm điểm mất hết khoảng cách giữa các mục, mà chẳng có lỗi
     nào báo ra. Nay mọi luật của tờ phiếu đều gắn tiền tố `.pt-to` để không với sang
     đây được nữa.
     ⛔ Ai đổi `.pt-muc` ở một trong hai chỗ thì mở CẢ HAI ra xem trước. */
  .pt-muc { margin-bottom:18px; }
  .pt-muc > label { display:block; font-weight:700; margin-bottom:7px; font-size:14.5px; }
  .pt-muc textarea, .pt-muc input, .pt-muc select {
      width:100%; border:1px solid var(--vien); border-radius:var(--r-o, 8px); padding:9px 11px;
      font:inherit; font-size:14px; }
  .pt-muc textarea { min-height:64px; resize:vertical; }
  .pt-muc select:focus, .pt-muc textarea:focus, .pt-muc input:focus {
      outline:2px solid var(--xanh); border-color:transparent; }
  .pt-otrong { margin-top:7px; display:grid; gap:6px; }
  .pt-otrong textarea { min-height:70px; resize:vertical; }
  .pt-them { margin-top:7px; display:flex; gap:8px; flex-wrap:wrap; }
  .pt-them button { border:1px dashed var(--vien); background:#fff; border-radius:8px;
                    padding:5px 11px; font-size:12.5px; cursor:pointer; color:var(--mo); }
  .pt-them button:hover { border-color:var(--xanh); color:var(--xanh-dam); background:var(--xanh-nhat); }
  .pt-them .pt-xoa-nut:hover { border-color:var(--do); color:var(--do); background:#FDECEA; }
  /* 🙈 05/10/2026 hộp «Sửa danh sách lựa chọn» — mỗi lựa chọn có sẵn một dòng, nút Ẩn / Hiện lại bên phải. */
  .pt-sua-ds { display:grid; gap:6px; margin-top:8px; }
  .pt-sua-dong { display:flex; align-items:center; gap:10px; padding:8px 10px;
                 border:1px solid var(--vien); border-radius:8px; }
  .pt-sua-chu { flex:1; min-width:0; font-size:13.5px; line-height:1.45; }
  .pt-sua-dong.da-an .pt-sua-chu { color:var(--mo); }
  .pt-sua-trang, .pt-sua-luon { flex:none; font-size:12px; color:var(--mo); white-space:nowrap; }
  .pt-sua-dong .nut-nho { flex:none; }
  /* 🧹 06/10/2026 phần «Lựa chọn giáo viên tự thêm» cùng hộp — chia theo người, số đã dùng /30, nút xoá. */
  .pt-sua-tieu { margin-top:18px; padding-top:12px; border-top:1px solid var(--vien); font-size:13.5px; font-weight:600; }
  .pt-sua-nguoi { display:flex; align-items:center; flex-wrap:wrap; gap:6px 10px; margin-top:12px; }
  .pt-sua-ten { flex:1; min-width:0; font-size:13px; font-weight:600; }
  .pt-sua-so { font-weight:400; color:var(--mo); font-variant-numeric:tabular-nums; }
  .pt-sua-trong { margin-top:6px; font-size:13px; color:var(--mo); }
  .nut-nho.pt-sua-xoa:hover { border-color:var(--do); color:var(--do); }
  /* 👥 05/10/2026 hộp HỎI LẠI khi đổi giáo viên (`hoiDoiGiaoVien`, js/tinh-nang.js) — lớp phủ
     riêng nằm TRÊN hộp thoại chung (.modal-nen = 12000) để «Huỷ» quay về đúng hộp đang sửa. */
  .gvxn-nen { position:fixed; inset:0; z-index:13000; display:flex; align-items:center; justify-content:center;
              padding:16px; background:rgba(10,25,30,.55); }
  .gvxn-hop { background:#fff; color:var(--chu); border-radius:var(--r-xl); width:min(94vw, 460px);
              max-height:86vh; overflow:auto; padding:22px; box-shadow:0 18px 50px rgba(0,0,0,.28); }
  body.toi .gvxn-hop { background:var(--the); }
  .gvxn-hop h3 { margin:0 0 14px; font-size:17px; text-wrap:balance; }
  .gvxn-ds { display:grid; grid-template-columns:auto 1fr; gap:8px 14px; margin:0 0 12px; font-size:14px; }
  .gvxn-ds dt { color:var(--mo); }
  .gvxn-ds dd { margin:0; font-weight:600; }
  .gvxn-ds dd.gvxn-trong { color:var(--do); }
  .gvxn-ghi { margin:0 0 10px; font-size:13px; color:var(--mo); line-height:1.5; }
  .gvxn-canh { margin:0 0 10px; padding:8px 10px; border-radius:8px; font-size:13px; line-height:1.5;
               color:var(--do); background:color-mix(in srgb, var(--do) 9%, transparent); }
  .gvxn-ly { display:grid; gap:6px; font-size:13px; color:var(--mo); margin:4px 0 16px; }
  .gvxn-ly input { height:40px; font-size:14px; }
  .gvxn-nut { display:flex; justify-content:flex-end; gap:10px; }
  .gvxn-nut .nut-chinh { width:auto; padding:0 18px; }
  /* 📒 05/10 khối «Lịch sử giáo viên» (hộp lớp → tab Lớp, man-hinh/lich-giao-vien.js) */
  .bll-ls > summary { display:list-item; cursor:pointer; }
  .bll-ls-gv { display:grid; gap:8px; margin:8px 0 0; padding:0; list-style:none; }
  .bll-ls-gv li { padding:8px 10px; border:1px solid var(--vien); border-radius:8px; font-size:13px; line-height:1.5; }
  .bll-ls-gv .bll-ls-doi { font-weight:600; }
  .bll-ls-gv .bll-ls-phu { color:var(--mo); font-size:12px; }
  .pt-tick { display:flex; align-items:flex-start; gap:8px; padding:7px 0; font-size:14px; }
  .pt-tick input { width:auto; margin-top:3px; }
  .pt-tudong { background:var(--xanh-nhat); border-radius:9px; padding:11px 13px;
               font-size:13.5px; white-space:pre-wrap; line-height:1.55; }
  .pt-day { position:sticky; bottom:0; background:#fff; border-top:1px solid var(--vien);
            padding:12px 0 4px; display:flex; gap:9px; justify-content:flex-end;
            flex-wrap:wrap; margin-top:6px; }
  .pt-day .trai { margin-right:auto; color:var(--mo); font-size:13px; align-self:center; }
  .thanh-tren .day { flex:1; }
  /* ⛔ 29/08/2026 — HAI NÚT THÔNG BÁO + GÓP Ý ĐÃ DỜI xuống thanh công cụ dọc, nhưng
     THẺ của chúng vẫn ở lại thanh trên làm chỗ chứa số chưa đọc (`#chuongSo`,
     `#gopYSo`, `#ccBadgeLGV`). Luật này là thứ DUY NHẤT ẩn chúng đi.
     `display:none` chứ đừng `visibility:hidden` — cái sau vẫn chiếm chỗ, thanh trên
     sẽ có hai khoảng trống không ai hiểu vì sao. Xem chú thích ở `#nutChuong`.
     ⛔⛔ ĐÃ MẤT MỘT LẦN, 06/09/2026: luật này nằm LỌT GIỮA khối CSS của streak, nên
        lúc bỏ streak nó bị cắt theo. Boss thấy ngay chuông và bóng đèn hiện lù lù
        trên thanh, mà cả 486 bài kiểm vẫn xanh. Nay đã có bài `thu-nut-da-doi-cho.js`
        đứng gác. ⛔ ĐỪNG gom luật này vào bất kỳ khối tính năng nào — nó là luật
        RIÊNG của thanh trên, phải đứng một mình để không ai cắt nhầm lần nữa. */
  .thanh-tren .da-doi-cho { display:none !important; }
  /* 🔥 STREAK LỬA — ĐÃ BỎ HẲN 06/09/2026 theo lệnh Boss: *"tôi ko cần cái streak
     lửa ở trang chủ và ở trên cái thanh nữa"*. Bỏ cả CSS, thẻ và hàm vẽ. */
  /* 🎨 22/08/2026 — NÚT theo nếp shadcn.
     ⛔ `background:#fff` cũ là màu GÁN CỨNG — ở nền tối nó thành nút trắng chói
        giữa màn đen. Đổi sang `var(--the)` là sửa một lỗi thật, không chỉ đổi gu.
     ⛔ Rê chuột thì đổi NỀN chứ đừng đổi màu chữ sang teal: chữ teal trên nền trắng
        chỉ đạt tương phản ~3,4 lần — dưới chuẩn đọc, mà lại đúng lúc người ta đang
        nhắm vào nút để bấm. */
  .nut-nho { border:1px solid var(--vien); background:var(--the); border-radius:var(--r-md);
             padding:7px 13px; font-size:13px; font-weight:500; color:var(--chu);
             box-shadow:var(--bong-1); transition:background .12s, border-color .12s; }
  /* 🪶 02/09/2026 — nền rê chuột NHẠT ĐI, chữ SÁNG LÊN (gợi ý của cô Quỳnh sau khi
     soi Supabase: *"cái nền vuông đằng sau nổi lên nhưng bị rõ quá khiến nút nó bị
     cứng cáp"*). Supabase làm nền sáng lên chừng 4–6%, không phải một khối xám rõ.
     ⛔ Vẫn phải CÒN một dấu hiệu: bỏ hẳn nền thì người dùng bàn phím mất chỗ bám. */
  .nut-nho:hover { border-color:var(--vien); background:color-mix(in srgb, var(--nen2) 55%, transparent); color:var(--chu); }
  .nut-nho:focus-visible { outline:none; border-color:var(--xanh); box-shadow:var(--vong); }
  .ten-toi { font-size:13px; color:var(--mo); }

  .noi-dung { padding:20px 18px 40px; max-width:1500px; margin:0 auto; }

  /* 🪟 02/08/2026 — MÀN CÔNG CỤ / TRANG CHỦ ngồi trên MỘT TẤM NỀN KÍNH MỜ ĐẶC để
     luôn ĐỌC RÕ trên ảnh nền 4 mùa (cô Quỳnh: "background làm block trắng khó
     nhìn"). Chỉ bật ở màn công cụ/Home (thêm class body.man-cong-cu); sảnh danh
     sách lớp và khi vào lớp GIỮ NGUYÊN (nền đẹp, thẻ vốn đã rõ). */
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ 21/08/2026 — MỌI CÔNG CỤ DÙNG HẾT BỀ NGANG MÀN HÌNH
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"Từ bây giờ bất cứ công cụ nào khi ấn vào thì giao diện của công cụ
     đó phải chiếm toàn màn hình chứ ko phải chỉ ở giữa màn hình nữa gây lãng phí
     diện tích màn hình của tùy từng màn."*

     Trước hôm nay `max-width:1120px` — trên màn 27 inch (2560px) thì hơn một nửa
     màn hình là nền trống hai bên. Ba màn đã phải tự PHÁ khung ấy bằng luật riêng
     (`#ctsBang`, `#tksThan`, `#ltKhung` — xem khối bên dưới) vì bảng của chúng
     không nhét vừa. Nay bỏ trần ở gốc thì ba luật kia thành thừa nhưng vô hại, cứ
     để nguyên cho khỏi động vào chỗ đang chạy đúng.

     ⛔ VẪN CHỪA MÉP 14px hai bên: dán sát mép màn hình thì chữ đầu dòng chạm viền,
        đọc rất mệt, và cái bóng đổ của tấm nền mất chỗ đứng.
     ⛔ ĐÂY LÀ KHUNG NGOÀI, KHÔNG PHẢI GIẤY PHÉP KÉO CHỮ DÀI RA. Màn nào chỉ có một
        cột chữ (ví dụ trang hướng dẫn) thì tự đặt trần cho RUỘT của nó, đừng đặt
        lại ở đây — đặt ở đây là kéo lùi mọi bảng về khung cũ.
     ══════════════════════════════════════════════════════════════════════════════ */
  body.man-cong-cu .noi-dung {
    background:rgba(255,255,255,.93);
    -webkit-backdrop-filter:blur(7px); backdrop-filter:blur(7px);
    /* ⛔ 22/08/2026 — bóng cũ toả 34px là bóng của một tấm nổi bồng bềnh. Tấm này
       phủ gần hết màn hình nên nó KHÔNG nổi; bóng to chỉ làm mép trang bẩn đi. */
    /* 🔗 02/09/2026 — LỀ NGOÀI VỀ 0 để tấm này dán liền cột công cụ bên trái.
       Cô Quỳnh: "khoảng cách trắng bé ở giữa bảng và thanh, tôi muốn nó liên kết
       lại với nhau toàn bộ". Thủ phạm đúng là lề 14px này, cộng thêm bóng đổ.
       ⛔ Lời cảnh báo cũ ngay trên vẫn đúng và VẪN ĐƯỢC GIỮ: chữ không chạm viền,
          vì padding 16/20/30 bên trong không đổi. Thứ bỏ đi là lề NGOÀI.
       ⛔ GIỮ ĐỦ BỐN VIỀN. Bản đầu tôi gỡ viền phải + viền dưới cho "sạch"; mất 2px
          bề ngang là mấy nút công cụ trên điện thoại xếp vừa MỘT hàng, app hết cớ
          gom chúng lại, và bài thu-thanh-nut-cong-cu đỏ ngay mục ⑤ (390x844).
       ⛔ Bóng đổ bỏ hẳn: đã dán sát mà còn bóng thì chỗ giáp ranh hiện một vệt tối,
          nhìn vẫn ra hai mảnh rời — đúng thứ cô Quỳnh bảo sửa. */
    border:1px solid var(--vien-nhe); border-radius:var(--r-xl);
    /* ⭐ 18/09/2026 — LE NGANG 20px -> 8px. Boss: *"hiện đang có khoảng trắng
       ở giữa thanh công cụ của app và bảng sheet thì bạn đẩy kéo bảng sheet
       sang sát cái thanh công cụ nha cho nó vừa ko khít quá gây ngột và có
       nhiều vị trí trong bảng sheet hơn"*.
       Do that truoc khi sua: cot icon het o x=56, bang bat dau o x=78 — ho
       22px, dung bang padding 20px nay cong 2px vien.
       ⛔ De 8px chu khong ve 0: Boss dan ro *"cho nó vừa ko khít quá gây
          ngột"*. Dinh han vao thanh la doc met mat.
       ⛔ Le PHAI thu theo cho can (Boss chot) — hai ben bang nhau thi bang
          duoc them cho ca hai phia.
       ⚠️ Le TREN va DUOI giu nguyen 16/30: Boss chi noi ve be ngang. */
    max-width:none; margin:0; padding:16px 8px 30px;
    box-shadow:none;
  }
  /* 📱 08/09/2026 — ĐIỆN THOẠI: TẤM NÀY DÁN TRỌN BỀ NGANG MÀN HÌNH.
     Boss: *"nó cứ có 1 số cái chỗ tách rời nho nhỏ ở các khu khác nhau… bây giờ tôi
     muốn gom hết tất cả lại toàn bộ app trên điện thoại, giao diện bạn nhìn Facebook
     mà xem nó hoàn toàn liền vào nhau những cái màu trắng"*.

     Thủ phạm là `margin:8px` — nó vẽ một khung xám mảnh chạy quanh cả trang, nên
     mọi khối trắng bên trong đều trông như đang nổi trên một cái khay. Facebook
     không có khay ấy: các mảng trắng chạm thẳng hai mép màn.

     ⛔ VIỀN TRÁI/PHẢI cũng phải bỏ, không riêng lề. Còn một nét viền là còn thấy
        rìa của "tấm giấy", vẫn ra hai mảnh rời.
     ⛔ VIỀN DƯỚI thì GIỮ (border-bottom) — nó là vạch ngăn với thanh đáy.
     ⛔ Chỗ chừa cho thanh đáy (90px) GIỮ NGUYÊN. Bỏ là hàng nút cuối cùng của mọi
        màn chui xuống dưới thanh đáy, bấm không tới. */
  @media (max-width:820px) {
    body.man-cong-cu .noi-dung {
      margin:0; padding:12px 12px 90px; border-radius:0;
      border-left:0; border-right:0; border-top:0;
    }
    /* ⚠️ Luật bỏ padding của TRANG CHỦ trên điện thoại KHÔNG viết ở đây được — nó
       phải nằm SAU khối `body.man-cong-cu .noi-dung:has(.home-boc)` của máy tính
       (dòng ~373), vì hai luật cùng độ nặng nên luật viết sau mới thắng. Viết ở đây
       thì bị đè, và đè LẶNG LẼ: không lỗi, chỉ còn nguyên vệt xám 14px.
       Đã đo và dính đúng bẫy này lúc 08/09/2026 — xem luật thật ngay dưới khối ấy. */
  }
  /* 🛡 05/08 — LỖI TÌM ĐƯỢC khi người dùng tự đặt ẢNH NỀN: ở SẢNH DANH SÁCH LỚP các chữ
     phụ ("4 lớp", "Thứ 7", "Chủ nhật"…) nằm TRỰC TIẾP trên ảnh → ảnh sáng thì chói,
     ảnh tối thì chữ gần như biến mất. Cách chữa: có ảnh nền thì sảnh cũng ngồi trên
     TẤM NỀN ĐỤC như màn công cụ → chữ luôn rõ, bất kể ảnh sáng hay tối. */
  body.co-nen-mua:not(.man-cong-cu):not(.dang-trong-lop) .noi-dung {
    background:rgba(255,255,255,.93);
    -webkit-backdrop-filter:blur(7px); backdrop-filter:blur(7px);
    border:1px solid rgba(255,255,255,.7); border-radius:var(--r-xl);
    max-width:1120px; margin:0 auto; padding:16px 18px 30px;
    box-shadow:0 6px 20px rgba(20,50,70,.18);
  }
  body.toi.co-nen-mua:not(.man-cong-cu):not(.dang-trong-lop) .noi-dung {
    background:rgba(27,31,35,.96); border-color:var(--vien); }   /* 06/08: bỏ ám navy */
  @media (max-width:820px) {
    body.co-nen-mua:not(.man-cong-cu):not(.dang-trong-lop) .noi-dung {
      margin:8px; padding:12px 12px 90px; border-radius:var(--r-lg); } }
  /* 🖼 03/08 — TRANG CHỦ KHÔNG dùng tấm kính mờ chung: khi cột phải (thông báo) ngắn,
     tấm trắng kéo dài xuống thành "khung trắng thừa" trông xấu (cô Quỳnh). Nền trong
     suốt, MỖI khung con (hero · lớp đến giờ · công cụ · thông báo) tự có nền riêng
     nổi trên nền 4 mùa — sạch và tách bạch hơn. */
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ 21/08/2026 (lần 2) — ĐÃ BỎ NỐT TRẦN 1680px Ở ĐÂY
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"ở phần bên phải của trang còn hở nguyên một mảng trắng kìa sao bạn
     ko nhìn thấy"* — và cô nói đúng, tôi đã bỏ trần ở luật GỐC (`body.man-cong-cu
     .noi-dung`, xem khối "MỌI CÔNG CỤ DÙNG HẾT BỀ NGANG MÀN HÌNH" phía trên) nhưng
     bỏ SÓT hai luật `:has(...)` viết sau, mà chúng nặng ký hơn nên vẫn thắng.

     ĐO THẬT bằng trình duyệt trước khi sửa (21/08/2026):
         cửa sổ 1920px → nội dung rộng 1640, hở  14px  — không thấy
         cửa sổ 2560px → nội dung rộng 1680, hở 614px  — CHÍNH LÀ MẢNG TRẮNG ẤY
     Thanh trên cùng thì kéo hết bề ngang, nên hai mép không thẳng hàng và mắt bắt
     ngay ra chỗ hụt.

     ⛔ CÒN MỘT LUẬT NỮA cùng bệnh ở gần cuối file (`:has(.lt-fullw)` và
        `:has(.fss-cuon)`) — đã bỏ trần cùng lượt này. Ngày nào thêm một luật
        `.noi-dung:has(...)` mới thì ĐỪNG đặt `max-width` vào đó nữa.
     ⛔ VẪN GIỮ padding hai bên: dán sát mép màn là chữ chạm viền, đọc mệt.
     ══════════════════════════════════════════════════════════════════════════════ */
  body.man-cong-cu .noi-dung:has(.home-boc) {
    max-width:none; background:none; box-shadow:none; border:none;
    /* ⛔⛔ PADDING NGANG PHẢI LÀ 0 — ĐỪNG ĐẶT LẠI CON SỐ NÀO VÀO ĐÂY.
       Mép 14px đã do `body.man-cong-cu .noi-dung { margin:14px }` lo rồi. Đặt thêm
       padding ngang ở đây là cộng mép HAI LẦN: đo thật 22/08/2026 được thanh trên
       266→1586 còn dải chào 280→1572, lệch đúng 14px mỗi bên — chính là "khoảng
       trắng dư" cô Quỳnh chỉ trong ảnh.
       ⚠️ Màn công cụ có padding ngang mà KHÔNG lệch, vì ở đó nội dung ngồi trên một
          tấm nền trắng và mép mắt nhìn thấy là mép tấm nền. Trang chủ bỏ tấm nền ấy
          (`background:none` ngay trên), nên padding lộ ra thành khoảng trắng.
       ⛔ Padding TRÊN/DƯỚI thì giữ — không liên quan tới thẳng hàng hai bên. */
    -webkit-backdrop-filter:none; backdrop-filter:none; padding:14px 0 30px;
  }
  /* 📱 08/09/2026 — TRÊN ĐIỆN THOẠI, TRANG CHỦ KHÔNG CÒN PADDING TRÊN.
     Boss: *"ở trên cùng tách ra 1 chút so với cái thông báo ở dưới"*. Sau khi bỏ lề
     8px của thanh trên thì vẫn còn đúng 14px này — ĐO ĐƯỢC, không phải đoán:
     thanh trên đáy 57px, dải chào đỉnh 71px, khe 14px.

     ⛔ PHẢI VIẾT SAU khối ngay trên, không viết chung với các luật màn hẹp ở đầu
        file. Hai luật cùng độ nặng (0,3,1) nên luật viết SAU mới thắng — bản đầu
        tôi đặt ở trên và nó bị đè lặng lẽ, không lỗi, vệt xám vẫn nguyên.
     ⛔ KHÔNG đụng padding DƯỚI. Chỗ chừa cho thanh đáy do
        `body:not(.dang-trong-lop) #noiDung` trong css/lop.css lo (88px + vùng
        an toàn iPhone). Đặt số ở đây là ghi đè mất, hàng nút cuối chui xuống dưới
        thanh đáy. */
  @media (max-width:820px) {
    body.man-cong-cu .noi-dung:has(.home-boc) {
      padding-top:0; padding-left:0; padding-right:0;
    }
  }

  /* ⚡⚡ 06/08/2026 — MÀN CÓ BẢNG KIỂU SHEET THÌ TẮT KÍNH MỜ. ĐỪNG BẬT LẠI.
     Cô Quỳnh: "di chuột sang 2 bên ở các công cụ dạng sheet đều rất lag và khựng."

     Thủ phạm là `backdrop-filter: blur(7px)` ở `.noi-dung` (khai phía trên). Đây là
     một trong những hiệu ứng NẶNG NHẤT của trình duyệt: nó phải lấy toàn bộ những gì
     nằm SAU khung rồi làm mờ lại — và phải làm lại MỖI KHUNG HÌNH khi có gì nhúc nhích
     bên trong. Kéo bảng ngang = bắt máy làm mờ lại cả ảnh nền 60 lần/giây.
     Đo được: kéo bảng KHÔNG tốn công tính bố cục (0,001ms) — nên chỗ nghẽn nằm ở khâu
     VẼ LẠI, đúng chỗ này.

     Bỏ đi có mất đẹp không? Gần như không: lớp nền vốn đã ĐỤC 93%, chỉ 7% ảnh nền lọt
     qua nên cái mờ hầu như không ai thấy. Nâng lên 97% cho chữ chắc chắn rõ trên mọi
     ảnh nền, đổi lại kéo bảng mượt hẳn.

     Chỉ tắt ở màn CÓ bảng — các màn khác giữ nguyên kính mờ cho đẹp. */
  /* ⛔⛔ 15/08/2026 — BỔ SUNG `.cts-cuon` VÀ `.tks-cuon`, HAI MÀN BỊ SÓT.
     Sổ tuyển sinh và Thống kê tuyển sinh cũng là bảng kiểu Sheet, cũng kéo ngang, mà
     lại KHÔNG có trong danh sách này — nên suốt từ 06/08 hai màn đó vẫn chạy kính mờ
     khi cuộn, đúng thứ đã được chẩn ra là nguyên nhân gây khựng. Sổ tuyển sinh còn là
     bảng NẶNG NHẤT: hơn 40 cột, gần 4.700 dòng.
     ⛔ Danh sách liệt kê tay kiểu này là chỗ dễ sót. Thêm màn bảng mới thì nhớ thêm
        vào đây — bài kiểm thu-cts-an-cot.js có canh hai cái tên trên. */
  body.man-cong-cu .noi-dung:has(.dg-cuon),
  body.man-cong-cu .noi-dung:has(.lt-cuon),
  body.man-cong-cu .noi-dung:has(.fss-cuon),
  body.man-cong-cu .noi-dung:has(.tths-cuon),
  body.man-cong-cu .noi-dung:has(.cts-cuon),
  body.man-cong-cu .noi-dung:has(.tks-cuon),
  /* ⛔⛔ 09/09/2026 — THEM `.lt-khung`, MAN LICH TEST BI SOT.
     Chinh chu thich tren da canh "danh sach liet ke tay kieu nay la cho de sot" —
     va no sot that. Man Lich test dung `#ltKhung.lt-khung`, khong phai `.lt-cuon`,
     nen kinh mo van bat.
     Hau qua do duoc o man 320x568: `#ltFab` (nut "+" them lich test) khai
     `position:fixed; bottom:70px` nhung **khong he fixed** — `backdrop-filter` tao
     mot khung chua moi cho moi con `position:fixed`, nen nut neo vao day `#noi-dung`
     va cuon theo noi dung. No roi xuong 535->591 trong man cao 568: **de len nut
     "Viec cua toi" cua thanh day 56x51px, va loi 23px khoi day man**.
     ⛔ Cho nay mo bang `offsetParent`: fixed that thi `offsetParent` phai la `null`.
        Do duoc `#noiDung` la biet ngay khung chua da bi doi. */
  body.man-cong-cu .noi-dung:has(.lt-khung),
  /* ⛔⛔ 12/09/2026 — THÊM `.mtb-cuon`, MÀN QUẢN LÝ TÀI KHOẢN BỊ SÓT.
     LẦN SÓT THỨ TƯ của đúng danh sách này. Đo được (người phá, 1366 và 1001):
     bấm ⋯ ở hàng cuối (nút ở y=693) thì menu ghi `top: 499.109px` mà VẼ RA ở
     `rect_top = 9` — lệch đúng `scrollY = 539`, tức 490px. Vì `backdrop-filter`
     biến `#noiDung` thành khung chứa mới, menu neo vào nó chứ không vào màn hình.
     ⇒ Nay có thêm đường CHUNG `.nd-co-cuon` ngay dưới; danh sách tay này giữ lại
       làm lớp đỡ cho lúc JS chưa kịp chạy. */
  body.man-cong-cu .noi-dung:has(.mtb-cuon),
  body.man-cong-cu .noi-dung.nd-co-cuon,
  body.man-cong-cu .noi-dung:has(.khung-cuon) {
    -webkit-backdrop-filter:none; backdrop-filter:none;
    /* ⚡ ĐỤC HẲN (không phải rgba nữa). Còn trong suốt một chút là trình duyệt vẫn
       phải trộn lại với ảnh nền cố định mỗi khung hình khi cuộn — xem `.dg-cuon`. */
    background:var(--the);
  }
  /* ⛔ ĐỪNG thêm luật riêng cho nền tối ở đây nữa: `var(--the)` đã tự đổi màu theo
     sáng/tối rồi. Khai lại bằng `rgba(...)` là vô tình cho trong suốt trở lại —
     đúng thứ vừa gây lag. */

  /* ============ 🏠 TRANG CHỦ (SẢNH HOME) ============ */
  .home-boc { display:flex; flex-direction:column; gap:18px; }
  /* 🧱 CỘT PHẢI (Thông báo nhắc việc → Ghi chú của tôi). `gap:inherit` để tự ăn theo
     khoảng cách của `.home-boc` ở mọi cỡ màn (18px · 13px điện thoại · 9px chế độ gọn). */
  .home-cot-phai, .home-cot-trai { display:flex; flex-direction:column; gap:inherit; min-width:0; }
  /* ============ 🏛 THANH TÊN (HERO) — bản doanh nghiệp, 06/08/2026 ============
     Cô Quỳnh: "thiết kế lại phần thanh tên cho nó nghiêm túc và business hơn, thật
     đẹp và chuyên nghiệp."
     Bản cũ: dải màu teal→CAM tự trôi qua lại + hai quầng sáng bồng bềnh. Vui mắt
     nhưng giống app giải trí, và animation chạy vô tận cũng tốn máy.
     Bản mới, theo lối bảng điều khiển doanh nghiệp:
       · Nền XANH SÂU một tông (không cam, không nhấp nháy) — chững chạc, chữ trắng nổi rõ.
       · Một vệt sáng chéo TĨNH thay cho hai quầng nhún nhảy: vẫn có chiều sâu, không động đậy.
       · Vạch teal mảnh mép trái làm dấu nhận diện thương hiệu.
       · Bố cục ba khối rõ ràng: ảnh · tên+chức vụ · ngày giờ, ngăn bằng đường kẻ mảnh.
       · Ảnh đại diện bo góc vuông-mềm (squircle) thay vì tròn — đúng gu app quản trị.
     ⛔ Đừng thêm animation vào đây nữa. */
  /* 🎨 Dải chào: thẻ trắng, nhưng có vạch teal mép trái và ảnh đại diện teal đặc.
     ⛔ Đây là chỗ ĐÃ SAI HAI LẦN theo hai hướng ngược nhau, ghi lại cả hai:
        · Bản 06/08 — cả khối là mảng teal chuyển sắc → cô chê lộ UI của AI.
        · Bản 22/08 lần đầu — trắng trơn không còn màu nào → cô chê trắng quá nhiều.
        Bản này ở giữa: nền trắng, màu nằm ở vạch mép và ảnh đại diện. */
  /* 🔵 MIỄN VUÔNG HOÁ — chỗ thứ ba, cô Quỳnh chỉ đích danh 02/09/2026:
     *"cái thanh tên chào buổi sáng có ngày ở trang chủ để lại dạng tròn bo góc"*.
     ⛔ Gõ thẳng 12px, KHÔNG lấy var(--r-xl): nấc ấy nay là 0 cho khung chứa, mà
        dải này không chứa gì — nó là một tấm màu đứng riêng. Cùng lối với
        `.the-lop` (9px) và `.pt-*` (12px), hai chỗ miễn đã có từ trước. */
  .home-hero { display:flex; align-items:center; gap:16px; padding:18px 20px;
    border-radius:12px; color:#fff;
    /* NĂM lớp, lớp khai TRƯỚC nằm TRÊN. Xem khối lý do ngay phía trên — mỗi lớp
       một việc, đừng gộp lại.
       ⛔ Hai lớp tối đo bằng PIXEL chứ không phải phần trăm: chữ có bề rộng cố định
          (~240px cụm trái, ~150px khối ngày), không co theo màn hình. Dùng % thì
          màn 2560px sẽ tối tới tận giữa dải — đúng cái bệnh của bản cũ. */
    background-image:
      linear-gradient(90deg,  rgba(10,14,20,.46) 0px, rgba(10,14,20,.30) 240px, rgba(10,14,20,0) 470px),
      linear-gradient(270deg, rgba(10,14,20,.34) 0px, rgba(10,14,20,.22) 180px, rgba(10,14,20,0) 380px),
      radial-gradient(130% 210% at 50% -75%, rgba(255,255,255,.30) 0%, rgba(255,255,255,.08) 42%, rgba(255,255,255,0) 68%),
      linear-gradient(180deg, rgba(0,0,0,0) 50%, rgba(0,0,0,.20) 100%),
      var(--hero-mau, linear-gradient(112deg, var(--xanh-dam) 0%, var(--xanh) 55%, var(--xanh-sang) 100%));
    background-size:cover;
    /* ⛔ Viền là màu TRẮNG MỜ, không phải `--vien`: viền xám trên nền màu đậm trông
       như một đường bẩn. Trắng mờ thì hoà vào bất cứ màu nào. */
    border:1px solid rgba(255,255,255,.18);
    /* `inset 0 1px 0` = một sợi sáng chạy dọc mép TRÊN. Thứ nhỏ xíu này là cái làm
       một khối màu trông như VẬT THỂ bắt sáng thay vì một hình chữ nhật tô màu. */
    box-shadow:var(--bong-2), inset 0 1px 0 rgba(255,255,255,.24);
    position:relative; overflow:hidden; }
  /* ══════════════════════════════════════════════════════════════════════════
     ✨ VỆT SÁNG QUÉT NGANG — MỘT LẦN, LÚC MỞ TRANG CHỦ (cô Quỳnh 22/08/2026)
     ──────────────────────────────────────────────────────────────────────────
     ⛔⛔ CÓ MỘT LUẬT CŨ Ở NGAY TRÊN NÓI "ĐỪNG THÊM ANIMATION VÀO ĐÂY NỮA".
        Luật ấy viết 06/08/2026 và nó ĐÚNG với thứ nó cấm: bản hồi đó có dải màu
        TỰ TRÔI QUA LẠI VÔ TẬN + hai quầng sáng bồng bềnh — vui mắt kiểu app giải
        trí, và chạy mãi thì tốn máy.
        Vệt này KHÁC HẲN ở chỗ: chạy ĐÚNG MỘT LẦN rồi thôi (`1 both`), tổng cộng
        1,5 giây. Nó là cái nháy sáng lúc trang vừa hiện ra, không phải một thứ
        nhấp nháy suốt buổi làm việc.
        Cô Quỳnh 22/08/2026 xin thẳng: *"làm quả hiệu ứng màu thật đẹp lộng lẫy và
        chuyên nghiệp"* — nên luật cũ được nới đúng phạm vi này, không nới thêm.
     ⛔ TUYỆT ĐỐI KHÔNG đổi `1` thành `infinite`. Một dải sáng quét qua lại suốt
        ngày ngay đầu Trang chủ là thứ khiến người ta không tập trung nổi vào việc.
     ⛔ Và phải tôn trọng `prefers-reduced-motion` — có người chóng mặt với hiệu
        ứng chuyển động, đó là cài đặt của hệ điều hành, không phải sở thích. */
  .home-hero::after {
    content:""; position:absolute; top:0; bottom:0; left:-45%; width:38%;
    pointer-events:none;
    background:linear-gradient(100deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.16) 45%, rgba(255,255,255,0) 100%);
    transform:skewX(-14deg);
    animation:heroLuot 1.5s cubic-bezier(.4,0,.2,1) .35s 1 both; }
  @keyframes heroLuot { from { left:-45%; } to { left:125%; } }
  @media (prefers-reduced-motion: reduce) {
    .home-hero::after { animation:none; opacity:0; } }
  /* ══════════════════════════════════════════════════════════════════════════
     🎨 MÀU CÁ NHÂN CỦA TỪNG NGƯỜI — cô Quỳnh báo lỗi 22/08/2026
     ──────────────────────────────────────────────────────────────────────────
     Mỗi người chọn được một màu cho thẻ chào của mình (bảng `HERO_MAU`, 7 màu).
     ⛔⛔ MÀU ẤY KHÔNG ĐƯỢC TÔ KÍN CẢ THẺ. Cả 7 màu đều NHẠT DẦN VỀ BÊN PHẢI, mà
        khối ngày tháng lại nằm đúng bên phải — chữ nào đặt ở đó cũng chìm, dù
        chọn chữ trắng hay chữ đen. Cô Quỳnh đã báo đúng chuyện này.
     Nay màu ấy làm DẤU NHẬN DIỆN: dải dày mép trái + ảnh đại diện. Thẻ vẫn trắng
     nên mọi chữ đọc rõ, mà nhìn từ xa vẫn biết là màu của ai. */
  /* ⛔ Dải màu mép trái đã BỎ (22/08/2026, cô Quỳnh: *"phủ có tí tẹo thế thì phủ
     làm cái gì nữa"*). Màu nay phủ kín cả thanh qua biến `--hero-mau` ở luật
     `.home-hero` bên trên — lớp `co-mau` giữ lại chỉ để CSS còn phân biệt được
     người đã chọn màu với người dùng màu mặc định, phòng khi sau này cần. */
  .home-hero.co-mau { }
  /* Ô chữ tắt: kính mờ trắng trên nền màu — hợp với mọi màu người dùng chọn, khỏi
     phải tính riêng cho từng màu. */
  /* ⛔ Đây là ô ảnh đại diện DUY NHẤT không dùng xám: nền dưới nó là màu người
     dùng chọn, nên hình người phải TRẮNG. `color:#fff` lo việc đó qua
     `fill:currentColor` của `.av-nguoi`. */
  /* 🟢 02/09/2026 — BO 12px, THÔI DÙNG `--r-lg`. Cô Quỳnh: *"mấy cái ô trong đó
     sửa lại thành viền tròn đi chứ để viền vuông xấu quá"*. `--r-lg` là token của
     KHUNG CHỨA (đang để 0 cho bảng biểu vuông kiểu Google Sheets) — ô trang trí
     này dùng nhầm vai nên vuông trong lòng dải bo 12px. Ghi số thẳng, bằng đúng
     bán kính của `.home-hero` bọc ngoài. ⛔ ĐỪNG chữa bằng cách đổi `--r-lg`. */
  .home-hero-av { flex:none; width:52px; height:52px; border-radius:12px;
    display:flex; align-items:center; justify-content:center;
    color:#fff; background:rgba(255,255,255,.18);
    border:1px solid rgba(255,255,255,.4); cursor:pointer; padding:0; overflow:hidden;
    transition:border-color .15s, background .15s; }
  .home-hero-av img { width:100%; height:100%; object-fit:cover; display:block; }
  .home-hero-av:hover { background:rgba(255,255,255,.3); border-color:rgba(255,255,255,.75); }
  .home-hero-chao { min-width:0; }
  /* ⛔ Lời chào: chữ THƯỜNG, không giãn ký tự. Xem khối lý do ở trên.
     ⛔ VÀ DÙNG `--chu`, KHÔNG DÙNG `--mo`. Cô Quỳnh 22/08/2026: *"chữ chào buổi
        sáng và 1 số chữ cứ bị mờ ý"*. Đây là dòng chữ đầu tiên người ta nhìn thấy
        mỗi sáng khi mở app — nó phải đọc được ngay, không phải nheo mắt.
        Thứ bậc đã có sẵn nhờ CỠ CHỮ (12,5px cạnh tên 22px), không cần bôi mờ thêm.
        ⛔ Đây là lời phàn nàn LẶP LẠI của cô Quỳnh về chữ mờ (đã có ba lần ở nền
           tối). Đừng hạ về `--mo` lần nữa cho "nhẹ nhàng". */
  /* ⛔⛔ TRẮNG ĐẶC, KHÔNG `.86`, KHÔNG `.6`, KHÔNG `opacity`. Cô Quỳnh đã chê chữ
     mờ BỐN lần, hai lần trong đó là chính dòng "Chào buổi sáng" này.
     Thứ bậc giữa dòng chào và cái tên đã có sẵn: 12,5px nét 400 đứng cạnh 22px nét
     600. Bôi mờ thêm không làm rõ thứ bậc hơn, chỉ làm khó đọc hơn. */
  .home-hero-chao .loi { font-size:12.5px; font-weight:400; color:#fff; }
  .home-hero-chao h2 { margin:2px 0 7px; font-size:22px; font-weight:600; line-height:1.15;
    letter-spacing:-.02em; color:#fff;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* Chức vụ: một viên chip xám nhạt, chữ thường — kiểu `Badge variant="secondary"`. */
  .home-hero-chao .home-vt { font-size:11.5px; font-weight:500; color:#fff;
    background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.38);
    /* 🟢 02/09/2026 — viên thuốc thay cho 4px. Chip cao 21px thì 4px gần như
       vẫn là góc vuông; bo hẳn mới ra đúng hình "viên chức vụ". */
    border-radius:999px; padding:2px 9px; display:inline-block; }
  /* ⛔ Đường kẻ mép trái đã THAY bằng một TẤM KÍNH bao cả khối. Lý do không phải
     thẩm mỹ: khối này nằm ở chỗ màu NHẠT NHẤT của mọi gradient, mà chữ trong nó
     lại là chữ NHỎ NHẤT của dải (12px). Tấm kính .35 cộng với lớp tối ② (.34)
     thành 57% — đủ cho chữ trắng đạt 5,5 lần trên màu nhạt nhất bảng (#B7EFC9).
     ⛔ Đừng hạ .35 xuống cho "nhẹ nhàng": bài kiểm tự tính lại và sẽ đỏ. */
  .home-hero-ngay { margin-left:auto; flex:none; text-align:right; line-height:1.3;
    padding:8px 14px; background:rgba(10,14,20,.35);
    /* 🟢 02/09/2026 — 12px cho khớp ô ảnh đại diện và dải bọc ngoài.
       ⛔ CHỈ đổi bo góc. Nền `rgba(10,14,20,.35)` GIỮ NGUYÊN — `thu-giao-dien-
          nen-tang.js` đọc đúng con số ấy để tính chữ trắng có đủ tương phản. */
    border:1px solid rgba(255,255,255,.2); border-radius:12px; }
  /* ⛔ Cũng TRẮNG ĐẶC — cùng lý do với dòng lời chào ngay trên, và ở đây còn gắt
     hơn: đây là chữ NHỎ NHẤT (12px) nằm ở chỗ màu NHẠT NHẤT. Nó là phép thử khắt
     khe nhất của cả dải chào — đọc được ở đây thì đọc được ở mọi chỗ. */
  .home-hero-ngay .thu { font-size:12px; font-weight:400; color:#fff; }
  /* `tabular-nums`: các chữ số rộng bằng nhau nên ngày không nhảy ngang mỗi lần đổi
     — thứ nhỏ nhưng là nếp chung của mọi bảng điều khiển làm tử tế. */
  .home-hero-ngay .ns { font-size:18px; font-weight:600; margin-top:2px; letter-spacing:-.01em;
    color:#fff; font-variant-numeric:tabular-nums;
    display:flex; align-items:center; justify-content:flex-end; gap:8px; }
  /* ⛔ Icon 17px cho chữ 19px — nhỏ hơn chữ một nấc là đúng vai PHỤ HOẠ. Bằng hoặc
     to hơn chữ thì nó tranh chỗ với con số, thành "quá lố" như cô Quỳnh dặn tránh.
     `opacity:.8` để nó lùi thêm một bước nữa sau con số. */
  .home-hero-ngay .ns .ic-lich { width:16px; height:16px; flex:none; color:rgba(255,255,255,.85); }

  /* ═══ 📝 NÚT GẬP/MỞ GHI CHÚ TRÊN DẢI CHÀO — Boss 08/09/2026 ═══════════════════
     *"ở bên phải cái thanh chào buổi sáng đang trống trơn, tôi muốn bạn thêm 1 cái
      nút kí hiệu phù hợp để ấn vào là nó kéo mở cái note ra"*.
     ⛔ MÁY TÍNH ẨN HẲN. Bên ấy ghi chú nằm sẵn ở cột phải, lúc nào cũng thấy — thêm
        nút gập vào là bày ra một thứ không giải quyết vấn đề gì.
        Luật hiện nó nằm trong khối `@media (max-width:820px)` phía dưới. */
  .home-hero-note { display:none; }
  /* Chữ CHỈ dành cho trình đọc màn hình của người khiếm thị: mắt không thấy, nhưng
     máy đọc vẫn đọc ra. ⛔ ĐỪNG thay bằng `display:none` — như thế là máy đọc cũng
     bỏ qua, và nút thành một hình vẽ không tên. */
  .chu-doc { position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0; }

  /* ═══ 🟢 DẢI "ĐANG ONLINE" (cô Quỳnh 19/08/2026) ═══════════════════════════
     Nằm GIỮA thanh avatar và Tin hôm nay. Hình tròn CỐ Ý BÉ (26px) — cô Quỳnh:
     *"bé thôi kẻo gây vướng và mất tập trung nhất là trên điện thoại màn hình bé"*.
     Khối rỗng thì không có class `home-online` nên KHÔNG chiếm dòng nào. */
  /* ⛔ Rỗng thì GIẤU HẲN: ô lưới rỗng vẫn ăn một khoảng `gap` nên trang chủ hở
     ra một vệt trắng khó hiểu. Chọn bằng ID để thắng `.home-online` ở cả hai trạng
     thái (lúc chưa hỏi máy chủ, và lúc hỏi xong mà không có ai). */
  #homeOnline:empty { display:none !important; }
  /* ⛔ 10/09/2026 — `overflow` ĐỔI TỪ `hidden` SANG `visible`, và thêm
     `position:relative`. Cả hai đều cần cho ô chữ hiện tên (Boss giao kèm mẫu
     React): `relative` làm mốc đo, còn `hidden` thì cắt cụt ô chữ ở mép trên.
     Bỏ `hidden` KHÔNG làm dải tràn ngang, vì `.ol-khung` bên trong vẫn
     `overflow-x:auto` — nó mới là chỗ chặn chiều ngang. */
  .home-online { position:relative; display:flex; align-items:center; gap:10px;
    margin:10px 0 0;
    padding:7px 12px; background:var(--the); border:1px solid var(--vien);
    border-radius:var(--r-lg); box-shadow:var(--bong-1); overflow:visible; }
  .ol-nhan { flex:none; display:flex; align-items:center; gap:6px; font-size:12px;
    font-weight:500; color:var(--mo); white-space:nowrap; }
  .ol-nhan em { font-style:normal; font-weight:600; color:var(--chu); }
  .ol-cham { width:7px; height:7px; border-radius:50%; background:#2E7D32; flex:none; }
  /* ⛔ ĐỨNG YÊN, KHÔNG CHẠY BĂNG CHUYỀN — cô Quỳnh chốt 20/08/2026:
     *"đổi lại thành ko tự đi theo băng chuyền sang trái nữa mà ở nguyên đi, nếu di
     chuột vào kéo sang 2 bên được thôi"*.
     Trước đây đông trên 7 người là dải tự trượt sang trái vô hạn. Bỏ hẳn: chuyển động
     vô hạn ở trang chủ hút mắt và gây mất tập trung, mà người ta lại KHÔNG đọc kịp tên
     ai đang online — muốn xem thì phải rê chuột vào cho nó dừng, tức là bắt người dùng
     đuổi theo cái đang chạy.
     Nay đứng yên, ai muốn xem tiếp thì KÉO. Ba lối kéo đều dùng được:
       · giữ chuột rê ngang        → mã ở `batKeoNgang`
       · vuốt ngón tay trên điện thoại → `overflow-x:auto` lo sẵn
       · lăn chuột                 → `batKeoNgang` đổi lăn dọc thành cuộn ngang
     Vì đứng yên nên KHÔNG cần in danh sách hai lần nữa, và cũng không còn cần luật
     `prefers-reduced-motion` — không có chuyển động nào để mà tắt. */
  .ol-khung { flex:1; min-width:0; overflow-x:auto; overflow-y:hidden;
    cursor:grab; scrollbar-width:none; -ms-overflow-style:none;
    overscroll-behavior-x:contain;
    /* `pan-x`: vuốt ngang thì cuộn dải, vuốt dọc thì vẫn cuộn được cả trang. */
    touch-action:pan-x;
    /* ⛔ CHỪA CHỖ CHO AVATAR NHÔ LÊN (10/09/2026). Rê chuột vào thì ô nhích lên 5px
       và phóng to 1,16 lần; không có khoảng đệm này thì phần nhô ra bị mép khung
       CẮT PHẲNG, trông như avatar bị xén mất đỉnh đầu.
       Đệm 8px trên / 4px dưới, rồi kéo lại đúng bấy nhiêu bằng lề âm — nên dải
       KHÔNG cao thêm một điểm ảnh nào. Cố ý giữ nhỏ: vùng đệm vẫn ăn cú bấm, đệm
       to là nó phủ lên thanh avatar ngay phía trên và làm nút ở đó chết câm (bẫy
       đã ghi ở `batKeoNgang`). Ô chữ tên thì to hơn nhiều nên phải nằm NGOÀI
       khung này — xem `.ol-bong`. */
    padding:8px 0 4px; margin:-8px 0 -4px; }
  /* Giấu thanh cuộn: dải chỉ cao 26px, thanh cuộn chiếm gần hết chiều cao và trông
     rất bẩn. Vẫn kéo/vuốt/lăn được bình thường — chỉ ẩn cái vạch đi. */
  .ol-khung::-webkit-scrollbar { display:none; }
  .ol-khung.dang-keo { cursor:grabbing; }
  /* Lúc đang kéo phải cấm chọn chữ và cấm lôi ảnh đi: không có hai dòng này thì rê
     chuột sẽ bôi đen tên người, hoặc kéo cái avatar chạy theo con trỏ. */
  .ol-khung.dang-keo, .ol-khung.dang-keo * { user-select:none; }
  .ol-khung img { -webkit-user-drag:none; user-select:none; }
  .ol-track { display:flex; width:max-content; }
  /* ⛔ 10/09/2026 — AVATAR CHỒNG LÊN NHAU, không còn xếp rời. Boss đưa mẫu và
     bảo làm theo. Chồng nhau vừa gọn hơn (7 người cũ chiếm 231px, nay 145px) vừa
     đọc ra ngay là "một nhóm người", chứ dải rời trông như bảy nút bấm.
     Lề âm phải đặt ở `.ol-tron` chứ đừng dùng `gap` âm — `gap` không nhận số âm. */
  .ol-lo { display:flex; padding-right:7px; }
  .ol-tron { position:relative; flex:none; width:26px; height:26px; border-radius:50%;
    overflow:visible; margin-left:-9px; cursor:default;
    /* Đường cong này là bản dịch của `spring` trong mẫu Boss đưa: vọt lên nhanh
       rồi lắc nhẹ về chỗ, chứ không trượt đều đều như `ease`. */
    transition:transform .28s cubic-bezier(.34,1.56,.64,1); }
  .ol-tron:first-child { margin-left:0; }
  /* ⛔ Thứ tự đè do JS gán (`z-index` giảm dần ở `veHomeOnline`) để người ĐỨNG
     TRƯỚC nằm trên — giống mẫu. Ô đang mở phải vượt lên hết, nếu không thì người
     bên phải che mất nửa mặt nó lúc phóng to. */
  .ol-tron.mo { z-index:60 !important; }
  .ol-tron img, .ol-tron i { display:block; width:26px; height:26px; border-radius:50%;
    object-fit:cover;
    /* Viền dày lên 2px và LẤY MÀU THẺ (không phải màu ô nhập): avatar chồng nhau
       thì cái viền chính là thứ tách mặt người này khỏi mặt người kia. Mẫu Boss
       dùng `border-4 border-background` cũng đúng ý ấy, chỉ là ở cỡ 40px. */
    border:2px solid var(--the); box-shadow:0 0 0 1px var(--vien); }
  /* ⛔ Trước 22/08/2026 ô này là chữ tắt trên nền màu sinh theo tên. Nay là hình
     người xám như mọi chỗ khác — xem `AV_NGUOI`. Tên người vẫn hiện khi rê chuột
     (thuộc tính `title` ở `veHomeOnline`), nên không mất thông tin nào. */
  .ol-tron i { font-style:normal; background:var(--nen2); color:var(--mo);
    display:flex; align-items:center; justify-content:center; }
  /* Chấm xanh góc dưới phải — dấu "đang online" quen mắt, không cần chú thích. */
  .ol-tron .ol-cham { position:absolute; right:-1px; bottom:-1px; width:8px; height:8px;
    border:1.5px solid var(--the); }

  /* ═══ RÊ CHUỘT / CHẠM VÀO MỘT NGƯỜI ═══════════════════════════════════════
     ⛔ `@media (hover:hover)` KHÔNG PHẢI THỪA. Thiếu nó thì trên điện thoại,
        cú chạm đầu tiên bị trình duyệt dịch thành "rê chuột giả" và avatar kẹt ở
        trạng thái phóng to cho tới khi chạm chỗ khác — người dùng tưởng app treo.
        Điện thoại đi lối class `.mo` do cú chạm gắn vào (xem `noiOChuOnline`). */
  @media (hover:hover) {
    .ol-tron:hover { transform:translateY(-5px) scale(1.16); z-index:60; }
  }
  .ol-tron.mo, .ol-tron:focus-visible { transform:translateY(-5px) scale(1.16); }
  .ol-tron:focus-visible { outline:2px solid var(--xanh); outline-offset:2px; }
  /* Người dùng đã xin tắt hiệu ứng chuyển động thì bỏ hẳn phần nhún nhảy — tên vẫn
     hiện đủ, chỉ là hiện thẳng. */
  @media (prefers-reduced-motion: reduce) {
    .ol-tron { transition:none; }
    .ol-tron:hover, .ol-tron.mo, .ol-tron:focus-visible { transform:none; }
  }

  /* ═══ Ô CHỮ HIỆN TÊN ═══════════════════════════════════════════════════════
     Nằm NGOÀI `.ol-khung` (lý do dài ở `veHomeOnline`), neo vào `.home-online`.
     JS chỉ đặt `left`; mọi thứ còn lại ở đây. */
  .ol-bong { position:absolute; left:0; bottom:calc(100% - 2px); z-index:80;
    transform:translateX(-50%) translateY(6px) scale(.72); transform-origin:50% 100%;
    opacity:0; pointer-events:none;
    /* ⛔ 22/09/2026 — Ô CHỮ KHÔNG BAO GIỜ RỘNG HƠN THẺ. Cục "+N" kể 5 tên rồi "và 38 người
       khác" (Boss chốt "và N … khác"); đo trên điện thoại 390px: ô chữ rộng 439px, lòi 55px
       ra mép phải, cắt mất đúng chữ "người khác". Rộng vừa chữ (`max-content`) nhưng trần là
       bề ngang thẻ — chạm trần thì dòng tên tự xuống dòng. `noiOChuOnline` đo `offsetWidth`
       sau khi đã có trần, nên phép kẹp hai mép thẻ của nó đúng trở lại. */
    white-space:normal; width:max-content; max-width:calc(100% - 8px);
    padding:4px 9px; border-radius:8px;
    background:var(--chu); color:var(--the);
    font-size:11.5px; line-height:1.35; text-align:center;
    box-shadow:0 6px 18px rgba(0,0,0,.22);
    transition:opacity .18s ease, transform .28s cubic-bezier(.34,1.56,.64,1); }
  .ol-bong.hien { opacity:1; transform:translateX(-50%) translateY(0) scale(1); }
  .ol-bong b { display:block; font-weight:600; }
  /* Vai trò là dòng phụ — mờ hơn, nhỏ hơn, để cái tên vẫn là thứ đọc trước. */
  .ol-bong span { display:block; opacity:.72; font-size:10.5px; }
  /* Mũi nhọn chỉ xuống đúng cái avatar đang mở. */
  .ol-bong::after { content:""; position:absolute; top:100%; left:50%;
    margin-left:-4px; border:4px solid transparent; border-top-color:var(--chu); }
  @media (prefers-reduced-motion: reduce) {
    .ol-bong { transition:none; transform:translateX(-50%); }
    .ol-bong.hien { transform:translateX(-50%); }
  }
  @media (max-width:520px) {
    .home-online { gap:7px; padding:6px 9px; }
    .ol-nhan em { display:none; }        /* màn bé: bỏ con số cho gọn */
    .ol-tron, .ol-tron img, .ol-tron i { width:22px; height:22px; }
    /* Giữ đúng tỉ lệ chồng của cỡ lớn (9/26) — để nguyên -9px trên avatar 22px thì
       chúng lấn nhau quá sâu, chỉ còn thấy một vệt viền. */
    .ol-tron { margin-left:-7px; }
    .ol-tron:first-child { margin-left:0; }
  }
  @media (max-width:820px) {
    .home-hero { padding:15px 16px; gap:13px; border-radius:12px; }
    .home-hero-chao h2 { font-size:20px; }
    .home-hero-ngay { padding-left:13px; }
    .home-hero-ngay .ns { font-size:15px; }
  }
  @media (max-width:560px) { .home-hero-ngay { display:none; } }
  /* 📝 Quyển note cá nhân — GIẤY VÀNG có DÒNG KẺ (cô Quỳnh 03/08: "như note người
     đời, màu vàng, có đường kẻ"). Bôi đậm · tô vàng · gắn link · tự dãn ra khi viết nhiều. */
  /* 🏛 06/08/2026 — Ô GHI CHÚ bản doanh nghiệp (cô Quỳnh: "thiết kế cái note chuyên
     nghiệp hơn"). Bản cũ là GIẤY VÀNG có DÒNG KẺ kiểu vở học trò: nền #FFFCEC, dòng
     kẻ ngang, nút vàng, chữ nâu. Trông thân thiện nhưng lạc lõng giữa app quản trị.
     Nay: mặt phẳng trung tính như mọi khung khác, bỏ dòng kẻ, nút công cụ mảnh và
     kín đáo, chỉ nổi lên khi rê chuột. Màu vàng CHỈ còn giữ ở tính năng tô sáng chữ
     — đúng chỗ nó có nghĩa. Tự đổi theo nền sáng/tối vì dùng biến màu chung. */

  /* ═══════════ 🎯 SỔ TUYỂN SINH (CTS) — 13/08/2026 ═══════════
     Cô Quỳnh: *"phải show được full thông tin cả file chứ không phải kiểu thiết kế
     của app cũ"* — nên bảng hiện ĐỦ 4.646 dòng × 40 cột, không cắt bớt dữ liệu.
     Cắt phần VẼ, không cắt DỮ LIỆU: xem chú thích ⛔ ở hàm ctsVeBang.
     ⛔ Bảng dùng `table-layout:fixed` và ô cao CỐ ĐỊNH — cuộn ảo tính vị trí bằng
        phép nhân số dòng × chiều cao, ô co giãn là tính sai, cuộn tới đâu lệch tới đó. */
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ BẢNG LÀ CHÍNH — MỌI THỨ TRÊN NÓ PHẢI NHỎ LẠI (cô Quỳnh 16/08/2026)
     ──────────────────────────────────────────────────────────────────────────────
     Nguyên văn: *"cái thứ quan trọng nhất là chỗ bảng nhập điền thông tin thì bạn
     lại để rõ bé mà cái ô báo cáo bên trên thì to lòi… bảng điền thông tin tuyển
     sinh luôn phải to nhất rõ ràng nhất chiếm trang nhất để dễ dùng"*.

     Khung bảng VỐN ĐÃ tự co cho vừa đáy cửa sổ (xem `ctsCanhCaoKhung`). Nên bảng
     bé không phải vì bảng, mà vì **phần đầu trang ăn mất chỗ**: đo trên màn của cô
     hôm nay, bốn khối phía trên (tiêu đề + nút · dải số hôm nay · ô tìm · hàng lọc)
     chiếm 268px, còn bảng chỉ được 16 dòng.

     BA VIỆC LÀM Ở ĐÂY, không đụng gì tới bảng:
       1. Dải số hôm nay: xếp số và nhãn NẰM CÙNG MỘT DÒNG thay vì chồng lên nhau
          → mỗi ô từ hai dòng còn một dòng, tiết kiệm ~26px.
       2. Chữ và lề nhỏ lại một nấc ở mọi khối phía trên.
       3. Màn hình THẤP (≤900px) thì thu thêm một nấc nữa — máy tính xách tay 13"
          và màn 768px mới là chỗ ngột nhất, chứ màn to vốn đã thoải mái.
     ⛔ Không đụng `.cts-bang` / `.cts-cuon`: cỡ chữ trong bảng là thứ cô đọc suốt
        ngày, thu nó lại là phản tác dụng.
     ══════════════════════════════════════════════════════════════════════════════ */
  .cts-dau { display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-bottom:7px; }
  /* Khối bọc tên sổ + nhãn. Trên MÁY TÍNH `display:contents` nghĩa là trình duyệt bỏ
     qua chính nó, hai con nằm thẳng trong flex y như trước khi có khối này — máy tính
     không đổi gì. Màn nhỏ mới cho nó thành một hàng riêng (xem @media cuối file). */
  .cts-dau .cts-ten, .cts-dau .cts-nut { display:contents; }
  .cts-dau h2 { margin:0; font-size:17px; font-weight:700; letter-spacing:-.01em; }
  .cts-thu { font-size:11px; font-weight:700; padding:3px 9px;
             border-radius:var(--r-sm); background:#FDF0D5; color:#7A5600; border:1px solid #E8C97A; }
  body.toi .cts-thu { background:#3A3016; color:#E8C77A; border-color:#5C4A1E; }
  .cts-loc { display:flex; gap:7px; flex-wrap:wrap; align-items:center; margin-bottom:7px; }
  .cts-loc select, .cts-loc input { font-family:inherit; font-size:12.5px; padding:5px 8px;
      border:1px solid var(--vien); border-radius:var(--r-o, 8px); background:var(--nen-o); color:var(--chu); }
  /* ⛔ ĐỪNG cho ô tìm nở hết bề ngang. Nó nở là nó chiếm trọn một hàng, đẩy năm ô lọc
     xuống hàng dưới — mất đúng 34px, tức gần một dòng bảng, mà chẳng ai cần ô tìm dài
     ngần ấy. Cho nó co giãn quanh 280px là tìm và lọc nằm chung một hàng. */
  .cts-loc .cts-tim { flex:0 1 280px; min-width:200px; }
  /* Cụm "− 100% +" dời vào cuối hàng bộ lọc — Boss 20/09/2026, xem `ctsGomZoomVaoLoc`.
     `margin-left:auto` đẩy nó sang mép phải, chỗ hàng lọc vốn đang bỏ trống.
     ⛔ Bỏ `margin-bottom` mà `.zoom-nut` mang sẵn (`margin:0 0 6px auto`): trong một
        hàng flex, lề dưới ấy chỉ làm hàng lọc cao thêm chứ chẳng ngăn cách với ai.
     ⛔ Bỏ luôn bóng đổ: nó là bóng của một cụm đứng riêng trên nền trang; nằm trong
        hàng lọc cùng các ô chọn thì bóng làm cụm trông như đang nổi lên trên. */
  /* ⛔⛔ CỤM "− 100% +" NẰM TRONG MỘT VỎ RIÊNG, KHÔNG THẢ THẲNG VÀO HÀNG LỌC.
     Lý do đầy đủ ở `ctsGomZoomVaoLoc` (man-hinh/tuyen-sinh.js): bộ gom nút của app rút
     mọi nút nằm cách hàng phụ ĐÚNG MỘT TẦNG, rút xong thì `gaZoomBang` cập nhật
     con số phần trăm vào một thẻ không còn tồn tại và ném lỗi. Vỏ này đẩy ba nút
     xuống tầng thứ ba, ngoài tầm với ấy.
     ⛔ Đừng gộp hai luật dưới thành một bằng cách bỏ vỏ đi cho gọn. */
  .cts-loc > .cts-zoom-vo { margin-left:auto; display:flex; align-items:center; flex:0 0 auto; }
  .cts-loc .zoom-nut.cts-zoom-loc { margin:0; box-shadow:none; }
  /* KHOẢNG THỞ — Boss dặn thẳng *"ko được sát quá mức gây bí bách"*.
     ⛔⛔ PHẢI LÀ `padding-bottom`, KHÔNG PHẢI `margin-bottom`. Hỏi CSSOM ra giá
        trị thật của lề dưới hàng lọc là `0px`: luật `#noiDung:has(table.dg-bang,
        table.cts-bang, …) > .sheet-giua-gon { margin-bottom:0 }` ở
        `css/lop.css` nặng hơn (1 id · 2 class · 1 thẻ — `:has()` lấy đặc
        hiệu của vế mạnh nhất trong ngoặc) và nó thắng mọi luật chỉ có class.
        Viết nặng hơn nữa là bước vào cuộc đua đặc hiệu mà chính luật ấy đã dặn
        đừng bước vào (*"KHÔNG DÙNG !important: màn nào cần lề riêng sẽ không đè
        lại được"*). Padding thì luật kia không đụng tới, nên không tranh với ai.
     ⛔ Khoảng thở này nằm TRONG chiều cao hàng lọc, nên đo bằng "khe giữa đáy hàng
        lọc và đỉnh bảng" sẽ ra 0 — phải đo chính `padding-bottom`. */
  .cts-loc.cts-loc-co-zoom { padding-bottom:9px; }
  /* Nút ở đầu màn nhỏ lại một nấc để tám cái nằm gọn MỘT hàng thay vì tràn xuống hai. */
  body:has(#ctsBang) .cts-dau .nut-nho { padding:5px 10px; font-size:12.5px; }
  /* ⛔⛔ 21/08/2026 — "Thêm học sinh" ĐÃ PHÌNH THÀNH MỘT DẢI MÀU NGUYÊN HÀNG.
     Cô Quỳnh: *"nó rất khó dùng và 1 số nút quan trọng bị tràn khuất màn hình"*.

     Gốc lỗi: nút ấy mang lớp `.nut-chinh`, mà `.nut-chinh` khai `width:100%` —
     lớp đó sinh ra cho nút "Đăng nhập" nằm một mình trong khung hẹp 340px, ở đó
     kéo hết bề ngang là đúng. Thả vào dải công cụ thì nó chiếm trọn một hàng, đẩy
     mọi nút đứng sau ("Tải lại"…) xuống hàng thứ ba. Ba hàng nút cho tám cái nút,
     trên đúng cái màn cô Quỳnh đã bảo "đỡ tốn diện tích nhất có thể".
     Nhìn cũng sai nốt: một dải màu đặc ngang màn hình là lối trang tiếp thị, không
     phải lối phần mềm nghiệp vụ.

     Nay: cùng cỡ, cùng chiều cao với các nút bên cạnh, chỉ khác ở chỗ TÔ ĐẶC để
     người ta biết đây là việc chính. Đây là cách những nút chính khác trong app đã
     làm từ lâu — xem `.nv-thanh > .nut-chinh` và `.pq-day > .nut-chinh`.
     ⛔ ĐỪNG chữa bằng cách đổi nút này sang `.nut-nho`: mất luôn phần tô đặc, tám
        nút xám như nhau thì không nút nào là việc chính nữa. */
  .cts-dau .nut-chinh {
    width:auto; height:auto; min-height:0;
    padding:5px 12px; font-size:12.5px; border-radius:var(--r-md);
    display:inline-flex; align-items:center; gap:6px;
  }
  /* 🗂 Dải tab của Sổ tuyển sinh (cô Quỳnh 16/08/2026) — hai cách nhìn CÙNG một sổ,
     không phải hai kho. Kiểu tab gạch chân, nghiêm túc, không viên thuốc màu mè. */
  .cts-tab { display:flex; gap:2px; margin-bottom:7px; border-bottom:1px solid var(--vien); }
  .cts-tab button { display:flex; align-items:center; gap:7px; border:none; background:none;
    font-family:inherit; font-size:13px; font-weight:700; color:var(--mo); cursor:pointer;
    padding:7px 13px; border-bottom:2px solid transparent; margin-bottom:-1px; }
  .cts-tab button:hover { color:var(--chu); }
  .cts-tab button.chon { color:var(--xanh-dam); border-bottom-color:var(--xanh); }
  /* Con số đi kèm: cho biết tab đó có bao nhiêu em, khỏi phải bấm vào mới biết. */
  .cts-tab button span { font-size:11px; font-weight:700; padding:1px 7px; border-radius:var(--r-xl);
    background:var(--nen2); color:var(--mo); }
  .cts-tab button.chon span { background:var(--xanh-nhat); color:var(--xanh-dam); }
  .cts-phieu { display:flex; gap:0; flex-wrap:wrap; margin-bottom:7px; border:1px solid var(--vien);
               border-radius:var(--r-lg); overflow:hidden; background:var(--the); }
  /* Số và nhãn NẰM NGANG NHAU — đây là chỗ cắt được nhiều chiều cao nhất. */
  .cts-phieu > div { flex:1; min-width:132px; padding:5px 11px; border-right:1px solid var(--vien);
      display:flex; align-items:baseline; gap:6px; }
  .cts-phieu > div:last-child { border-right:none; }
  .cts-phieu b { font-size:15px; font-weight:700; line-height:1.25; white-space:nowrap; }
  .cts-phieu span { font-size:11px; color:var(--mo); line-height:1.25; }
  /* Dòng phụ "Cả sổ": chiếm trọn một hàng dưới, chữ nhỏ và mờ để KHÔNG bị đọc lẫn
     với dải số của hôm nay. Trộn chung hàng là con số tích luỹ đứng cạnh con số
     trong ngày, nhìn ra hai chuyện khác nhau mà tưởng cùng loại. */
  .cts-phieu .cts-ca-so { flex:1 0 100%; min-width:0; border-right:none; display:block;
      border-top:1px solid var(--vien); background:var(--nen2);
      padding:4px 11px; font-size:11px; color:var(--mo); }
  /* Màn thấp: thu thêm một nấc. Mỗi 10px cắt được ở đây là thêm gần một dòng bảng. */
  @media (max-height: 900px) {
    .cts-dau { gap:7px; margin-bottom:5px; }
    .cts-dau h2 { font-size:15.5px; }
    .cts-loc { gap:6px; margin-bottom:5px; }
    .cts-loc select, .cts-loc input { font-size:12px; padding:4px 7px; }
    .cts-phieu { margin-bottom:5px; }
    .cts-phieu > div { padding:4px 9px; }
    .cts-phieu b { font-size:13.5px; }
    .cts-phieu span { font-size:10.5px; }
    .cts-phieu .cts-ca-so { padding:3px 9px; }
  }
  /* Màn hẹp: dải số xuống thành hai hàng còn hơn là mỗi ô bị bóp cụt mất chữ. */
  @media (max-width: 1100px) {
    .cts-phieu > div { min-width:calc(33.333% - 1px); }
    .cts-loc .cts-tim { flex:1 0 100%; }
  }
  /* Khung cuộn: chiều cao cố định để hàng tiêu đề có mép mà bám dính. */
  /* ⭐ CÔ QUỲNH 13/08/2026: *"tổng thể bạn thiết kế cột trông rất bé và hẹp mà nó
     chứa nhiều thông tin thế, phải để rộng ra để nhìn được nhiều thông tin trong
     một lúc"*. Nên màn này PHÁ khung 1500px của `.noi-dung` để dùng hết bề ngang
     màn hình, và bảng cao hơn. Chỉ áp cho màn tuyển sinh, không đụng màn khác. */
  /* ⛔⛔ SỬA 14/08/2026 — TRƯỚC ĐÂY DÙNG CLASS `man-cts` GẮN VÀO BODY, VÀ KHÔNG CHỖ
     NÀO GỠ RA. Cô Quỳnh mở Sổ tuyển sinh một lần, xem xong bấm sang Nhắc việc hay
     Báo cáo giáo viên — class vẫn còn nguyên, nên khung 1500px của MỌI màn còn lại
     biến mất, chữ chạy dài hết bề ngang màn 27 inch, đọc rất mệt. Phải tải lại trang
     mới hết.
     Gỡ class ở chỗ rời màn thì phải đi sửa 20 chỗ, sót một chỗ là lỗi quay lại. Nay
     hỏi thẳng: TRONG TRANG CÓ BẢNG TUYỂN SINH KHÔNG? Rời màn là bảng biến mất, luật
     tự hết hiệu lực — không cần ai nhớ gỡ. */
  /* ⛔ LỊCH TEST cũng phá khung 1500px (cô Quỳnh 14/08/2026: "mở rộng cả bộ lịch ra
     cân đối với full màn ở các máy, phù hợp với độ phân giải mỗi màn"). Bảy cột ngày
     nhồi trong 1500px thì mỗi cột chỉ còn hơn 200px — tên học sinh cụt hết. Cùng một
     lối "hỏi trong trang có khung lịch không" nên rời màn là luật tự hết. */
  body:has(#ctsBang) .noi-dung, body:has(#tksThan) .noi-dung,
  body:has(#ltKhung) .noi-dung {
      max-width:none; padding-left:14px; padding-right:14px; }
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ ĐỆM ĐÁY 40px CHÍNH LÀ DẢI TRẮNG DƯỚI BẢNG — vá 16/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"vẫn dữ ra 1 khoảng trắng bên dưới phí diện tích, để cái bảng chiếm
     hết bên dưới luôn cho tôi, hở trắng ra siêu ít thôi"*.

     `.noi-dung` có `padding: 20px 18px 40px` — 40px đệm đáy, đúng cho mọi màn cuộn
     bình thường. Nhưng ở sổ tuyển sinh nó gây ra dải trắng theo đường vòng, và đây
     mới là chỗ khó thấy:

       `ctsCanhCaoKhung` đo xong còn NGẮM LẠI LẦN HAI — hỏi trình duyệt "cả trang
       đang cao hơn cửa sổ bao nhiêu" rồi thu bảng vào đúng ngần ấy. Nó thấy trang
       thừa 40px, tưởng bảng dài quá, nên CẮT BẢNG ĐI 40px. Nhưng 40px thừa ấy là
       ĐỆM, không phải bảng — cắt xong đệm vẫn còn nguyên, chỉ bảng là ngắn lại.
       Kết quả: đúng một dải trắng 40px nằm dưới, không ai dùng vào việc gì.

     Bỏ đệm ở riêng màn này là hết. Chỉ áp cho SỔ TUYỂN SINH (`#ctsBang`) — màn Thống
     kê và Lịch test cuộn cả trang, cắt đệm đáy của chúng thì dòng cuối dính sát mép.
     ══════════════════════════════════════════════════════════════════════════════ */
  body:has(#ctsBang) .noi-dung { padding-top:12px; padding-bottom:4px; }
  body:has(#ctsBang) .cts-chan { margin-top:4px; }
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ MỞ SỔ TUYỂN SINH THÌ CẢ TRANG KHÔNG ĐƯỢC CUỘN — vá 15/08/2026, lần thứ hai.
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh báo lại: *"sổ tuyển sinh lúc kéo xuống thì các cột title ở đầu tiên không
     xuống cùng theo hướng kéo xuống"*.

     Hàng tiêu đề CÓ dán dính (position:sticky, top:0), nhưng nó chỉ dính so với KHUNG
     CUỘN của bảng. Nếu CẢ TRANG cũng cuộn được thì trang kéo cái khung ấy — kèm hàng
     tiêu đề đang dính bên trong — trôi lên khỏi màn. Người dùng thấy tiêu đề biến mất.

     Lần vá trước tôi chỉ đo lại chiều cao khung cho vừa cửa sổ. CHƯA ĐỦ: chỉ cần lề
     dưới của trang, hay một ô nào đó dựng xong mới cao thêm vài điểm ảnh, là trang lại
     có cái để cuộn và lỗi quay lại y nguyên.

     NAY CHẶN TẬN GỐC: mở sổ thì TRANG KHÔNG CUỘN ĐƯỢC NỮA, chỉ mỗi khung bảng cuộn.
     Không còn cách nào cho hàng tiêu đề trôi đi đâu.
     ⛔ Dùng phép hỏi "trong trang có bảng tuyển sinh không" chứ không gắn lớp vào thân
        trang — rời màn là luật tự hết, không cần ai nhớ gỡ. Gắn lớp rồi quên gỡ đã
        từng làm mọi màn khác mất khung 1500px (xem chú thích ngay trên).
     ⛔ Chỉ áp cho SỔ TUYỂN SINH. Màn Thống kê và Lịch test cuộn cả trang là đúng —
        chúng không có bảng nào cần ghim tiêu đề.
     ══════════════════════════════════════════════════════════════════════════════ */
  body:has(#ctsBang) { overflow:hidden; }
  /* Khung bảng tự co cho vừa phần còn lại của cửa sổ. Chiều cao thật do JS đo và đặt
     (xem ctsCanhCaoKhung); dòng này chỉ là mức dự phòng khi JS chưa kịp chạy. */
  body:has(#ctsBang) .cts-cuon { max-height:calc(100vh - 268px - var(--dnc-du, 0px)); }
  .cts-cuon { overflow:auto; max-height:calc(100vh - 268px - var(--dnc-du, 0px)); border:1px solid var(--vien);
              border-radius:var(--r-sheet); background:var(--the);
              /* app tự lo cuộn (xem gaKeoBang) — để trình duyệt lo là giật khi kéo */
              touch-action:none; overscroll-behavior:contain; }
  .cts-cuon.keo-duoc { cursor:grab; }
  .cts-cuon.keo-duoc.dang-keo { cursor:grabbing; }
  .cts-bang { border-collapse:separate; border-spacing:0; table-layout:fixed; font-size:12.5px; }
  .cts-bang th, .cts-bang td { border-right:1px solid var(--vien); border-bottom:1px solid var(--vien);
      padding:0 8px; height:30px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .cts-bang thead th { position:sticky; top:0; z-index:4; background:var(--dau-bang-nen); font-weight:700;
      font-size:12px; text-align:left; color:var(--dau-bang-chu);
      border-right-color:var(--dau-bang-vien); border-bottom-color:var(--dau-bang-vien); }
  /* Hai cột ĐẦU dính bên trái — bảng rộng ~5.100px, không ghim thì cuộn ngang là
     mất tên, chẳng biết đang xem hồ sơ của ai. */
  /* ⛔⛔ MỐC GHIM CỘT 2 PHẢI TỰ ĐO, ĐỪNG ĐÓNG ĐINH CON SỐ — cô Quỳnh báo 13/08/2026:
     *"lúc tôi kéo sang 2 bên bị kéo theo cột SĐT, trông loạn lắm"*.
     Chuyện đã xảy ra: bản đầu ghim cột SĐT ở `left:170px` cho khớp cột Tên HS rộng
     170px. Sau đó nới cột Tên lên 210px mà QUÊN đổi con số này → cột SĐT bắt đầu
     sớm hơn chỗ cột Tên kết thúc 40px, hai cột ĐÈ CHỒNG nhau. Kéo ngang là nội dung
     cuộn bên dưới lòi ra ở khe đó, nhìn như cột SĐT trôi theo tay.
     Tệ hơn: người dùng còn KÉO RỘNG/HẸP cột được (gaKeoCot nhớ lại cho lần sau), nên
     bất cứ con số cố định nào cũng sẽ sai ngay lần kéo đầu tiên.
     Nay lấy từ biến `--cts-d2`, và JS tự đo lại bề rộng thật sau mỗi lần vẽ và mỗi
     lần người dùng kéo cột. Xem hàm ctsDoMocGhim. */
  .cts-bang .cts-g1, .cts-bang .cts-g2, .cts-bang .cts-g3,
  .cts-bang .cts-g4, .cts-bang .cts-g5, .cts-bang .cts-g6 {
    /* ⛔⛔ 7, KHÔNG PHẢI 3 — vá 12/09/2026, CHIỀU CHE NGƯỢC ở SỔ TUYỂN SINH.
       Thang bậc chung của mọi bảng kiểu Sheet (xem khối `.sheet-moi.sheet-gham`
       trong css/lop.css) là: ô trôi auto · ô trôi đang gõ 5 · ô trôi bung ra 6 ·
       ô ghăm 7 · ô ghăm bung 8 · hàng tiêu đề 9 · ô góc 10.
       Sổ tuyển sinh ghăm năm cột bằng luật RIÊNG `.cts-g*` ở đây, nên nó đứng
       ngoài thang bậc ấy: thân bảng vẫn 3, tức THẤP HƠN cả ô đang gõ (5) — bấm
       sửa một ô cột trôi thì ô ấy nổi lên đè trùm sang dải đứng yên.
       ⚠ Ba cột đầu không lộ ra vì bộ chung còn khoác thêm `sheet-cot-gham` (z=7)
         tới cột Tên HS; đúng hai cột "Trường" và "Ngày sinh" thì không — đó là
         lý do chỉ hai cột ấy hỏng. ⛔ ĐỪNG chữa bằng cách khoác thêm lớp cho hai
         cột đó: số cột ghăm của Sổ tuyển sinh do JS quyết (CTS_COT_DAU), sửa ở
         CSS là mai kia đổi số cột thì sai tiếp. Nâng cả họ `.cts-g*` lên đúng bậc.
       ⛔ Nâng thân bảng thì PHẢI nâng luôn hàng tiêu đề (luật ngay dưới), không
          thì cuộn DỌC dải ghăm lại trèo lên che tiêu đề — đổi một lỗi lấy một lỗi. */
    position:sticky; z-index:7; background:var(--the);
  }
  .cts-bang .cts-g1 { left:0; }
  .cts-bang .cts-g2 { left:var(--g2, 0px); }
  .cts-bang .cts-g3 { left:var(--g3, 0px); }
  .cts-bang .cts-g4 { left:var(--g4, 0px); }
  .cts-bang .cts-g5 { left:var(--g5, 0px); }
  .cts-bang .cts-g6 { left:var(--g6, 0px); }
  .cts-bang thead .cts-g1, .cts-bang thead .cts-g2, .cts-bang thead .cts-g3,
  .cts-bang thead .cts-g4, .cts-bang thead .cts-g5, .cts-bang thead .cts-g6 {
    z-index:6; background:var(--dau-bang-nen); color:var(--dau-bang-chu);
  }
  /* Ô GÓC (vừa hàng tiêu đề vừa dải ghăm) = 10, trên hàng tiêu đề trôi (9).
     ⛔ PHẢI VIẾT RIÊNG MỘT LUẬT ĐẬM HƠN, đừng chỉ đổi số 6 ở luật trên:
     luật trên nặng (0,2,1), thua luật chung `.sheet-moi.sheet-gham thead th`
     (0,2,2) ở css/lop.css — mà file ấy còn nạp SAU file này, nên hòa
     điểm cũng thua nốt. Đo được trước khi vá (sân 20 hàng, khổ 2320, cuộn 800):
     "Trường"×"SĐT" giao 88px · "Trường"×"Email" 112px · "Ngày sinh"×"Email" 88px
     · "Ngày sinh"×"Địa chỉ" 30px — cả bốn đều z 9/9, và vì hòa điểm nên cái
     VẼ SAU (cột trôi) nằm trên. Thêm `table` + `th` cho đủ (0,2,3) là thắng hẳn.
     ⛔ Luật này CHỈ đặt `z-index`. Đừng gộp nền/màu chữ vào: màu ô góc do JS đo
        từ ô tiêu đề bên cạnh (`--sheet-nen-th`), gộp vào là cướp mất việc đó. */
  table.cts-bang thead th.cts-g1, table.cts-bang thead th.cts-g2,
  table.cts-bang thead th.cts-g3, table.cts-bang thead th.cts-g4,
  table.cts-bang thead th.cts-g5, table.cts-bang thead th.cts-g6 { z-index:10; }
  /* Vạch dày ở cột ghim CUỐI CÙNG — để mắt hiểu ngay "bên trái đứng yên, bên phải trôi".
     ⭐ 08/09/2026: vùng ghim rút từ SÁU xuống NĂM cột (Boss chốt lại thứ tự, xem
        `CTS_COT_DAU` trong js/tinh-nang.js), nên vạch dời từ `.cts-g6` sang `.cts-g5`.
     ⛔ Lớp `.cts-g6` nay KHÔNG còn ô nào mang nữa. Để vạch nằm lại đó thì nó biến mất
        khỏi màn hình và người nhìn không biết vùng đứng yên hết ở chỗ nào — số cột
        ghim và chỗ đặt vạch đi thành MỘT CẶP, đổi cái này phải dời cái kia. */
  .cts-bang .cts-g5 { border-right:2px solid var(--muc); }
  /* ⛔⛔ HÀNG TIÊU ĐỀ PHẢI CÙNG MỘT MÀU VỚI THÂN BẢNG — vá 12/09/2026 (nửa (a) của cụm vạch).
     Trước đó dòng này ghi `var(--dau-bang-vien)`, tức là MỘT ĐƯỜNG KẺ DÙNG HAI BIẾN MÀU:
     đo bằng pixel thật trên mốc b2d51e6, sân 20 hàng, cuộn ngang 45%, bốn khổ 1001/1280/
     1366/2320 đều ra cùng một cặp số —
         thân bảng   rgb(13,128,129)  dày 2px → 4,75:1   (đạt, chuẩn nét đồ hoạ WCAG ≥ 3:1)
         hàng tiêu đề rgb(185,179,170) dày 2px → 2,08:1   (KHÔNG đạt)
     nên cái vạch "một mảng đứng yên" bị GÃY MÀU đúng chỗ mắt nhìn vào đầu tiên.
     Ba màn kia (Dự giờ · Chăm sóc · Follow up · Lộ trình) không có bệnh này vì luật chung
     `.sheet-moi.sheet-gham .sheet-cot-gham-cuoi` vẽ `box-shadow` cho CẢ thead lẫn tbody.
     ⭐ Chính app cũng đã làm đúng ở khổ nhỏ: trong `@media (max-width:820px)` dưới kia,
        `.cts-bang .cts-g3, .cts-bang thead .cts-g3` dùng chung `var(--muc)`. Nay áp lại
        cho khổ lớn cho khỏi tự mâu thuẫn.
     ⛔ VẪN GIỮ MỘT LUẬT RIÊNG cho thead thay vì xoá đi: `.cts-bang thead th` (0,1,2) có
        khai `border-right-color:var(--dau-bang-vien)`, hôm nay thua `.cts-bang .cts-g5`
        (0,2,0) nên xoá vẫn ra --muc — nhưng ai siết luật kia lên một bậc là vạch âm thầm
        đổi màu lại mà không ai báo. Viết thẳng ra thì hỏng cũng hỏng to tiếng. */
  .cts-bang thead .cts-g5 { border-right:2px solid var(--muc); }
  /* ⛔ MỌI Ô PHẢI CÓ NỀN ĐẶC. Sáu cột đầu là cột GHIM (dính lại khi kéo ngang) —
     ô nào để nền trong suốt thì nội dung cuộn phía sau hiện xuyên qua, trông như
     chữ chồng chữ. Đặt trước luật sọc để sọc vẫn thắng. */
  /* ══════════════════════════════════════════════════════════════════════════════
     CỘT BỊ ẨN — cô Quỳnh 15/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     *"thêm chức năng ẩn cột nào đó đi, vì một số nhân viên kiểu không muốn nhìn thấy
     tất cả các cột thì họ có thể ẩn đi ở account của họ… và ẩn đi CHỈ Ở ACCOUNT ĐÓ
     chứ không phải tất cả mọi người đều bị ẩn cột đó."*

     ⛔⛔ ẨN TẠI CHỖ BẰNG display:none, KHÔNG BỎ CỘT KHỎI DANH SÁCH VẼ.
        Bề rộng cột người dùng tự kéo được lưu THEO VỊ TRÍ CỘT (khoá `cotRong:`, xem
        gaKeoCot). Bỏ hẳn một cột ra khỏi danh sách là mọi cột phía sau tụt lên một
        nấc, và ai đã kéo cột cho vừa mắt sẽ thấy bề rộng nhảy lung tung — đúng cái
        lỗi cô Quỳnh đã báo hồi 13/08.
        Giữ nguyên vị trí rồi ẩn đi thì bề rộng, mốc ghim, cuộn ảo đều không phải sửa.
     ⛔ Phải ẩn CẢ ô tiêu đề LẪN mọi ô dữ liệu của cột đó. Ẩn một bên là cả bảng lệch
        cột từ đó trở đi. */
  .cts-bang .cot-an { display:none; }
  .cts-bang tbody td { background:var(--the); }
  /* ⛔⛔ SỌC TÔ THEO LỚP `le`, KHÔNG DÙNG `nth-child` (sửa 14/08/2026).
     Bảng này cuộn ảo — mỗi lần kéo chỉ vẽ những dòng đang lọt màn hình, kèm hai ô
     đệm cũng là thẻ `tr`. Đếm bằng `nth-child` là đếm theo vị trí TRONG KHUNG NHÌN,
     nên vị trí của cùng một học sinh nhảy chẵn ↔ lẻ liên tục lúc kéo, và nền em đó
     nhấp nháy trắng ↔ xám. Cô Quỳnh gọi đúng tên: "nhấp nháy đen trắng khó chịu".
     Lớp `le` gán theo SỐ THỨ TỰ THẬT của dòng (xem `ctsVeBang`), nên sọc đứng yên. */
  /* ⛔ 21/08/2026 — SỌC ĐÃ TẮT, DÒNG LẺ NAY CŨNG TRẮNG. Cô Quỳnh chê thẳng:
     *"xám trắng gây loá mắt khó chịu kiểu dạng giao diện thời cũ"*, và bảo tô
     *"trắng hết như trong sheet"*. Google Sheets cũng không sọc.
     ⛔ Luật vẫn để đây chứ không xoá: lớp `le` là bản vá lỗi nhấp nháy 14/08/2026.
        Ai muốn bật sọc lại thì đổi `var(--the)` ở hai dòng dưới, TUYỆT ĐỐI KHÔNG
        quay về `nth-child` — bảng này cuộn ảo, nth-child là nền nhấp nháy lúc kéo. */
  .cts-bang tbody tr.le > td { background:var(--the); }
  .cts-bang tbody tr.le .cts-g1, .cts-bang tbody tr.le .cts-g2,
  .cts-bang tbody tr.le .cts-g3, .cts-bang tbody tr.le .cts-g4,
  .cts-bang tbody tr.le .cts-g5, .cts-bang tbody tr.le .cts-g6 { background:var(--the); }
  /* ⛔ ĐỔI MÀU CẢ DÒNG KHI RÊ CHUỘT LÀ THỨ ĐẮT NHẤT LÚC KÉO.
     Kéo ngang thì con trỏ quét qua hàng loạt dòng, mỗi lần đổi dòng là trình duyệt
     phải VẼ LẠI cả dòng 40 ô. Nay chỉ tô đúng hai cột ghim — vẫn đủ để mắt bám
     được dòng đang xem, mà việc vẽ lại giảm 20 lần.
     ⛔ Và TẮT HẲN khi đang kéo: lúc đó người ta nhìn cả bảng trôi, chẳng ai để ý
        dòng nào đang sáng. */
  /* ⭐ Bạn ĐĂNG KÝ NHIỀU LẦN: cả nhóm có một vạch dọc bên trái nối liền, dòng đầu
     bo trên, dòng cuối bo dưới — nhìn là biết mấy dòng này của cùng một người.
     Dùng vạch mảnh màu nhấn, không tô nền cả dòng: tô nền thì bảng 40 cột thành
     loang lổ, mà 216 bạn có nhiều lượt là rất nhiều mảng màu. */
  .cts-bang tbody tr.cts-nhom .cts-g1 { box-shadow:inset 3px 0 0 var(--muc); }
  /* ══════════════════════════════════════════════════════════════════════════════
     NÚT MỞ/ĐÓNG NHÓM HỌC SINH TRÙNG — cô Quỳnh 21/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ CHIỀU CAO PHẢI VỪA TRONG 30px. Cuộn ảo tính chỗ bằng số dòng × 30px
        (hằng CTS_CAO). Nút cao hơn ô là dòng phình ra, và cả bảng lệch chỗ cuộn —
        đúng lỗi "kéo xuống là trắng trơn" đã mất công vá ngày 14/08.
     ⛔ Nhãn nút là CON SỐ lượt, không phải ký tự hình. Trạng thái mở đọc bằng nền đặc.
     ⛔ Không đặt `position:absolute`: ô cột đầu là ô GHIM (position:sticky), chồng
        thêm một lớp định vị nữa là nút trôi khỏi ô lúc kéo ngang. */
  .cts-bung { display:inline-block; vertical-align:middle; width:17px; height:17px;
      line-height:15px; margin:0 5px 0 2px; padding:0; flex:none;
      font:inherit; font-size:10.5px; font-weight:700; font-variant-numeric:tabular-nums;
      text-align:center; color:var(--muc); background:var(--the);
      border:1px solid var(--muc); border-radius:var(--r-sm); cursor:pointer; }
  .cts-bung:hover { background:var(--xanh-nhat); }
  .cts-bung.mo { background:var(--muc); color:#fff; }
  /* Ô đệm của dòng con: đúng bề ngang cái nút (17 + 5 + 2) để chữ thẳng cột với
     dòng đầu. Không có nó thì dòng con lệch trái, bảng nhìn như vỡ. */
  .cts-bung-lui { display:inline-block; width:24px; height:1px; vertical-align:middle; }
  /* ═════════════════════════════════════════════════════════════════════════════
     🗑 NÚT XOÁ HÀNG — Boss 08/09/2026, đứng ở ô đầu mỗi dòng
     ─────────────────────────────────────────────────────────────────────────────
     ⛔ LUÔN HIỆN, MỜ NHẠT — ĐừNG ĐỔI SANG "chỉ hiện khi rê chuột".
        Hai lý do, cả hai đều đã cắn một lần ở chỗ khác trong chính bảng này:
        · ĐIỆN THOẠI KHÔNG CÓ RÊ CHUỘT. Ẩn sau `:hover` là trên máy tính thì có, trên
          điện thoại thì không bao giờ thấy — đúng kiểu tính năng chết im lặng mà không
          ai báo lỗi (chặng ② của skill `cong-cu-cho-nguoi-that`).
        · `tr:hover` LÀ THỨ ĐẮT NHẤT LÚC KÉO — xem lời ghi ngay trên `.cts-nhom`:
          con trỏ quét qua hàng loạt dòng, mỗi lần đổi dòng là vẽ lại cả dòng 40 ô.
        Mờ sẵn thì không có luật `tr:hover` nào cả, mà vẫn nhìn ra để bấm.
     ⛔ 15×15px VÀ `inline-block` — Ô CAO ĐÚNG 30px (hằng CTS_CAO trong js/tinh-nang.js).
        Cao hơn là dòng phình ra và cả bảng lệch chỗ cuộn — đúng lỗi "kéo xuống là
        trắng trơn" đã mất công vá ngày 14/08.
     ⛔ KHÔNG `position:absolute`: ô cột đầu là ô GHIM (position:sticky), chồng thêm
        một lớp định vị nữa là nút trôi khỏi ô lúc kéo ngang.
     ⛔ HÌNH THÙNG RÁC, KHÔNG PHẢI DẤU CHÉO. Dấu chéo đọc là "đóng lại"; thùng rác
        đọc là "bỏ đi mà lấy lại được" — đúng thứ nút này làm. Dùng chung mặt nạ
        `.icx-xoa` có sẵn ở bộ icon, không vẽ thêm hình mới.
     ═════════════════════════════════════════════════════════════════════════════ */
  .cts-bang .cts-xoa { display:inline-block; vertical-align:middle; width:15px; height:15px;
      margin:0 4px 0 0; padding:0; flex:none; border:0; background-color:var(--mo);
      opacity:.3; cursor:pointer; transition:opacity .12s, background-color .12s;
      -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
      -webkit-mask-position:center;  mask-position:center;
      -webkit-mask-size:contain;     mask-size:contain;
      -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 6h17M9.5 6V4.4A1.4 1.4 0 0 1 10.9 3h2.2a1.4 1.4 0 0 1 1.4 1.4V6'/%3E%3Cpath d='M18.2 6l-.8 13.1a1.6 1.6 0 0 1-1.6 1.5H8.2a1.6 1.6 0 0 1-1.6-1.5L5.8 6'/%3E%3Cpath d='M10 10.5v6M14 10.5v6'/%3E%3C/svg%3E");
      mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 6h17M9.5 6V4.4A1.4 1.4 0 0 1 10.9 3h2.2a1.4 1.4 0 0 1 1.4 1.4V6'/%3E%3Cpath d='M18.2 6l-.8 13.1a1.6 1.6 0 0 1-1.6 1.5H8.2a1.6 1.6 0 0 1-1.6-1.5L5.8 6'/%3E%3Cpath d='M10 10.5v6M14 10.5v6'/%3E%3C/svg%3E"); }
  .cts-bang .cts-xoa:hover, .cts-bang .cts-xoa:focus-visible {
      opacity:1; background-color:var(--do); }
  /* ⛔ Điện thoại: to hơn một chút và đậm hơn. Ngón tay không chọn được 15px mờ 30%,
     mà đây lại là màn không có rê chuột để cứu. Vẫn giữ trong 30px chiều cao. */
  @media (hover:none) {
    .cts-bang .cts-xoa { width:18px; height:18px; opacity:.55; } }

  /* 🗑 KHUNG THÙNG RÁC — danh sách hàng đã xoá, trong hộp thoại `rong`. */
  .cts-rac { max-height:56vh; overflow-y:auto; }
  .cts-rac-hang { display:flex; align-items:center; gap:10px;
      padding:8px 2px; border-bottom:1px solid var(--vien); }
  .cts-rac-hang:last-child { border-bottom:0; }
  .cts-rac-ten { flex:1 1 auto; min-width:0; font-weight:600;
      overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cts-rac-ten small { font-weight:400; color:var(--mo); }
  .cts-rac-phu { flex:0 0 auto; font-size:11.5px; color:var(--mo); }
  .cts-rac-lay { flex:0 0 auto; }
  @media (max-width:640px) {
    .cts-rac-hang { flex-wrap:wrap; }
    .cts-rac-ten { flex:1 1 100%; }
    .cts-rac-phu { flex:1 1 auto; } }

  /* 🔗 HỘP "NỐI VỚI DÒNG SỔ" — bên Lịch test, Boss 08/09/2026.
     Khối này của kênh Coder 2 (nhánh `tuyen-sinh`, commit 9845218). Ở nhánh ấy nó
     nằm trong `giao-dien.css`; nhánh này đã xé CSS làm ba nên nó phải sang đây,
     cạnh khối thùng rác cùng màn Tuyển sinh.
     ⛔ GIỮ TÊN LỚP `.ltt-noi-hang` — bài kiểm `thu-cts-noi-lich-test.js` canh nó.
     ⛔ Mỗi dòng kết quả là MỘT NÚT, không phải một `div` có tay bấm: bàn phím phải
        Tab tới được, và trình đọc màn hình phải biết đây là thứ bấm được.
     ⛔ CAO ÍT NHẤT 40px và cách nhau bằng đường kẻ: chọn nhầm dòng ở đây là gắn ca
        vào hồ sơ em khác — việc hệ trọng thì đích bấm phải rộng. */
        vào hồ sơ em khác — việc hệ trọng thì đích bấm phải rộng.
     ⚠️ Bản gốc gõ `var(--nen-2, rgba(0,0,0,.04))`. Biến ấy KHÔNG TỒN TẠI (app dùng
        `--nen2`, không gạch) nên nó lặng lẽ rơi về giá trị dự phòng — nền xám cứng
        `rgba(0,0,0,.04)` không theo nền tối, và không ai biết vì trình duyệt không
        kêu. Đã đổi về `--nen2`; đúng cái bẫy đã ghi ở lời dặn dòng ~2152 file này. */
  .ltt-noi-o { width:100%; box-sizing:border-box; margin:0 0 8px; }
  .ltt-noi-kq { max-height:46vh; overflow-y:auto; border:1px solid var(--vien);
      border-radius:8px; }
  .ltt-noi-hang { display:flex; align-items:center; gap:10px; width:100%;
      min-height:40px; padding:8px 10px; border:0; border-bottom:1px solid var(--vien);
      background:transparent; text-align:left; cursor:pointer; font:inherit;
      color:inherit; }
  .ltt-noi-hang:last-child { border-bottom:0; }
  .ltt-noi-hang:hover, .ltt-noi-hang:focus-visible { background:var(--nen-2, rgba(0,0,0,.04)); }
  .ltt-noi-hang:hover, .ltt-noi-hang:focus-visible { background:var(--nen2); }
  .ltt-noi-ten { flex:1 1 auto; min-width:0; font-weight:600;
      overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ltt-noi-ten small { font-weight:400; color:var(--mo); }
  .ltt-noi-phu { flex:0 0 auto; font-size:11.5px; color:var(--mo); }
  .ltt-noi-trong { padding:12px 10px; font-size:12.5px; color:var(--mo); }
  @media (max-width:640px) {
    .ltt-noi-hang { flex-wrap:wrap; }
    .ltt-noi-ten { flex:1 1 100%; }
    .ltt-noi-phu { flex:1 1 auto; } }
  /* Dòng con (lượt cũ vừa bung ra) — chữ nhạt hơn một nấc để mắt biết đâu là dòng
     chính. ⛔ KHÔNG đổi nền: nền đổi thì mất sọc chẵn/lẻ, mà sọc ấy vừa mới được vá
     cho hết nhấp nháy hôm 14/08. */
  .cts-bang tbody tr.cts-nhom.con td { color:var(--mo); }
  /* ⭐ 21/09/2026 — LƯỢT CŨ TÔ NHẠT. Boss chốt bằng nút: *"chỉ tô nhạt các lượt CŨ;
     lượt mới nhất và mọi học sinh khác vẫn trắng"*. Lời dặn "KHÔNG đổi nền" ngay trên
     là của thời còn sọc — sọc đã tắt từ 21/08 (bảng trắng hết như Sheet), nên nay tô
     không còn đụng gì.
     ⛔ `background-color`, KHÔNG `background`: ô đầu mang dải số dòng vẽ bằng
        `background-image`; viết tắt `background` là xoá mất dải số.
     ⛔ Độ nặng (0,4,3) CỐ Ý: thắng nền trắng của sổ và nền dải ghăm dùng chung
        (`.sheet-moi.sheet-gham tbody td.sheet-cot-gham` 0,3,2) — không thì sáu cột ghim
        vẫn trắng giữa một dòng xám — nhưng THUA luật rê chuột (0,5,2), nên rê vào lượt
        cũ vẫn sáng lên như mọi dòng khác.
     ⛔ `:where(:not(...))` không cộng độ nặng: ô đang gõ vẫn trắng như mọi ô đang gõ,
        và ô Boss tô màu tay (`sheet-dd-to`) vẫn giữ màu của Boss.
     ⛔ Lượt cũ mang lớp `sheet-nen-rieng` để `sheetGhamCot` KHÔNG lấy màu này làm màu
        cả dải ghăm — đúng đường lỗi "cả cột cố định xanh hết" Boss báo 21/09. */
  .cts-cuon .cts-bang tbody tr.cts-nhom.con > td:where(:not(:focus-within, .sheet-dd-to)) {
      background-color:var(--nen2); }
  /* ⭐ 21/09/2026 — MỞ NHÓM THÌ LƯỢT CŨ TRƯỢT NHẸ RA (Boss chốt bằng nút: bảng đứng
     yên, không nháy, và có trượt nhẹ). Lớp `cts-vua-mo` chỉ có trong ĐÚNG MỘT lượt vẽ
     ngay sau cú bấm — xem `ctsBungNhom`. Cuộn ảo vẽ lại liên tục mà lớp còn thì kéo
     đến đâu lượt cũ trượt đến đó.
     ⛔ Chỉ `opacity` + `transform`: không đổi chiều cao dòng. Cuộn ảo tính chỗ bằng
        số dòng × chiều cao dòng — dòng phình ra một nhịp là cả bảng lệch.
     ⛔ Tên khung hình riêng — đừng mượn khung hình của màn khác (bài học: keyframe
        dùng chung kéo về giá trị của nó). */
  @keyframes cts-luot-cu-truot {
      from { opacity:0; transform:translateY(-6px); }
      to   { opacity:1; transform:none; } }
  .cts-cuon .cts-bang tbody tr.cts-vua-mo > td { animation:cts-luot-cu-truot .18s ease-out; }
  @media (prefers-reduced-motion: reduce) {
    .cts-cuon .cts-bang tbody tr.cts-vua-mo > td { animation:none; } }
  /* ⛔⛔ RÊ CHUỘT CHỈ TÔ KHI KHÔNG KÉO — VÀ TÔ BẰNG LUẬT RIÊNG, KHÔNG DÙNG `inherit`.
     Bản cũ tô hover rồi gỡ bằng một luật thứ hai `background:inherit` lúc đang kéo.
     Hỏng ở chỗ: thẻ dòng không có nền riêng, nên `inherit` ra TRONG SUỐT — mà luật
     đó lại nặng ký hơn cả luật sọc lẫn luật nền cột ghim. Kết quả: đang kéo thì dòng
     dưới con trỏ mất sạch nền, và nội dung cuộn phía sau LÒI QUA sáu cột ghim. Thêm
     một nhịp nhấp nháy nữa, đúng lúc người ta đang kéo.
     Nay khoanh thẳng điều kiện vào luật hover, khỏi cần luật gỡ. */
  .cts-cuon:not(.dang-keo) .cts-bang tbody tr:hover .cts-g1,
  .cts-cuon:not(.dang-keo) .cts-bang tbody tr:hover .cts-g2,
  .cts-cuon:not(.dang-keo) .cts-bang tbody tr:hover .cts-g3,
  .cts-cuon:not(.dang-keo) .cts-bang tbody tr:hover .cts-g4,
  .cts-cuon:not(.dang-keo) .cts-bang tbody tr:hover .cts-g5,
  .cts-cuon:not(.dang-keo) .cts-bang tbody tr:hover .cts-g6 { background:var(--xanh-nhat); }
  /* ⛔ ĐỪNG đặt `will-change` cho các ô ghim. Với 2 cột thì còn được; nay 6 cột ×
     36 dòng đang vẽ = 216 ô, mỗi ô một lớp đồ hoạ riêng — tốn bộ nhớ card màn hình
     và làm CHẬM chính cái nó định làm nhanh. Trình duyệt tự lo phần này tốt hơn.
     Cái thật sự làm mượt là không vẽ lại bảng khi kéo ngang (xem ctsHenVe). */
  .cts-dem td { padding:0; border:none; height:0; }        /* hai ô đệm của cuộn ảo */
  .cts-chip { display:inline-block; padding:1px 8px; border-radius:var(--r-lg); font-size:11.5px; font-weight:700; }
  .cts-tien { text-align:right; font-variant-numeric:tabular-nums; }
/* CHEP TU NHANH `tuyen-sinh` (Coder 2, moc 195b6d3) — nhanh do van dung mot
   file `giao-dien.css`, nhanh nay da tach lam ba. Khoi nay thuoc man So tuyen
   sinh nen dat o `css/man.css`. Sua ben ay thi nho chep sang day. */
  /* ════════════════════════════════════════════════════════════════════════
     💰 CỘT GOM TIỀN — Boss 08/09/2026, thay cho mười lăm cột
     ────────────────────────────────────────────────────────────────────────
     ⛔ NÚT PHẢI VỪA TRONG MỘT DÒNG 30px (`CTS_CAO`). Cao hơn là đè sang dòng dưới,
        vì cuộn ảo đặt từng dòng theo đúng con số ấy chứ không đo lại.
     ⛔ KHÔNG `position:absolute` — bảng này có sáu cột ghim dùng `position:sticky`;
        một thằng con thoát khỏi dòng chảy là nó trôi qua cột ghim lúc kéo ngang.
     ⛔ NỀN TRẮNG, VIỀN MẢNH, chữ thường — không in đậm 800, không viết hoa,
        không giãn chữ. Đây là bảng kiểu Google Sheets, xem `thiet-ke/BANG-MAU-VA-CHU.md`.
     ════════════════════════════════════════════════════════════════════════ */
  .cts-tien-nut { display:inline-flex; align-items:center; gap:5px;
      max-width:100%; height:21px; padding:0 8px; margin:0;
      font:inherit; font-size:12px; color:var(--chu);
      background:var(--the); border:1px solid var(--vien);
      border-radius:var(--r-sm); cursor:pointer; }
  .cts-tien-nut:hover { background:var(--xanh-nhat); border-color:var(--muc); }
  .cts-tien-so { font-variant-numeric:tabular-nums; }
  /* ── Ruột ô gom: NGÀY + SỐ TIỀN của lần gần nhất (Boss 09/09/2026) ──
     ⛔ Hai mẩu nằm TRÊN MỘT DÒNG, không xếp dọc: cả ô chỉ cao 30px (`CTS_CAO`).
     ⛔ Số tiền đậm hơn ngày một nấc — đó là thứ mắt tìm trước khi lướt cả cột. */
  /* XXX KHONG DE CHU DE LEN NHAU — Boss bao 09/09/2026 kem anh: nhan "+3 lan truoc"
     chen het cho, so tien bi de len khong doc duoc. Ba luat phai di cung nhau:
     · nut CAT phan thua (overflow:hidden) — khong cho chu tran ra ngoai vien;
     · cum ngay+tien duoc co lai (flex:1 1 auto, min-width:0);
     · SO TIEN khong bao gio bi cat (flex:none) — do la thu Boss can nhin;
       ngay bi cat truoc, va cat bang dau ... chu khong cut giua chung. */
  .cts-tien-moi { display:inline-flex; align-items:baseline; gap:6px;
      flex:1 1 auto; min-width:0; overflow:hidden; }
  .cts-tien-nut { overflow:hidden; }
  .cts-tien-moi .cts-tien-mn { flex:0 1 auto; min-width:0; overflow:hidden;
      text-overflow:ellipsis; white-space:nowrap; }
  .cts-tien-moi .cts-tien-mt { flex:none; }
  .cts-tien-mn { color:var(--mo); font-variant-numeric:tabular-nums; }
  .cts-tien-mt { font-weight:600; font-variant-numeric:tabular-nums; }
  .cts-tien-moi.hoan .cts-tien-mt { color:var(--do); }
  /* "+2" — nhạt thôi, nó là lời mời bấm chứ không phải con số chính.
     Câu đầy đủ nằm ở `title`, xem lý do ở `ctsVeO` trong js/tinh-nang.js. */
  .cts-tien-them2 { flex:none; font-size:11px; color:var(--mo); }
  /* Ô chưa có lần đóng nào: chữ mờ, nhưng VẪN BẤM ĐƯỢC — đó là đường duy nhất
     để ghi lần đầu tiên. 2.492 / 4.652 dòng đang ở trạng thái này, nên đừng đậm quá
     kẻo cả cột thành một rừng chữ. */
  .cts-tien-trong { color:var(--mo); }
  /* Dấu ! — dòng có lần đóng thiếu ngày hoặc thiếu số tiền (đo thật: 21 mục).
     ⛔ Vẽ bằng màu chứ không bằng emoji ⚠ — luật "không ký tự thay hình". */
  .cts-tien-thieu { flex:none; width:13px; height:13px; line-height:13px;
      font-size:10.5px; font-weight:700; text-align:center;
      color:#fff; background:var(--o-thieu); border-radius:50%; }
  /* ── Hộp "Các lần đóng tiền" ── */
  .cts-tien-ds { max-height:46vh; overflow-y:auto;
      border:1px solid var(--vien); border-radius:var(--r-sm); }
  .cts-tien-hang { display:flex; align-items:center; gap:10px;
      padding:7px 10px; border-bottom:1px solid var(--vien); font-size:13px; }
  .cts-tien-hang:last-child { border-bottom:0; }
  /* Mục thiếu ngày hoặc thiếu số: nền ấm để nhìn là thấy, không ẩn đi. */
  .cts-tien-hang.thieu { background:var(--do-nen); }
  .cts-tien-ngay { flex:0 0 92px; font-variant-numeric:tabular-nums; }
  .cts-tien-loai { flex:1 1 auto; min-width:0;
      overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cts-tien-loai.hoan { color:var(--do); }
  .cts-tien-so2 { flex:0 0 auto; min-width:96px; text-align:right;
      font-variant-numeric:tabular-nums; }
  .cts-tien-ht { flex:0 0 62px; font-size:11.5px; color:var(--mo); }
  .cts-tien-xoa { flex:none; width:22px; height:22px; padding:0; line-height:1;
      font:inherit; font-size:12px; color:var(--mo);
      background:none; border:1px solid transparent; border-radius:var(--r-sm);
      cursor:pointer; }
  .cts-tien-xoa:hover { color:var(--do); border-color:var(--do); }
  /* ⛔ Hỏi lại NGAY TRONG DÒNG khi xoá một lần đóng — xem khối chú thích cùng
     tên trong js/tinh-nang.js. Mở hộp thoại thứ hai ở đây là nuốt mất cả hộp tiền,
     vì `#htThan` là một thẻ dùng chung. Nền đỏ nhạt để mắt bắt ngay dòng đang chờ
     trả lời, hai nút nằm đúng chỗ dấu xoá vừa bấm nên ngón tay không phải đi đâu. */
  .cts-tien-hang.hoi { background:var(--do-nen); }
  .cts-tien-hoi { flex:1 1 auto; min-width:0; font-size:12.5px; color:var(--do); }
  .cts-tien-hang.hoi .nut-nho { flex:none; height:26px; padding:0 10px; font-size:12px; }
  .cts-tien-xoathat { color:var(--do); border-color:var(--do); }
  .cts-tien-trong-hop { padding:14px 10px; font-size:12.5px; color:var(--mo); }
  /* Hàng ghi thêm — bốn ô trên một dòng ở màn rộng, xuống dòng ở màn hẹp. */
  .cts-tien-them { display:flex; flex-wrap:wrap; align-items:center; gap:8px;
      margin-top:10px; }
  .cts-tien-them select, .cts-tien-them input { font:inherit; font-size:13px;
      height:32px; padding:0 8px; color:var(--chu); background:var(--the);
      border:1px solid var(--vien); border-radius:var(--r-o, 8px); box-sizing:border-box; }
  .cts-tien-loai-chon { flex:0 0 150px; }
  /* O ngay = o chu + nut lich nho, dung sat nhau thanh MOT o. Boss chot 09/09/2026:
     "o ghi ngay cho chon ngay va ghi ngay deu duoc". */
  .cts-tien-o-ngay { display:flex; align-items:center; gap:4px; flex:0 0 154px; }
  .cts-tien-ngay-o { flex:1 1 auto; min-width:0; }
  .cts-tien-lich { flex:none; width:30px; padding:0 2px; }
  /* XXX Chrome ve o date rat rong; bop lai chi con nut lich, phan chu an di. */
  .cts-tien-lich::-webkit-datetime-edit,
  .cts-tien-lich::-webkit-inner-spin-button,
  .cts-tien-lich::-webkit-clear-button { display:none; }
  .cts-tien-lich::-webkit-calendar-picker-indicator { margin:0; padding:0; cursor:pointer; }
  .cts-tien-so-o   { flex:1 1 120px; min-width:110px; }
  /* Rong 130px chu khong 78 — nay la o CHON, phai chua het chu "Chuyen khoan". */
  .cts-tien-ht-o   { flex:0 0 130px; }
  @media (max-width:620px) {
    .cts-tien-hang { flex-wrap:wrap; }
    .cts-tien-ngay { flex:0 0 auto; }
    .cts-tien-so2 { min-width:0; }
    .cts-tien-them > * { flex:1 1 100%; }
  }
  /* ⛔ DẤU TÍCH VẼ BẰNG NÉT, KHÔNG DÙNG KÝ TỰ.
     Bản đầu tôi đổ ký tự ✓ vào ô. Bài kiểm bắt ngay, và bắt đúng: luật cô Quỳnh
     chốt là *"không emoji, không ký tự thay hình"* — ký tự dấu tích chính là một
     ký tự đứng thay cho hình vẽ, mỗi máy một phông lại ra một kiểu, có máy còn ra
     ô vuông rỗng. Vẽ bằng hai nét viền xoay 45° thì máy nào cũng ra như nhau. */
  .cts-tick { display:inline-block; width:11px; height:6px; margin-bottom:3px;
              border-left:2px solid var(--o-tot); border-bottom:2px solid var(--o-tot);
              transform:rotate(-45deg); }
  /* Ô tích còn TRỐNG — vẽ cái khung vuông rỗng để người ta biết là bấm được, chứ ô
     trắng trơn thì không ai đoán ra. Mờ thôi, đậm quá thì 40 cột thành rừng khung. */
  .cts-o-tich { display:inline-block; width:12px; height:12px; vertical-align:-2px;
                border:1.5px solid var(--vien); border-radius:var(--r-sm); opacity:.65; }
  td.cts-sua:hover .cts-o-tich { opacity:1; border-color:var(--o-tot); }
  /* Ô có chữ lạ ("TM", "CK" — người ta gõ nhầm hình thức trả tiền vào cột tích).
     Gạch chân chấm để nhìn là biết ô này KHÔNG phải ô tích, bấm vào sẽ mở ô gõ chữ. */
  .cts-chu-la { border-bottom:1px dotted var(--mo); }
  /* Đang gửi lên máy chủ — mờ đi một chút để biết là máy đang làm, không phải đơ. */
  td.dang-luu { opacity:.45; }
  .cts-trong { padding:26px; text-align:center; color:var(--mo); }
  /* ⛔ SỔ HỎNG KHÁC SỔ TRỐNG — thêm 17/08/2026.
     Trước đây hai chuyện này trông y hệt nhau: cùng một bảng trắng, cùng một câu chữ
     xám. Người mở sổ ra xem tưởng mất sạch dữ liệu, trong khi file vẫn nằm trên đĩa,
     chỉ là máy chủ đọc không ra. Nhãn đỏ và chữ đỏ để nhìn phát biết ngay là có
     chuyện, chứ không phải "chưa ai nhập". Khuôn bám theo `.cts-thu` ở trên.
     ⛔ CỐ Ý dùng `var(--do)` chứ KHÔNG gõ mã màu cứng như `.cts-thu`. Hai cái lợi:
        `--do` đã có sẵn bản riêng cho nền tối nên khỏi phải viết thêm dòng
        `body.toi`; và bài kiểm `thu-cts-man-hinh.js` canh đúng chuyện này — nó chỉ
        cho tối đa 4 luật `.cts-*` được gõ mã màu cứng, thêm nữa là đỏ ngay. Viền đỏ
        trên nền thường đã đủ rõ, không cần tô nền. */
  .cts-hong { font-size:11px; font-weight:700; padding:3px 9px;
             border-radius:var(--r-sm); background:transparent; color:var(--do);
             border:1px solid var(--do); }
  .cts-trong-hong { color:var(--do); font-weight:600; }
  /* ⛔ Tiêu đề KHÔNG bấm được nữa (cô Quỳnh bỏ 13/08/2026) — nên không có con trỏ
     bàn tay, không có mũi chỉ chiều. Giữ user-select:none để lúc kéo ngang không
     bôi đen chữ tiêu đề. */
  .cts-bang thead th { user-select:none; }
  /* Ô sửa được: chỉ hiện gợi ý khi rê chuột, để bảng 40 cột không thành rừng ô vuông. */
  .cts-bang td.cts-sua { cursor:text; }
  .cts-bang td.cts-sua:hover { box-shadow:inset 0 0 0 1px var(--muc); }
  .cts-bang td.dang-sua { padding:0; box-shadow:inset 0 0 0 2px var(--muc); }
  .cts-o { width:100%; height:28px; box-sizing:border-box; border:none; outline:none;
           background:var(--nen-o); color:var(--chu); font-family:inherit; font-size:12.5px;
           padding:0 7px; }
  select.cts-o { padding:0 3px; }
  /* Ô viết chữ — Boss 20/09/2026: *"nó phải mở ra như xem để sửa chứ"*.
     ⛔ `height:auto` để JS (`ctsGianOChu`) làm chủ chiều cao — luật `.cts-o` ngay trên
        ghim cứng 28px, không gỡ thì ô không bao giờ giãn được.
     ⛔ `word-break: break-word` là bắt buộc: link Facebook dài 236 ký tự không có
        dấu cách nào, không cho bẻ giữa chữ thì nó tràn ngang y như cũ.
     ⛔ `z-index` để ô đang viết NỔI LÊN trên các hàng dưới, không thì chữ giãn ra
        nằm dưới hàng kế — đúng cảnh "bị che khuất" Boss chê. */
  textarea.cts-o-chu {
    height:auto; min-height:28px; resize:none; overflow:hidden;
    white-space:pre-wrap; word-break:break-word; line-height:1.35;
    position:relative; z-index:45; background:var(--nen, #fff);
    box-shadow:0 2px 10px rgba(0,0,0,.14);
  }
  .cts-chan { font-size:12px; color:var(--mo); margin-top:8px; }

  /* ═══════════ 📊 THỐNG KÊ TUYỂN SINH — công cụ riêng (13/08/2026) ═══════════
     Cô Quỳnh: *"cái thống kê của tuyển sinh để ra 1 công cụ riêng là thống kê
     tuyển sinh"*, và *"để theo từng tháng từng tuần từng ngày để có số liệu cụ thể"*.
     Tách ra khỏi sổ CTS vì hai việc khác nhau: sổ là để LÀM VIỆC hằng ngày, thống kê
     là để NGỒI XEM. Nhét chung thì mở sổ lúc nào cũng phải kéo qua một mảng số. */
  /* ══════════════════════════════════════════════════════════════════════════════
     BẢNG ĐIỀU KHIỂN TUYỂN SINH — cô Quỳnh 14/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"báo cáo thống kê có cả dashboard và pie chart và bảng chứng khoán
     lên xuống"*.

     ⛔ MÀU BIỂU ĐỒ KHÔNG CHỌN BẰNG MẮT. Sáu màu dưới đây đã chạy qua máy kiểm màu và
        ĐẠT cả sáu phép: nằm trong dải sáng cho phép · đủ tươi để không hoá xám · phân
        biệt được với người mù màu (cả kiểu đỏ-lục lẫn vàng-lam) · người mắt thường
        nhìn cũng tách bạch · đủ tương phản với nền.
        Bảng màu SẴN CÓ của app thì TRƯỢT: teal và xám-xanh bị máy coi là xám, hai màu
        cam/vàng quá nhạt trên nền trắng. Đổi màu ở đây thì phải chạy lại máy kiểm,
        đừng sửa bằng cảm tính.
     ⛔ THỨ TỰ MÀU LÀ CƠ CHẾ AN TOÀN, không phải trang trí — hai màu ĐỨNG CẠNH NHAU
        mới là cặp cần tách bạch. Cấp màu theo đúng thứ tự này, đừng xáo.
     ⛔ Chế độ tối dùng BƯỚC MÀU RIÊNG, không phải lấy màu sáng rồi làm mờ đi.
     ══════════════════════════════════════════════════════════════════════════════ */
  :root {
    --bd1:#2a78d6; --bd2:#eb6834; --bd3:#1baf7a;
    --bd4:#eda100; --bd5:#e87ba4; --bd6:#008300;
    --bd-len:#1E7C45; --bd-giam:#C0392B;
  }
  body.toi {
    --bd1:#3987e5; --bd2:#d95926; --bd3:#199e70;
    --bd4:#c98500; --bd5:#d55181; --bd6:#008300;
    --bd-len:#5BB37C; --bd-giam:#E5766C;
  }
  /* ── Dải ô số dẫn đầu ── */
  .bd-o { display:flex; gap:0; flex-wrap:wrap; margin-bottom:12px;
          border:1px solid var(--vien); border-radius:var(--r-lg); overflow:hidden;
          background:var(--the); }
  .bd-o > div { flex:1; min-width:132px; padding:11px 14px;
                border-right:1px solid var(--vien); }
  .bd-o > div:last-child { border-right:none; }
  .bd-o .bd-nhan { font-size:11.5px; color:var(--mo); display:block; margin-bottom:3px; }
  /* ⛔ Số dẫn đầu KHÔNG dùng chữ số đều bề ngang: ở cỡ lớn nó làm "121" trông rời rạc.
     Chỉ bảng mới cần đều bề ngang, để các hàng thẳng cột nhau. */
  .bd-o .bd-so { font-size:23px; font-weight:700; line-height:1.15; display:block; }
  .bd-o .bd-doi { font-size:11.5px; font-weight:700; margin-top:2px; display:block; }
  .bd-doi.len  { color:var(--bd-len); }
  .bd-doi.giam { color:var(--bd-giam); }
  .bd-doi.bang { color:var(--mo); font-weight:600; }
  /* ── Hàng hai tấm: biểu đồ tròn và bảng so kỳ ── */
  .bd-hang { display:flex; gap:12px; flex-wrap:wrap; margin-bottom:12px; align-items:stretch; }
  .bd-tam { flex:1 1 340px; min-width:0; border:1px solid var(--vien); border-radius:var(--r-lg);
            background:var(--the); padding:12px 14px; }
  .bd-tam h3 { font-size:13px; font-weight:700; margin:0 0 2px; }
  .bd-tam .bd-phu { font-size:11.5px; color:var(--mo); margin:0 0 10px; }
  .bd-chia { display:flex; gap:14px; align-items:center; flex-wrap:wrap; }
  .bd-tron { flex:none; }
  /* ⛔ CHÚ GIẢI LUÔN CÓ khi từ hai phần trở lên — màu không được là cách DUY NHẤT để
     biết phần nào là phần nào. Kèm luôn con số, để ai không phân biệt được màu vẫn
     đọc đủ. (Máy kiểm màu báo ba màu hơi nhạt so với nền trắng, và cách bù đúng
     luật là hiện số ra chữ như thế này.) */
  .bd-chu { flex:1 1 170px; min-width:0; font-size:12px; }
  .bd-chu div { display:flex; align-items:center; gap:7px; padding:2.5px 0; }
  .bd-chu i { flex:none; width:10px; height:10px; border-radius:var(--r-sm); }
  .bd-chu .bd-ten { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bd-chu .bd-sl { font-variant-numeric:tabular-nums; color:var(--mo); }
  .bd-doi-chon { display:flex; gap:6px; margin-bottom:9px; flex-wrap:wrap; }
  .bd-doi-chon button { font-size:11.5px; padding:3px 9px; border:1px solid var(--vien);
                        border-radius:var(--r-sm); background:var(--the); color:var(--chu);
                        font-family:inherit; cursor:pointer; }
  .bd-doi-chon button.chon { background:var(--muc); color:#fff; border-color:var(--muc); }
  /* ── Bảng so với kỳ trước ── */
  .bd-so-ky { width:100%; border-collapse:collapse; font-size:12.5px; }
  .bd-so-ky th, .bd-so-ky td { padding:5px 8px; border-bottom:1px solid var(--vien);
      text-align:right; white-space:nowrap; font-variant-numeric:tabular-nums; }
  .bd-so-ky th { font-size:11px; font-weight:700; color:var(--mo); }
  .bd-so-ky th:first-child, .bd-so-ky td:first-child { text-align:left;
      font-variant-numeric:normal; }
  .bd-so-ky tr:last-child td { border-bottom:none; }
  .bd-so-ky .len  { color:var(--bd-len); font-weight:700; }
  .bd-so-ky .giam { color:var(--bd-giam); font-weight:700; }
  .bd-so-ky .bang { color:var(--mo); }
  .bd-canh { font-size:11.5px; color:var(--mo); margin:8px 0 0; }

  /* ══════════════════════════════════════════════════════════════════════════════
     LỊCH TEST — DỰNG LẠI THEO LỐI GOOGLE CALENDAR (cô Quỳnh 14/08/2026)
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh xem bản đầu rồi bác: *"bạn làm thế này kiểu copy y hệt lịch thi định kỳ
     của giáo viên… cái giao diện tôi rất cần là google calendar để mọi người dễ dùng"*.

     Bản đầu là một cái BẢNG có ô giờ — đúng là trông y như công cụ Lịch thi định kỳ.
     Nay dựng đúng lối Google Calendar, gồm bốn phần người ta quen mắt:
       · CỘT TRÁI: nút đặt lịch · lịch tháng thu nhỏ để nhảy ngày · danh sách người
         phụ trách có ô tích để lọc (đúng chỗ Google để "Lịch của tôi")
       · THANH TRÊN: Hôm nay · hai mũi tên · tên khoảng đang xem · chọn Ngày/Tuần/Tháng
       · LƯỚI GIỜ: cột giờ bên trái, các cột ngày, VẠCH ĐỎ chỉ giờ hiện tại
       · THẺ CA đặt ĐÚNG VỊ TRÍ theo phút, cao theo thời lượng — không nhét vào ô

     ⛔ THẺ ĐẶT BẰNG TOẠ ĐỘ THEO PHÚT, không xếp vào ô giờ. Đây là khác biệt lớn nhất
        giữa "cái bảng" và "cái lịch": ca 17h30 phải nằm giữa dòng 17h và 18h, không
        phải nằm gọn trong ô 17h. Nhìn là thấy ngay ca nào chồng giờ nhau.
     ⛔ CA CHỒNG GIỜ CHIA ĐÔI BỀ NGANG, không đè lên nhau. Đo thật: ngày đông nhất có
        70 em, khung 09:00 có tới 346 lượt trong cả sổ — chồng giờ là chuyện thường
        ngày, đè lên nhau là mất hẳn thông tin.
     ⛔ KHÔNG hiệu ứng, KHÔNG đổ bóng, KHÔNG chuyển màu. Google Calendar bản thân nó
        cũng phẳng; và luật cô Quỳnh cấm mọi thứ trang trí.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ⛔ LỊCH CHIẾM HẾT BỀ NGANG MÀN (cô Quỳnh 14/08/2026: "mở rộng cả bộ lịch ra cân
     đối với full màn ở các máy, phù hợp với độ phân giải mỗi màn").
     Dùng phép hỏi "trong trang có lưới lịch không" thay vì gắn lớp vào thân trang —
     rời màn là luật tự hết, không cần ai nhớ gỡ (xem chú thích ở màn tuyển sinh). */
  .lt-man { display:flex; gap:18px; align-items:flex-start; }
  /* Cột trái co giãn theo bề ngang màn: hẹp thì 214px, màn 27" thì nở tới 268px —
     lịch mini to lên cho dễ bấm, chứ không nhỏ mãi một cỡ. */
  .lt-ben { flex:none; width:clamp(214px, 15vw, 268px); }
  /* ⭐ 16/08/2026 — BA THỨ CHỈ DÀNH CHO ĐIỆN THOẠI, MẶC ĐỊNH ẨN.
     Nút ba sọc ☰, tấm mờ sau ngăn kéo, và nút tròn ＋ ở góc. Trên máy tính cột trái
     nằm sẵn cạnh lịch nên không cần ngăn kéo, và nút "Đặt lịch test" đã ở ngay đó.
     ⛔ Ẩn Ở ĐÂY (ngoài mọi @media) chứ đừng chỉ khai `display` trong @media màn nhỏ —
        khai một chiều thì máy tính mọc thêm ba thứ lạ giữa màn. Phần @media ≤820px
        bật lại bằng `display:flex !important`. */
  .lt-ham, .lt-mo, #ltFab, .lt-dong-ngan { display:none; }
  .lt-chinh { flex:1; min-width:0; }

  /* ── Cột trái ── */
  .lt-tao { width:100%; border:none; background:var(--muc); color:#fff; font-family:inherit;
      font-size:13px; font-weight:700; padding:9px 12px; border-radius:var(--r-md); cursor:pointer;
      margin-bottom:12px; }
  .lt-tao:hover { background:var(--xanh-dam); }
  .lt-mini { border:1px solid var(--vien); border-radius:var(--r-md); background:var(--the);
      padding:9px 10px 11px; margin-bottom:12px; }
  .lt-mini-dau { display:flex; align-items:center; justify-content:space-between;
      margin-bottom:6px; }
  .lt-mini-ten { font-size:12.5px; font-weight:700; }
  .lt-mini-dau button { border:none; background:transparent; color:var(--mo);
      font-family:inherit; font-size:15px; line-height:1; padding:2px 6px; cursor:pointer;
      border-radius:var(--r-sm); }
  .lt-mini-dau button:hover { background:var(--nen2); color:var(--chu); }
  .lt-mini-luoi { display:grid; grid-template-columns:repeat(7, 1fr); gap:1px; }
  .lt-mini-luoi span { font-size:11.5px; color:var(--mo); text-align:center; padding:2px 0; }
  /* ⛔⛔ Ô NGÀY LÀ Ô VUÔNG, KHÔNG BAO GIỜ LÀ HÌNH TRÒN — cô Quỳnh 21/08/2026:
     *"bỏ hình tròn đi nhìn tởm quá"*. Mẫu gốc cô thích là Google Sheets, ở đó một ô
     được chọn là một Ô VUÔNG tô đặc, không phải cái vòng.
     ⛔ Và `border-radius:50%` không chỉ bo cái nút: nó CẮT mọi box-shadow vẽ sau đó
        theo vành ellipse. Dấu "ngày có ca test" ở dưới vốn định là một vạch thẳng,
        bị vành ấy cắt thành NÉT CONG BÁN NGUYỆT — đó là cái cô nhìn thấy. Ai đặt
        lại 50% ở đây là nét cong quay về, dù không đụng gì tới dòng dấu ấy. */
  .lt-mini-luoi button { border:none; background:transparent; color:var(--chu);
      font-family:inherit; font-size:12px; padding:0; height:26px; border-radius:var(--r-sm);
      cursor:pointer; font-variant-numeric:tabular-nums; }
  .lt-mini-luoi button:hover { background:var(--nen2); }
  .lt-mini-luoi button.ngoai { color:var(--mo); opacity:.55; }
  /* Ngày có ca test: CHỈ IN ĐẬM CON SỐ, không đeo dấu hiệu nào cả.
     ⛔⛔ TUYỆT ĐỐI KHÔNG THÊM LẠI HÌNH VẼ QUANH SỐ NGÀY. Cô Quỳnh đã nói BA LẦN về
        đúng chỗ này trong một ngày (21/08/2026):
          ① *"bỏ hình tròn đi nhìn tởm quá"*        → tôi bỏ vòng tròn, thay bằng vạch
          ② (tôi để vạch chạy suốt bề ngang)        → bảy ngày nối thành một đường kẻ
          ③ *"bỏ mấy cái gạch ngang ở dưới các số đi"* → bỏ nốt vạch
        Ý cô đã rõ hẳn: ô ngày phải TRƠN. Chấm tròn, gạch chân, vòng cung, chấm màu —
        tất cả đều là cùng một thứ cô không muốn. Đừng sáng tạo lại.
     ⛔ Nhưng GIỮ nét đậm 700: bỏ nốt thì ngày có ca và ngày trống trông y hệt nhau,
        lịch mini mất hẳn công dụng. */
  .lt-mini-luoi button.co { font-weight:700; }
  /* ⛔ ĐÃ BỎ DẢI TÔ CẢ TUẦN — cô Quỳnh 15/08/2026: *"cái bảng này lúc ấn không cần
     hiện cả thanh tuần đâu"*. Bấm một ngày mà cả bảy ngày cùng sáng lên thì mắt phải
     dò lại xem rốt cuộc mình đang chọn ngày nào. Nay chỉ ngày ĐANG XEM được tô đậm
     (.dangxem) và HÔM NAY có viền (.homnay) — hai dấu đó đủ và không lẫn nhau. */
  /* ══════════════════════════════════════════════════════════════════════════════
     HAI DẤU KHÁC NHAU, ĐỪNG GỘP LÀM MỘT
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh 14/08/2026: *"ấn ngày 14 xong ấn 15 thì cái ô xanh in đậm ngày vẫn là
     14"*. Vì bản đầu chỉ có dấu HÔM NAY, mà hôm nay thì không đổi — bấm sang ngày
     khác là dấu đứng im, nhìn tưởng bấm hụt.
       • vòng tròn ĐẶC  = ngày ĐANG XEM  (đổi mỗi lần bấm — đây là phản hồi)
       • vòng tròn VIỀN = HÔM NAY        (mốc cố định để định vị)
     Ngày đang xem mà trùng hôm nay thì vòng đặc thắng, có thêm viền cho rõ.
     ══════════════════════════════════════════════════════════════════════════════ */
  .lt-mini-luoi button.homnay { box-shadow:inset 0 0 0 1.5px var(--muc); font-weight:700; }
  /* Hôm nay MÀ ĐỒNG THỜI có ca test: hai dấu nay không tranh nhau thuộc tính nào
     (viền là box-shadow, vạch là nền) nên tự chồng lên nhau đúng, khỏi cần luật gộp. */
  .lt-mini-luoi button.dangxem { background:var(--muc); color:#fff; font-weight:700; }
  .lt-mini-luoi button.dangxem:hover { background:var(--xanh-dam); }
  /* Ngày đang xem đã tô đặc nên nền dùng hết rồi — vạch "có ca" ở đây phải vẽ bằng
     box-shadow, và cố ý để nó chạy suốt bề ngang: chỉ có ĐÚNG MỘT ngày đang xem nên
     không có chuyện hai vạch nối vào nhau. */
  .lt-mini-luoi button.dangxem.co { background:var(--muc);
      box-shadow:inset 0 -3px 0 #fff; }
  .lt-mini-luoi button.dangxem.co:hover { background:var(--xanh-dam); }

  /* ── Ô tìm học sinh (cô Quỳnh 21/08/2026) ── */
  .lt-tim-khoi { margin-bottom:10px; }
  .lt-tim { width:100%; box-sizing:border-box; border:1px solid var(--vien);
      border-radius:var(--r-md); padding:7px 11px; font-family:inherit; font-size:13px;
      background:var(--nen-o); color:var(--chu); }
  .lt-tim:focus { outline:none; border-color:var(--muc); }
  .lt-tim-dem { font-size:11.5px; color:var(--mo); margin-top:5px; min-height:15px;
      font-variant-numeric:tabular-nums; }
  /* Không tìm thấy gì thì nói bằng MÀU nữa, không chỉ bằng chữ — dòng xám nhỏ rất dễ
     lướt qua, mà đây là lúc người ta đang nhìn một cái lịch trống và tự hỏi vì sao. */
  .lt-tim-dem.khong { color:var(--do); }

  .lt-nguoi { border:1px solid var(--vien); border-radius:var(--r-md); background:var(--the);
      padding:9px 10px; }
  .lt-nguoi h4 { font-size:12.5px; font-weight:700; color:var(--chu); margin:0 0 7px;
      letter-spacing:normal; }
  .lt-nguoi label { display:flex; align-items:center; gap:8px; padding:3.5px 0;
      font-size:12.5px; cursor:pointer; }
  .lt-nguoi input { flex:none; width:14px; height:14px; accent-color:var(--muc);
      margin:0; cursor:pointer; }
  .lt-nguoi i { flex:none; width:11px; height:11px; border-radius:var(--r-sm); }
  .lt-nguoi .lt-ten { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .lt-nguoi .lt-dem { font-size:11px; color:var(--mo); font-variant-numeric:tabular-nums; }
  /* Khối lọc CƠ SỞ dùng lại y nguyên kiểu của khối người phụ trách (mang cùng lớp
     .lt-nguoi), chỉ thêm quãng cách với khối trên và một ô mã ngắn.
     ⛔ Ô mã phải là span, KHÔNG được là thẻ i: luật .lt-nguoi i ngay bên trên ép mọi
        thẻ i trong khối này thành ô vuông 11×11 — nhét chữ vào là mất chữ. */
  .lt-coso { margin-top:12px; }
  .lt-coso .lt-ma { flex:none; min-width:38px; text-align:center; font-size:12px;
      font-weight:600; letter-spacing:normal; padding:1px 5px; border-radius:var(--r-sm);
      border:1px solid var(--vien); background:var(--nen2); color:var(--chu); }

  /* ── Thanh trên ── */
  .lt-top { display:flex; align-items:center; gap:8px; margin-bottom:10px; flex-wrap:wrap; }
  .lt-top button { border:1px solid var(--vien); background:var(--the); color:var(--chu);
      font-family:inherit; font-size:12.5px; padding:5px 11px; border-radius:var(--r-md); cursor:pointer; }
  .lt-top button:hover { background:var(--nen2); }
  .lt-mui { padding:5px 9px !important; font-size:15px !important; line-height:1; }
  .lt-tieude { font-size:16px; font-weight:700; margin:0 4px; }
  .lt-che { display:flex; border:1px solid var(--vien); border-radius:var(--r-md); overflow:hidden;
      margin-left:auto; }
  .lt-che button { border:none; border-right:1px solid var(--vien); border-radius:0;
      padding:5px 12px; }
  .lt-che button:last-child { border-right:none; }
  .lt-che button.chon { background:var(--muc); color:#fff; }

  /* ── Lưới giờ ── */
  .lt-khung { border:1px solid var(--vien); border-radius:var(--r-sheet); background:var(--the);
      overflow:auto; max-height:calc(100vh - 214px - var(--dnc-du, 0px));
      touch-action:none; overscroll-behavior:contain; }
  /* ⛔⛔ `touch-action:none` LÀ CỐ Ý, và DÒNG DƯỚI KHÔNG THỪA.
     ① Vì sao `none`: lưới Tuần ép `min-width:820px`, trên màn 390px nó thừa ra
        460px. Trước 20/09/2026 chỗ này để `pan-y` nên trình duyệt chỉ cuộn dọc,
        còn mọi cú vuốt ngang bị cử chỉ "đổi tuần" nuốt — đo thật: vuốt ngang
        160px, `scrollLeft` vẫn 0. Tức cột thứ Năm → Chủ nhật KHÔNG AI VỚI TỚI.
        Nay `man-hinh/lich-test.js` gọi `gaKeoBang(#ltKhung)` — đúng bộ kéo của bảng
        Điểm danh — nên app tự lo cả hai chiều. Đây cũng là bài học 25/07/2026 ở
        khối `.khung-cuon`: `pan-y` bắt trình duyệt ĐOÁN hướng trước, kéo rất ì.
     ② Vì sao phải lặp lại với `[data-keo-ngang="1"]`: `ganKeoNgang` cắm thuộc
        tính ấy lên chính `#ltKhung`, mà `css/lop.css` có
        `[data-keo-ngang="1"]{touch-action:pan-y}` — NGANG ĐỘ NẶNG và nạp SAU
        file này, nên nó thắng. Đã dính đúng bẫy này ở `.lgv-khung` cùng ngày:
        sửa xong đo trong Chrome thật vẫn ra `pan-y` ở cả 5 cỡ màn.
     ⛔ Cố ý KHÔNG dùng `!important`: luật `[data-keo-ngang]` kia vẫn đúng cho
        mọi khung vuốt khác, chỉ hai khung lịch này là ngoại lệ. */
  .lt-khung[data-keo-ngang="1"] { touch-action:none; }
  /* Cột ngày rộng tối thiểu 150px thay vì để bóp lại — dưới mức đó tên học sinh cụt
     hết, mà tên là thứ duy nhất người xếp lịch cần đọc. Màn rộng thì các cột tự chia
     đều phần thừa. */
  .lt-than, .lt-dau-hang { min-width:0; }
  .lt-dau-hang { display:grid; position:sticky; top:0; z-index:5; background:var(--the);
      border-bottom:1px solid var(--vien); }
  .lt-dau-o { text-align:center; padding:9px 6px 10px; border-left:1px solid var(--vien); }
  .lt-dau-o:first-child { border-left:none; }
  .lt-dau-o .lt-thu { font-size:10.5px; color:var(--mo);
 }
  .lt-dau-o .lt-sn { font-size:22px; font-weight:600; line-height:1.25; margin-top:2px; }
  /* ══════════════════════════════════════════════════════════════════════════════
     ⛔⛔ HAI DẤU KHÁC NHAU Ở HÀNG TIÊU ĐỀ — vá 14/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"tôi ấn 13 mà trên bảng lịch không chịu bôi xanh 13, vẫn giữ số 14"*.
     Vì bản cũ CHỈ có dấu HÔM NAY. Bấm 13 thì lưới có vẽ lại thật, nhưng vẽ ra giống
     hệt từng ký tự — 13 và 14 cùng một tuần nên chẳng có gì đổi. Nhìn như bấm hụt.
       • vòng tròn ĐẶC  = ngày ĐANG XEM  (đổi theo mỗi lần bấm — đây là phản hồi)
       • vòng tròn VIỀN = HÔM NAY        (mốc cố định để định vị)
     Đúng quy ước đã dùng ở lịch mini bên trái, để hai bên nói cùng một thứ tiếng.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ⛔ Ô VUÔNG, không phải vòng tròn — cùng một luật với lưới tháng nhỏ, xem lời
     cảnh báo ở `.lt-mini-luoi button`. Cả app chỉ có MỘT lối đánh dấu ngày. */
  .lt-dau-o.homnay .lt-sn { box-shadow:inset 0 0 0 2px var(--muc); color:var(--muc);
      border-radius:var(--r-sm); min-width:34px; height:30px; line-height:30px; margin:2px auto 0;
      padding:0 6px; font-size:17px; font-weight:700; }
  .lt-dau-o.dangxem .lt-sn { background:var(--muc); color:#fff; box-shadow:none;
      border-radius:var(--r-sm); min-width:34px; height:30px; line-height:30px; margin:2px auto 0;
      padding:0 6px; font-size:17px; font-weight:700; }
  /* Cả cột của ngày đang xem sáng lên một chút, để mắt bắt được ngay cột nào — đúng
     lối Google Calendar làm với ngày được chọn. */
  .lt-dau-o.dangxem { background:var(--xanh-nhat); }
  .lt-cot.dangxem { background:var(--xanh-nhat); }
  .lt-dau-o.cuoituan { background:transparent; }
  .lt-than { display:grid; position:relative; }
  .lt-cot-gio { border-right:1px solid var(--vien); }
  /* ⛔ height PHẢI bằng LTT_CAO_GIO trong mã (58). Lệch là nhãn giờ trôi khỏi vạch. */
  .lt-nhan-gio { height:66px; font-size:11.5px; color:var(--mo); text-align:right;
      padding-right:8px; position:relative; top:-7px; font-variant-numeric:tabular-nums; }
  .lt-cot { position:relative; border-left:1px solid var(--vien); }
  /* ⛔ CUỐI TUẦN KHÔNG TÔ NỀN XÁM (cô Quỳnh 14/08/2026: "bỏ cái background xám đằng
     sau đi để yên cái cách dòng kẻ cho nó smooth"). Mảng xám cắt lưới thành từng
     khối, phá mất cảm giác các dòng giờ chạy liền một mạch. Google Calendar cũng để
     cuối tuần nền y hệt ngày thường. */
  .lt-cot.cuoituan { background:transparent; }
  /* ⛔ Vạch giờ phải MỜ hơn thẻ, không tranh mắt với nội dung. Vạch nửa giờ mờ hẳn —
     có để ước lượng, không để đọc. */
  .lt-vach { position:absolute; left:0; right:0; border-top:1px solid var(--vien);
      opacity:.75; }
  .lt-vach.nua { border-top-style:solid; opacity:.32; }
  /* Vạch đỏ chỉ giờ hiện tại — thứ khiến người ta tin đây là cái lịch đang sống. */
  .lt-bay-gio { position:absolute; left:0; right:0; height:0; z-index:4;
      border-top:2px solid var(--do); pointer-events:none; }
  .lt-bay-gio::before { content:""; position:absolute; left:-4px; top:-5px; width:8px;
      height:8px; border-radius:50%; background:var(--do); }
  /* ══════════════════════════════════════════════════════════════════════════════
     BẢNG MÀU THẺ CA — LỐI GOOGLE CALENDAR (cô Quỳnh 14/08/2026)
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"thiết kế cứng cáp ở mấy cái ô, trong quá — để thoải mái và không bị
     viền đậm vậy, kiểu khung vuông như Google Calendar á"*.

     ⛔ KHÔNG mượn --bd1..--bd6 nữa. Bộ đó là màu BIỂU ĐỒ TRÒN, cố ý bão hoà cao để
        sáu miếng bánh nhỏ tách bạch nhau. Màu tốt cho miếng bánh thì thành khối màu
        đè mắt khi bôi lên hai chục cái thẻ nằm cạnh nhau.
     ⛔ Đo thật bằng máy tương phản: nền cũ + chữ TRẮNG thì 5/7 màu TRƯỢT chuẩn đọc
        4,5 lần (hổ phách #eda100 chỉ được 2,17). Chế độ tối còn tệ hơn, 6/7 trượt.
        Bộ mới lật ngược: nền NHẠT, chữ TỐI cùng tông → cả 7 màu đều vượt 5,7 lần.
     ⛔ Nền tối dùng BƯỚC MÀU RIÊNG, không phải lấy màu sáng rồi làm mờ đi.
     ⛔ Đổi số ở đây thì phải chạy lại máy đo (kiem-thu/thu-mau-the-lich.js), đừng
        sửa bằng cảm tính.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ⛔ SÁU SẮC ĐẶT CÁCH ĐỀU 60° TRÊN VÒNG MÀU, DỰNG BẰNG MÁY chứ không chọn bằng
     mắt (kiem-thu/thu-mau-the-lich.js đo lại mỗi lần chạy). Bản chọn tay đầu tiên có
     "xanh lá" và "lục đậm" chỉ cách nhau 4,3 — hai sắc xanh na ná, hai người phụ
     trách nhìn như một. Bản này cặp gần nhau nhất cũng cách 17. */
  :root {
    --ltt-n1:#C4E3FF; --ltt-c1:#006099;   /* xanh dương   chữ/nền 5,04 */
    --ltt-n2:#F4D6F7; --ltt-c2:#784782;   /* tím          chữ/nền 5,23 */
    --ltt-n3:#FFD3D2; --ltt-c3:#943D43;   /* hồng đỏ      chữ/nền 5,15 */
    --ltt-n4:#F4DCBA; --ltt-c4:#725514;   /* cam đất      chữ/nền 5,22 */
    --ltt-n5:#CAE8C8; --ltt-c5:#2B6530;   /* xanh lá      chữ/nền 5,28 */
    --ltt-n6:#ADEAED; --ltt-c6:#006971;   /* xanh ngọc    chữ/nền 4,84 */
    --ltt-n0:#E4E7EB; --ltt-c0:#3D4653;   /* chưa giao và thẻ "+N ca"  7,70 */
  }
  body.toi {
    --ltt-n1:#26425B; --ltt-c1:#A6D0FC;   /* 6,48 */
    --ltt-n2:#4E3951; --ltt-c2:#E5C0EA;   /* 6,44 */
    --ltt-n3:#5B3636; --ltt-c3:#FEBBBB;   /* 6,44 */
    --ltt-n4:#4C3E25; --ltt-c4:#E4C89C;   /* 6,45 */
    --ltt-n5:#2F452E; --ltt-c5:#AFD6AD;   /* 6,48 */
    --ltt-n6:#0D474A; --ltt-c6:#87DADD;   /* 6,50 */
    --ltt-n0:#2B3037; --ltt-c0:#AEB7C4;   /* 6,56 */
  }
  /* Thẻ: nền nhạt, chữ tối cùng tông, bo góc nhỏ 3px, một đường viền mảnh cùng
     tông chữ để mép thẻ sắc — không đổ bóng, không hiệu ứng, đúng luật của dự án.
     ⛔ `box-sizing:border-box` là luật toàn cục (dòng 389) nên thêm viền KHÔNG làm
        thẻ cao thêm; chiều cao vẫn đúng con số mã nguồn tính ra.
     ⛔ Cỡ chữ 13px là SÀN, đừng hạ nữa. Bản 12px đã bị cô Quỳnh chê thẳng
        21/08/2026 là *"chữ vừa bé"*. */
  .lt-the { position:absolute; border:1px solid currentColor; border-radius:var(--r-sm);
      padding:4px 7px;
      font-family:inherit; font-size:13px; line-height:1.32; cursor:pointer;
      overflow:hidden; text-align:left;
      background:var(--ltt-n0); color:var(--ltt-c0); }
  /* Rê chuột: nền SẪM lại một chút. ⛔ Không dùng brightness(1.06) như bản cũ — nền
     đã nhạt sẵn, làm sáng thêm thì nhìn như thẻ đang mờ đi, ngược ý. */
  .lt-the:hover { filter:brightness(.96); }
  body.toi .lt-the:hover { filter:brightness(1.18); }
  /* Bảy cặp nền-và-chữ. ⛔ Gắn bằng LỚP chứ không tô bằng style inline: thẻ cần một
     CẶP nền+chữ đi liền, và cặp đó phải tự đổi khi bật nền tối. Tên lớp do
     lttLopMau() trong mã sinh ra. */
  .lt-the.ltt-mau1 { background:var(--ltt-n1); color:var(--ltt-c1); }
  .lt-the.ltt-mau2 { background:var(--ltt-n2); color:var(--ltt-c2); }
  .lt-the.ltt-mau3 { background:var(--ltt-n3); color:var(--ltt-c3); }
  .lt-the.ltt-mau4 { background:var(--ltt-n4); color:var(--ltt-c4); }
  .lt-the.ltt-mau5 { background:var(--ltt-n5); color:var(--ltt-c5); }
  .lt-the.ltt-mau6 { background:var(--ltt-n6); color:var(--ltt-c6); }
  .lt-the.ltt-mau0 { background:var(--ltt-n0); color:var(--ltt-c0); }
  /* Giờ + tên em: chữ VỪA đậm, không đậm hết cụm — Google cũng vậy. */
  .lt-the b { display:block; font-weight:600; white-space:nowrap; overflow:hidden;
      text-overflow:ellipsis; }
  /* Dòng phụ (cơ sở · người phụ trách): chữ thường, nhỏ hơn dòng trên.
     ⛔ KHÔNG làm mờ bằng opacity. opacity làm mờ luôn cái nhãn cơ sở nằm bên trong,
        mà nhãn đó phải là thứ RÕ NHẤT của dòng này. Thứ bậc đã đủ nhờ cỡ chữ và độ
        đậm rồi (12px/600 ở trên, 11px/400 ở dưới) — Google Calendar cũng chỉ làm vậy. */
  /* ⛔ 21/08/2026 — 11px/400 bị cô Quỳnh chê là *"mờ nhạt"*. Nay 12px/500: vẫn
     nhẹ hơn dòng trên (13px/600) nên thứ bậc còn nguyên, mà đọc được thật. */
  .lt-the span { display:block; font-size:12px; font-weight:500;
      white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
  /* ══════════════════════════════════════════════════════════════════════════════
     NHÃN MÃ CƠ SỞ TRÊN THẺ
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh 14/08/2026: *"cần có cách nào đó để nhận biết học sinh đó test ở CƠ SỞ
     nào rõ hơn, chứ chỉ ghi PV trong block học sinh đó thì khó nhìn lắm"*.

     ⛔ GỐC RỄ KHÔNG PHẢI "CHỮ NHỎ" MÀ LÀ THỨ TỰ CẮT CHỮ. Dòng phụ cắt bằng dấu ba
        chấm ở ĐUÔI, mà mã cơ sở lại được nối vào ĐUÔI. Một cột ngày chia ba làn trên
        màn 1366 chỉ còn khoảng 25 điểm ảnh chữ — đủ cho "H.Yế…" là hết, mã cơ sở bị
        xoá sạch. Đưa lên ĐẦU dòng thì nó thành thứ CUỐI CÙNG bị cắt.

     ⛔ KHÔNG TÔ MÀU THEO CƠ SỞ. Nền thẻ đã mang màu người phụ trách; chồng thêm một
        bảng màu nữa là có cặp trùng nhau (nhãn xanh trên thẻ xanh thì mất hút). Nhãn
        LẤY NGƯỢC cặp màu của chính thẻ đó: nền nhãn = màu chữ của thẻ, chữ nhãn =
        màu mặt lưới. Nhờ vậy nhãn luôn nổi bật đúng mức trên mọi màu thẻ, ở cả nền
        sáng lẫn nền tối, mà không phải đo thêm cặp màu nào.
     ⛔ Thông tin nằm ở CHỮ, không nằm ở màu — nên người mù màu vẫn đọc được.

     ⛔ CÓ TRẦN BỀ NGANG. Máy chủ giữ nguyên chữ gốc khi không nhận ra cơ sở, mà chữ
        gốc trong Sheet có ô dài tới 78 ký tự. Không chặn là một dòng địa chỉ đẩy nát
        cả cái thẻ.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ⛔⛔ ĐỪNG DÙNG currentColor CHO NỀN NHÃN — LỖI ĐÃ XẢY RA THẬT 14/08/2026.
     Bản đầu viết background:currentColor; color:var(--the). Nghe thì hay: "nền nhãn
     lấy màu chữ của thẻ". Nhưng currentColor đọc thuộc tính color CỦA CHÍNH THẺ NHÃN,
     mà dòng ngay dưới lại đặt color:var(--the) — nên nền và chữ RA CÙNG MỘT MÀU
     TRẮNG. Kết quả: nhãn hiện ra là một ô trắng rỗng, mã cơ sở mất hút hoàn toàn.
     Nay khai thẳng từng cặp một, xem khối .lt-the.ltt-mauN .lt-cs bên dưới. */
  .lt-the .lt-cs { display:inline-block; vertical-align:1px; max-width:64px;
      overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
      background:var(--ltt-c0); color:var(--ltt-n0); font-style:normal; font-size:11.5px;
      font-weight:600; letter-spacing:normal; line-height:1.5; padding:0 4px;
      border-radius:var(--r-sm); margin-right:5px; }
  /* Nhãn dùng ĐẢO NGƯỢC cặp màu của chính thẻ đó: nền nhãn = màu chữ của thẻ, chữ
     nhãn = màu nền của thẻ. Nhờ vậy nhãn luôn nổi đúng mức trên mọi màu thẻ, ở cả nền
     sáng lẫn nền tối, mà không phải đo thêm cặp màu nào — cặp đó đã đo rồi. */
  .lt-the.ltt-mau1 .lt-cs { background:var(--ltt-c1); color:var(--ltt-n1); }
  .lt-the.ltt-mau2 .lt-cs { background:var(--ltt-c2); color:var(--ltt-n2); }
  .lt-the.ltt-mau3 .lt-cs { background:var(--ltt-c3); color:var(--ltt-n3); }
  .lt-the.ltt-mau4 .lt-cs { background:var(--ltt-c4); color:var(--ltt-n4); }
  .lt-the.ltt-mau5 .lt-cs { background:var(--ltt-c5); color:var(--ltt-n5); }
  .lt-the.ltt-mau6 .lt-cs { background:var(--ltt-c6); color:var(--ltt-n6); }
  .lt-the.ltt-mau0 .lt-cs { background:var(--ltt-c0); color:var(--ltt-n0); }
  /* ⛔⛔ ĐÃ CÓ ĐIỂM = GẠCH BÊN TRÁI, KHÔNG PHẢI VÒNG QUANH THẺ.
     Chính cái vòng inset 0 0 0 2px của bản cũ là "viền đậm" cô Quỳnh chê: nó chạy
     sát mép trong cả bốn phía, màu xanh rất tối đè lên nền cam/hồng nên chênh sáng
     tối tới 2,4 lần — mắt đọc ra là cái hộp có khung. Nay chỉ còn một vạch dọc bên
     trái; lề trái nới lên 10px để chữ không đè lên vạch. */
  .lt-the.xong { box-shadow:inset 3px 0 0 var(--o-tot); padding-left:10px; }
  /* Ca chưa ghi giờ: xếp thành một dải riêng ngay dưới đầu cột, không nhét vào lưới —
     nhét đại vào một giờ nào đó là bịa giờ hẹn. */
  /* Dải "chưa ghi giờ": nền y như lưới, chỉ ngăn bằng một nét mảnh — không tô xám. */
  .lt-chua-gio { border-bottom:1px solid var(--vien); background:transparent;
      padding:5px 7px; font-size:11px; color:var(--mo); }
  .lt-chua-gio .lt-the { position:static; display:inline-block; margin:2px 3px 2px 0;
      max-width:100%; }

  /* ══════════════════════════════════════════════════════════════════════════════
     KÉO THẢ THẺ SANG GIỜ KHÁC — cô Quỳnh 14/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ touch-action:none CHỈ đặt cho thẻ nằm trong lưới giờ và trong dải "chưa ghi
        giờ" — hai chỗ kéo được. Đặt cho cả .lt-the thì thẻ trong lịch THÁNG cũng
        dính, mà lịch tháng không kéo được: ngón tay chạm trúng thẻ là không cuộn
        được lịch tháng nữa, chẳng đổi lại được gì.
     ⛔ THIẾU DÒNG NÀY LÀ HỎNG NGẦM TRÊN MÁY TÍNH BẢNG: ngón tay vừa đi là trình duyệt
        hiểu "đang cuộn trang" và huỷ luôn thao tác kéo. Kéo bằng chuột thì chạy, chạm
        tay thì không — kiểu hỏng rất khó lần ra.
     ⛔ KHÔNG đổ bóng, KHÔNG hiệu ứng, KHÔNG chuyển màu. Bóng mờ phân biệt bằng độ
        mờ, vạch chỉ giờ đi theo đúng lối vạch giờ hiện tại.
     ══════════════════════════════════════════════════════════════════════════════ */
  .lt-cot .lt-the, .lt-chua-gio .lt-the { touch-action:none; }
  /* Thẻ gốc mờ đi trong lúc đang cầm — để mắt biết mình đang cầm cái nào. */
  .lt-the.lt-dang-cam { opacity:.3; }
  body.lt-dang-keo { user-select:none; cursor:grabbing; }
  /* Bóng mờ bám con trỏ. Nó mang luôn cả lớp .lt-the và lớp màu của thẻ gốc nên
     không phải khai lại một bộ kiểu nữa — luật này chỉ đổi ba thứ.
     ⛔ pointer-events:none là BẮT BUỘC: bóng nằm ngay dưới con trỏ, không cho nó
        "trong suốt với chuột" thì phép dò ô giờ bên dưới luôn chạm phải chính cái
        bóng, và vạch chỉ giờ đứng im một chỗ. */
  .lt-bong { position:fixed; z-index:60; pointer-events:none; opacity:.92; }
  /* Vạch chỉ chỗ sẽ thả — cùng lối với vạch giờ hiện tại, chỉ khác màu. Nó là con
     của .lt-cot nên tự trôi theo lưới lúc cuộn, khỏi phải tính lại. */
  .lt-vach-tha { position:absolute; left:0; right:0; height:0; z-index:6;
      border-top:2px solid var(--muc); pointer-events:none; }
  .lt-vach-tha::after { content:attr(data-gio); position:absolute; left:2px; top:-15px;
      background:var(--muc); color:#fff; font-size:10.5px; line-height:1.45;
      padding:0 5px; border-radius:var(--r-sm); font-variant-numeric:tabular-nums; }

  /* ══════════════════════════════════════════════════════════════════════════
     ⛔⛔ CHẾ ĐỘ "NGÀY" LÀ LƯỚI THÁNG. ĐỌC HẾT KHỐI NÀY TRƯỚC KHI SỬA.
     ──────────────────────────────────────────────────────────────────────────
     Cô Quỳnh 21/08/2026 (chiều), sau khi xem ảnh: *"nút tháng chuyển giao diện
     thành của ngày tức là tháng là ngày lấy y hệt thiết kế đó chứ tôi có bảo xoá
     thiết kế đâu"* — và *"ý tôi lúc đó là chuyển tháng sang thành thiết kế của
     ngày"*.
     Nghĩa là: BỎ CÁI NHÃN "Tháng", GIỮ NGUYÊN CÁI LƯỚI. Nút mang tên "Ngày" nhưng
     bên trong vẽ đúng tấm lịch tháng 7 cột × 6 hàng của bản cũ.

     Sáng cùng ngày đã hiểu nhầm câu *"chuyển giao diện của ngày về giống giao diện
     của tháng và bỏ tháng đi"* thành "vứt lưới tháng, dựng lối thẻ" và bị bác hai
     lần liền. Toàn bộ luật dưới đây là bản CHÉP NGUYÊN VĂN từ commit 13ef6d3 —
     bản cuối cùng còn chế độ Tháng.
     ⛔ Đừng "cải tiến" một dòng nào ở đây. Cô Quỳnh nói: *"đừng làm sai 1 tí cọng
        nào nha sai tôi bắt bạn sửa ngay đó"*. Muốn đổi thì hỏi trước.
     ══════════════════════════════════════════════════════════════════════════ */
  .lt-thang { display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); }
  /* Ô ngày cao theo màn: màn 27" thì mỗi ô cao hơn nên chứa được nhiều ca hơn mà
     không phải bấm "+N ca". Có trần 168px để lịch tháng không dài quá một màn. */
  .lt-thang .lt-o-ngay { border-left:1px solid var(--vien); border-top:1px solid var(--vien);
      min-height:clamp(96px, 12vh, 168px); padding:5px 7px; }
  /* ⛔ Ngày của tháng khác KHÔNG tô nền xám (cô Quỳnh 14/08/2026). Chỉ làm mờ con số
     là đủ phân biệt — mảng xám cắt lưới thành từng khối trông rất gợn. */
  .lt-thang .lt-o-ngay.ngoai { background:transparent; }
  .lt-thang .lt-o-ngay.ngoai .lt-sn { opacity:.45; }
  .lt-thang .lt-o-ngay .lt-sn { font-size:12px; font-weight:600; text-align:right;
      color:var(--mo); margin-bottom:2px; }
  .lt-thang .lt-o-ngay.homnay .lt-sn { color:var(--muc); box-shadow:inset 0 0 0 1.5px var(--muc);
      border-radius:var(--r-sm); min-width:20px; height:19px; line-height:19px; text-align:center;
      padding:0 3px; margin-left:auto; }
  .lt-thang .lt-o-ngay.dangxem .lt-sn { color:#fff; background:var(--muc); box-shadow:none;
      border-radius:var(--r-sm); min-width:20px; height:19px; line-height:19px; text-align:center;
      padding:0 3px; margin-left:auto; }
  .lt-thang .lt-o-ngay.dangxem { background:var(--xanh-nhat); }
  /* ⛔⛔ `width:100%` VÀ `box-sizing:border-box` LÀ BẮT BUỘC — đo ngày 21/08/2026.
     `.lt-the` là thẻ <button>. Button KHÔNG co theo ô chứa nó như <div>: nó luôn tự
     rộng bằng nội dung bên trong. Nên trong ô ngày hẹp (cột 135px trên màn 1.500px),
     thẻ "13:00 [Xem thử] Hoàng Thu Trang" rộng thành 190px và ĐÈ SANG CỘT BÊN CẠNH —
     chụp màn thấy rõ nền màu và chữ bị đường kẻ cột cắt ngang.
     Hai dòng `overflow:hidden; text-overflow:ellipsis` ở `.lt-the b` / `.lt-the span`
     KHÔNG cứu được: chúng chỉ cắt khi cha đã bị chặn bề ngang, mà ở đây cha nở ra
     theo con nên chẳng có gì để cắt.
     ⛔ Thiếu `box-sizing:border-box` thì `width:100%` tính theo phần ruột rồi CỘNG
        thêm 14px padding — vẫn tràn, chỉ tràn ít hơn nên khó thấy.
     ⛔ Chỉ bó trong `.lt-thang`. Ở lưới giờ (chế độ Tuần) thẻ được đặt bằng toạ độ
        tuyệt đối kèm `width` inline, thêm luật này vào là đè mất phép chia làn. */
  .lt-thang .lt-the { position:static; display:block; margin-bottom:2px; padding:2px 7px;
      width:100%; box-sizing:border-box; }
  /* ⛔ PHẢI CÓ DÒNG NÀY. Luật ngay trên viết padding gộp và nằm SAU .lt-the.xong
     trong file, độ ưu tiên lại BẰNG NHAU (đều hai lớp) → nó đè mất phần chừa chỗ cho
     gạch trái, và trong lịch tháng chữ sẽ nằm đè lên vạch. Luật này ba lớp nên thắng. */
  .lt-thang .lt-the.xong { padding-left:10px; }
  /* ⛔ 21/08/2026 — đây nay là <button> chứ không phải <div> (bấm vào bung bảng đủ
     ca của ngày). Phải tự đặt lại nền, viền, phông — không thì trình duyệt vẽ nó
     thành cái nút xám mặc định giữa ô lịch. */
  .lt-them-nua { display:block; width:100%; text-align:left; font:inherit;
    background:none; border:0; cursor:pointer; }
  .lt-them-nua:hover { text-decoration:underline; }
  .lt-them-nua { font-size:10.5px; color:var(--mo); padding:1px 3px; }
  /* ══════════════════════════════════════════════════════════════════════════
     CHẾ ĐỘ NGÀY — MỘT NGÀY, TRỤC GIỜ KẺ DỌC. Cô Quỳnh 21/08/2026 (chiều muộn).
     ──────────────────────────────────────────────────────────────────────────
     *"thay vì ở trên ghi thứ thì thay vào đó chuyển thành giờ… và ở dưới các block
     sẽ chia rõ về từng giờ có khung vuông rồi. Để giờ cái kẻ dọc bảng á. Nút ngày
     thì có nghĩa là phải rõ ngày hôm đó có những gì vào giờ nào chứ ko phải thiết
     kế như tuần thế này."*

     Nên: cột trái là GIỜ (kẻ dọc), mỗi giờ MỘT HÀNG có khung, trong hàng là các ca
     của giờ ấy xếp thành ô vuông cạnh nhau — đúng câu cô nói hôm trước: *"có thời
     gian chia cột và có nhiều ô khung vuông chia ra trong khung giờ đó"*.

     ⛔ KHÁC HẲN lưới giờ của chế độ TUẦN (`.lt-cot`): ở đó thẻ được đặt bằng toạ độ
        tuyệt đối theo phút, cao thấp theo độ dài ca. Ở đây mỗi giờ là một Ô THẬT và
        ô tự cao theo số ca — nhờ vậy giờ nào đông thì nhìn ra ngay, và 12h–17h trống
        thì chỉ chiếm một dòng mảnh chứ không ngốn nửa màn.
     ⛔ Chip rộng CỐ ĐỊNH 236px, không chia đều theo số ca. Chia đều thì giờ có 1 em
        chip dài hết màn, giờ có 6 em chip hẹp 140px — cùng một thứ mà mỗi chỗ một cỡ.
     ══════════════════════════════════════════════════════════════════════════ */
  .lt-ngay-gio { display:grid; grid-template-columns:64px minmax(0,1fr); }
  .lt-ng-dau { border-bottom:1px solid var(--vien); padding:9px 10px;
      font-size:12.5px; font-weight:600; display:flex; align-items:baseline; gap:8px; }
  .lt-ng-dau-gio { justify-content:flex-end; color:var(--mo); font-weight:400;
      font-size:11px; }
  .lt-ng-nay { font-size:11px; font-weight:600; color:var(--muc);
      border:1px solid var(--muc); border-radius:var(--r-sm); padding:0 5px; }
  .lt-ng-dem { margin-left:auto; font-weight:400; color:var(--mo);
      font-variant-numeric:tabular-nums; }
  .lt-ng-gio { border-top:1px solid var(--vien); padding:7px 8px 0 0; text-align:right;
      font-size:11.5px; line-height:1.35; color:var(--mo); font-variant-numeric:tabular-nums; }
  /* ⛔ `border-left` chính là cái "kẻ dọc" cô Quỳnh nói — nó chạy suốt từ trên xuống
     dưới và tách cột giờ khỏi phần ca. Bỏ nó là bảng mất trục. */
  .lt-ng-o { border-top:1px solid var(--vien); border-left:1px solid var(--vien);
      min-height:46px; padding:5px 7px; display:flex; flex-wrap:wrap; gap:4px;
      align-content:flex-start; }
  .lt-ng-o.trong { cursor:pointer; }
  .lt-ng-o .lt-the { position:static; display:block; width:236px; max-width:100%;
      box-sizing:border-box; margin:0; padding:3px 8px; }
  .lt-ng-o .lt-the.xong { padding-left:12px; }
  .lt-ng-them { align-self:center; font:inherit; font-size:11.5px; color:var(--mo);
      background:none; border:0; padding:2px 6px; cursor:pointer; }
  .lt-ng-them:hover { text-decoration:underline; }
  /* ══════════════════════════════════════════════════════════════════════════
     CHẾ ĐỘ TUẦN — CÙNG MỘT LƯỚI Ô VUÔNG, THÊM 7 CỘT THỨ
     ──────────────────────────────────────────────────────────────────────────
     Cô Quỳnh 21/08/2026: *"thiết kế cái nút tuần giống nút tháng là hợp hơn á như
     vừa nãy nhưng thêm giờ bên trái á vì tuần cx chia thứ rồi chỉ cần thêm giờ
     thôi"*.
     Nên Tuần và Ngày nay là MỘT công thức, khác đúng một chỗ: Ngày có 1 cột nội
     dung, Tuần có 7. Mỗi ô là một cặp (thứ × khung giờ).
     ⛔ Dùng chung `.lt-ng-gio` cho cột giờ — hai chế độ phải khớp nhau từng điểm
        ảnh, tách ra hai luật là sớm muộn cũng lệch.
     ⛔ Ô hẹp (màn 1.500px chia 7 còn ~120px) nên chip phải `width:100%`, không
        giữ 236px như chế độ Ngày — giữ là tràn sang cột bên cạnh. */
  .lt-tuan-o { display:grid; grid-template-columns:64px repeat(7, minmax(0,1fr)); }
  .lt-tu-dau { border-bottom:1px solid var(--vien); border-left:1px solid var(--vien);
      padding:7px 8px; text-align:center; }
  .lt-tu-dau .lt-thu { font-size:11px; font-weight:600; color:var(--mo);
 }
  .lt-tu-dau .lt-sn { font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; }
  /* ⛔⛔ HAI DẤU KHÁC NHAU — NỀN ĐẶC = NGÀY ĐANG XEM, VIỀN MẢNH = HÔM NAY.
     Đây là quy ước của cả app, xem `.lt-mini-luoi button.homnay/.dangxem` và
     `.lt-dau-o.homnay/.dangxem .lt-sn`.
     ⛔ SỬA 22/08/2026 — chỗ này TỪNG LÀM NGƯỢC: hôm nay được tô NỀN ĐẶC, còn ngày
        đang xem thì không có luật nào cả. Cộng với việc dải cột không gắn lớp
        `dangxem` (xem `lttVeTuanO`), thành ra bấm ngày 21 mà ngày 22 vẫn hiện như
        thể đang được chọn — đúng lỗi cô Quỳnh báo.
     ⛔ Chú thích cũ ở đây ghi "giống hệt lịch nhỏ ở cột trái" — SAI SỰ THẬT, nó làm
        ngược hẳn lịch nhỏ. Đã sửa lại lời cho khỏi lừa người đọc sau.
     ⛔ Phần hình khối (min-width/height/line-height/padding) để CHUNG một luật cho
        hai lớp: tách đôi thì lần sau ai sửa một bên là con số nhảy chỗ đúng lúc đổi
        ngày. Không tô nền cả cột (mảng màu dọc cắt lưới trông rất gợn). */
  .lt-tu-dau.homnay .lt-sn, .lt-tu-dau.dangxem .lt-sn { display:inline-block;
      min-width:22px; height:21px; line-height:21px; border-radius:var(--r-sm); padding:0 4px; }
  .lt-tu-dau.homnay .lt-sn { box-shadow:inset 0 0 0 1.5px var(--muc); color:var(--muc); }
  /* `box-shadow:none` là cố ý: ngày đang xem TRÙNG hôm nay thì chỉ còn ô đặc, không
     kèm viền — chép đúng cách `.lt-dau-o.dangxem .lt-sn` đang làm. */
  .lt-tu-dau.dangxem .lt-sn { background:var(--muc); color:#fff; box-shadow:none; }
  .lt-tu-o { border-top:1px solid var(--vien); border-left:1px solid var(--vien);
      min-height:44px; padding:4px 5px; display:flex; flex-direction:column; gap:3px; }
  .lt-tu-o .lt-the { position:static; display:block; width:100%; box-sizing:border-box;
      margin:0; padding:2px 6px; }
  .lt-tu-o .lt-the.xong { padding-left:10px; }
  /* Ô đang nhắm tới trong lúc kéo thả — thay cho vạch ngang của lưới toạ độ cũ.
     ⛔ Dùng inset shadow chứ không dùng border: border làm ô nhích đi 2px và cả
        hàng giật một cái mỗi lần rê qua. */
  .lt-tu-o.lt-o-dich, .lt-ng-o.lt-o-dich {
      box-shadow:inset 0 0 0 2px var(--muc); background:var(--xanh-nhat); }
  /* ── Chế độ DANH SÁCH ── */
  .lt-ds-ngay { border-bottom:1px solid var(--vien); }
  .lt-ds-ngay:last-child { border-bottom:none; }
  .lt-ds-dau { position:sticky; top:0; z-index:3; background:var(--the);
      border-bottom:1px solid var(--vien); padding:7px 12px; font-size:13px;
      display:flex; align-items:baseline; gap:9px; }
  .lt-ds-dau b { font-weight:700; }
  .lt-ds-ngay.homnay .lt-ds-dau b { color:var(--muc); }
  .lt-ds-ngay.dangxem .lt-ds-dau { background:var(--xanh-nhat); }
  .lt-ds-dem { margin-left:auto; font-size:11.5px; color:var(--mo);
      font-variant-numeric:tabular-nums; }
  /* Mỗi ca MỘT DÒNG, không cắt chữ, không gộp. Nền màu nhạt theo người phụ trách —
     cùng bảng màu với thẻ trên lưới, để hai màn đọc như nhau. */
  .lt-ds-hang { display:flex; align-items:center; gap:10px; width:100%;
      border:none; border-bottom:1px solid var(--vien); background:transparent;
      font-family:inherit; font-size:12.5px; text-align:left; cursor:pointer;
      padding:7px 12px; color:var(--chu); }
  .lt-ds-hang:last-child { border-bottom:none; }
  .lt-ds-hang:hover { background:var(--nen2); }
  .lt-ds-gio { flex:none; width:52px; font-weight:700;
      font-variant-numeric:tabular-nums; }
  /* Vạch màu bên trái theo người phụ trách — nhận ra người ngay mà không tô cả dòng
     thành khối màu (hai chục dòng màu đặc liền nhau là nhức mắt). */
  .lt-ds-hang.ltt-mau1 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c1); padding-left:9px; }
  .lt-ds-hang.ltt-mau2 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c2); padding-left:9px; }
  .lt-ds-hang.ltt-mau3 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c3); padding-left:9px; }
  .lt-ds-hang.ltt-mau4 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c4); padding-left:9px; }
  .lt-ds-hang.ltt-mau5 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c5); padding-left:9px; }
  .lt-ds-hang.ltt-mau6 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c6); padding-left:9px; }
  .lt-ds-hang.ltt-mau0 .lt-ds-gio { box-shadow:inset 3px 0 0 var(--ltt-c0); padding-left:9px; }
  .lt-ds-ten { flex:1 1 auto; min-width:0; font-weight:600; overflow:hidden;
      text-overflow:ellipsis; white-space:nowrap; }
  .lt-ds-hang .lt-cs { flex:none; font-style:normal; font-size:11.5px; font-weight:600;
      letter-spacing:normal; padding:0 4px; border-radius:var(--r-sm);
      background:var(--ltt-c0); color:var(--ltt-n0); }
  .lt-ds-hang .lt-cs-trong { background:transparent; color:var(--mo);
      border:1px dashed var(--vien); font-weight:600; }
  .lt-ds-nguoi { flex:0 0 148px; color:var(--mo); overflow:hidden;
      text-overflow:ellipsis; white-space:nowrap; }
  .lt-ds-sdt { flex:none; color:var(--mo); font-variant-numeric:tabular-nums; }
  /* Đã có điểm test: cùng dấu với thẻ trên lưới. */
  .lt-ds-hang.xong .lt-ds-ten::after { content:" ✓"; color:var(--o-tot); font-weight:700; }
  @media (max-width: 860px) {
    .lt-ds-nguoi, .lt-ds-sdt { display:none; }
  }

  .lt-trong { padding:30px; text-align:center; color:var(--mo); }
  /* Màn hẹp: giấu cột trái, lịch chiếm hết bề ngang. */
  @media (max-width: 900px) {
    .lt-man { flex-direction:column; }
    .lt-ben { width:100%; display:flex; gap:10px; }
    .lt-mini { flex:1; margin-bottom:0; }
    .lt-nguoi { flex:1; }
    /* Màn hẹp thì các khối nằm ngang hàng — quãng cách dọc thành thừa và gây lệch. */
    .lt-coso { margin-top:0; }
  }

  /* ══════════════════════════════════════════════════════════════════════════════
     📅 LỊCH GIÁO VIÊN (.lgv-*) — cô Quỳnh 30/08/2026.  LƯỢT 1 = CHỈ NHÌN.
     ──────────────────────────────────────────────────────────────────────────────
     ⛔⛔ HỌ LỚP LÀ `.lgv-`, TUYỆT ĐỐI KHÔNG GIÀNH `.lt-`. Tiền tố `lt` đã có HAI
        chủ — "Lịch thi định kỳ" (giáo vụ) và "Lịch test" (tuyển sinh) — và chính chỗ
        chồng tên ấy từng làm cô Quỳnh mất gần hai tiếng ngày 14/08/2026: bấm Lịch
        test thì hiện ra Lịch thi. Xem `kiem-thu/thu-trung-ten-ham.js`.

     NẾP DỰNG chép từ màn Lịch test (`.lt-*`) vì màn ấy đã đi hết đường: đúng lối
     Google Calendar, đã đo tương phản bằng máy, đã xử xong điện thoại. Chép NẾP chứ
     không chép TÊN.

     ⛔ KHÔNG `:has()` trong khối này (luật của dự án — xem cảnh báo ở dòng ~1070).
     ⛔ Không emoji, không đổ bóng, không chuyển màu, không `font-weight:700`, không
        `` kèm `letter-spacing` ở chữ thường. Ba thứ sau là
        cái làm "lộ rõ ui AI" mà cô Quỳnh đã chê NĂM lần.
     ⛔ Mọi màu đều phải có bản `body.toi`. Thiếu là nền tối đọc ra chữ tối trên nền
        tối — hỏng im lặng, không lỗi nào báo.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ══════════════════════════════════════════════════════════════════════════════
     BA MÀU TRẠNG THÁI Ô — cô Quỳnh CHỐT LẠI tối 30/08/2026 (bảng cũ đã BỎ)
     ──────────────────────────────────────────────────────────────────────────────
       🔵 XANH = buổi dạy BÌNH THƯỜNG               (lượt 1 mọi ô đều màu này)
       🔴 ĐỎ   = ĐANG THIẾU NGƯỜI DẠY               (lượt sau) — màu BÁO ĐỘNG
       🟡 VÀNG = ĐÃ CÓ NGƯỜI DẠY THAY, kèm tên      (lượt sau)

     ⛔⛔ ĐỪNG ĐỔI NGƯỢC LẠI. Bản nháp cũ để ĐỎ làm màu của buổi bình thường; cô
        Quỳnh xem hình minh hoạ rồi bác đi, và lý do cô nêu là lý do đúng: *lịch
        chạy êm thì cả màn xanh, chỗ nào đỏ là chỗ phải làm gấp*. Để cả màn đỏ
        quanh năm thì màu đỏ mất sạch ý nghĩa cảnh báo — nhìn mãi thành quen, tới
        lúc thiếu người dạy thật thì không ai giật mình nữa.
     ⛔ TÊN BIẾN LÀ TÊN MÀU (`--lgv-do-*` là hồng/đỏ), CÒN NGHĨA THÌ NẰM Ở BẢNG
        `LGV_TRANG_THAI` trong mã. Đừng gán nghĩa vào tên biến màu, và đừng đổi
        nghĩa bằng cách đổi giá trị màu ở đây — đổi ở đây là đổi luôn cả ba chỗ
        (ô lịch · chú giải · nhãn trong hộp) theo hai hướng khác nhau.

     ⛔ SÁU CẶP MÀU DƯỚI ĐÂY KHÔNG PHẢI CHỌN BẰNG MẮT — mỗi cặp đều đo trước rồi mới
        ghi vào đây. Hai cặp đầu mượn của bảng thẻ Lịch test (`--ltt-n3/c3` đỏ hồng ·
        `--ltt-n4/c4` cam đất), đã đo bằng `kiem-thu/thu-mau-the-lich.js`: 5,15 và 5,22
        lần ở nền sáng, 6,44 và 6,45 ở nền tối.
     ⛔ CẶP THỨ BA LÀ XANH LÁ, KHÔNG PHẢI XANH DƯƠNG — cô Quỳnh đổi 30/08/2026 sau khi
        xem ảnh chụp thật: *"đổi màu xanh nước biển thành màu xanh lá cho tôi"*. Nên nó
        KHÔNG còn mượn `--ltt-n1/c1` nữa mà dò riêng, cùng cách đo: nền sáng 5,44 lần,
        nền tối 6,38 — ngang tầm hai cặp kia, đều vượt chuẩn đọc 4,5.
        Xanh lá này cố ý KHÁC hai chấm giáo viên xanh lá (`--lgv-g5` #006E22 lá đậm,
        `--lgv-g6` #009C7E lá ngả lam) và khác teal MyPAS `--xanh` #14A0A0 của thanh
        điều hướng — ba thứ đứng cạnh nhau trong cùng một ô thì phải phân biệt được.
        Khai lại thành tên RIÊNG chứ không `var(--ltt-…)` vì hai màn nói hai chuyện
        khác nhau: bên kia màu là NGƯỜI PHỤ TRÁCH, bên này màu là TRẠNG THÁI. Dùng
        chung biến thì hôm nào Lịch test đổi bảng màu là nghĩa của lịch này đổi theo.
     ⛔ ĐỪNG TÔ ĐỎ TƯƠI. "Đỏ" ở đây là nền HỒNG NHẠT + chữ đỏ sẫm, không phải mảng
        đỏ đặc: một tháng có tới vài trăm ô, tô đặc là cả màn hình bốc cháy và chẳng
        còn gì "nổi bật" nữa — đúng lúc lượt sau cần màu vàng/xanh nổi lên thì hết chỗ.
     ⛔ Ba màu này KHÔNG được là thứ duy nhất mang tin: mỗi ô luôn có chữ trạng thái
        ở hộp thông tin, để người mù màu vẫn đọc được. */
  :root {
    --lgv-do-n:#FFD3D2;   --lgv-do-c:#943D43;    /* thiếu người dạy      5,15 */
    --lgv-vang-n:#F4DCBA; --lgv-vang-c:#725514;  /* đã có người thay     5,22 */
    --lgv-xanh-n:#C9E9D2; --lgv-xanh-c:#16653A;  /* dạy bình thường      5,44 */
  }
  body.toi {
    --lgv-do-n:#5B3636;   --lgv-do-c:#FEBBBB;    /* 6,44 */
    --lgv-vang-n:#4C3E25; --lgv-vang-c:#E4C89C;  /* 6,45 */
    --lgv-xanh-n:#2A4A35; --lgv-xanh-c:#A8DCB6;  /* 6,38 */
  }
  /* ══════════════════════════════════════════════════════════════════════════════
     CHẤM MÀU GIÁO VIÊN — 11 sắc + 1 xám, DỰNG BẰNG MÁY chứ không chọn bằng mắt
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ ĐỪNG LẤY BA MÀU TRẠNG THÁI Ở TRÊN LÀM CHẤM GIÁO VIÊN. Một ô chỉ được nói MỘT
        thứ bằng màu; hai bảng màu chồng nhau trên cùng một ô là người nhìn phải đoán
        cái nào nói gì.
     ⛔ Trung tâm đang có 34 giáo viên mà bảng chỉ có 11 sắc — SỰ THẬT LÀ MÀU SẼ LẶP.
        Nên chấm chỉ là thứ giúp mắt LƯỚT nhanh trong một ngày, còn thứ định danh
        vẫn là CÁI TÊN nằm ngay cạnh. Đừng bỏ tên đi để "cho gọn" rồi trông cậy vào
        màu — bỏ tên là hai cô cùng sắc thành một người.
     ⛔ `--lgv-g12` LÀ XÁM, và nó DÀNH RIÊNG cho lớp chưa khai giáo viên (hằng
        `LGV_SAC_TRONG` trong mã). Đừng phát nó cho người thứ 12.

     ⛔⛔ MƯỜI MỘT SẮC KIA ĐẶT CÁCH ĐỀU 32,7° TRÊN VÒNG MÀU LCh, XEN KẼ HAI BẬC SÁNG.
        Bản chọn tay đầu tiên có hai sắc nâu (#8A5A10 và #96501B) chỉ cách nhau ΔE
        12,3 — hai người khác nhau mà chấm nhìn như một. Xen kẽ bậc sáng là cách gỡ:
        hai sắc cạnh nhau khác cả GÓC MÀU lẫn ĐỘ SÁNG, nên không phải chỉ dựa vào
        mắt phân biệt màu.
     ⛔ Chấm chỉ 10×10px nên chuẩn phải theo là tương phản của THÀNH PHẦN GIAO DIỆN
        (3 lần), không phải chuẩn CHỮ (4,5). Đo được:
          nền sáng: ΔE nhỏ nhất 26,0 · tương phản thấp nhất 3,32 trên nền thẻ trắng
          nền tối : ΔE nhỏ nhất 21,8 · tương phản thấp nhất 7,65 trên nền thẻ #1B1F23
        `kiem-thu/thu-lich-gv-man.js` ĐO LẠI cả 24 con số ấy mỗi lần chạy — đổi số ở
        đây thì chạy lại bài ấy, đừng sửa bằng cảm tính. */
  :root {
    --lgv-g1:#AE2A4E; --lgv-g2:#CE6A48; --lgv-g3:#825500; --lgv-g4:#818D2A;
    --lgv-g5:#006E22; --lgv-g6:#009C7E; --lgv-g7:#007289; --lgv-g8:#0096D5;
    --lgv-g9:#0062BA; --lgv-g10:#9576CF; --lgv-g11:#9F3380; --lgv-g12:#6E6E75;
  }
  /* ⛔ Nền tối dùng BƯỚC MÀU RIÊNG, không phải lấy màu sáng rồi làm mờ đi — đúng
     cách bảng thẻ Lịch test đã làm và đã đo. */
  body.toi {
    --lgv-g1:#F794A3; --lgv-g2:#FFBAA0; --lgv-g3:#D6A969; --lgv-g4:#CCD18F;
    --lgv-g5:#81BF83; --lgv-g6:#7DDDC6; --lgv-g7:#00C3D2; --lgv-g8:#78D7FF;
    --lgv-g9:#82B3F9; --lgv-g10:#D9C1FF; --lgv-g11:#E797CB; --lgv-g12:#B4B4BE;
  }

  /* ⭐⭐ CHIỀU CAO CHỐT Ở ĐÂY, KHÔNG CHỐT Ở TỪNG CỘT — cô Quỳnh 31/08/2026, LẦN THỨ HAI:
       *"cái thanh lọc của công cụ giáo viên ở bên trái ở dưới ô lọc giáo viên lộ ra
        cái chỗ trắng xoá chiếm diện tích ko đẹp"*

     Lần chữa thứ nhất cho cột trái ĐÚNG công thức của khung lịch (`100vh − 258px`)
     nên mọi phép soi chuỗi đều xanh — mà màn vẫn hở. Vì HAI CỘT KHÔNG CÙNG MỐC BẮT
     ĐẦU: cột trái bắt đầu ngay đỉnh `.lgv-man`, còn khung lịch nằm dưới `.lgv-top`
     và dải nhắc `.lgv-bao`. Trần bằng nhau + mốc lệch nhau = cột trái hụt.

     ĐO THẬT 31/08/2026, Playwright, kho 60 lớp · 40 giáo viên (con số đo được, không
     phải nhẩm):
         1366×768   đỉnh .lgv-man 101px · hở dưới cột lọc 108px so đáy khung,
                    135px so đáy cột phải
         1400×900   y hệt: 108px / 135px
         1920×1080  đỉnh 104px
     Cột lọc cần 1.346px mà chỉ nhìn được 510px, nên nó LUÔN chạm trần — mảng trắng
     hiện ra ở mọi cỡ màn, không phải chuyện hiếm.

     ⛔ SỐ 101 LÀ SỐ ĐO ĐƯỢC, ĐỪNG SUY RA BẰNG PHÉP LOẠI SUY. Một lượt soạn vá trước
        đã suy từ hằng 214px của Lịch test ra "177px" — lệch 76px, đủ để cả khối lịch
        thò khỏi đáy màn mà mọi phép soi chuỗi vẫn xanh.
     ⛔ Sai vài điểm ảnh ở con số này chỉ làm CẢ KHỐI nhích lên xuống, KHÔNG bao giờ
        tách hai cột ra nữa — đó mới là lý do đổi cách chặn. (Đỉnh đo được 101px ở
        màn 768 và 104px ở màn 1080; chênh 3px, không đáng kể.)
     ⛔ `align-items:stretch` là nửa còn lại của bản vá: nó kéo cột trái cao BẰNG dòng
        flex. Thiếu nó thì đặt chiều cao ở đây cũng vô ích.
     ⛔ Điện thoại trả `height` về `auto` ở `@media` bên dưới — ngăn kéo là
        `position:fixed`, nằm ngoài dòng flex. */
  /* ⛔ 08/09/2026 — CHIỀU CAO NAY ĐO THẬT, hằng 101px chỉ còn là ĐƯỜNG LUI.
     Boss: *"nó đang bị hở ra 1 khoảng trống ở dưới cùng tôi muốn cái bảng phải full
     hết màn"*. Hằng 101px chốt đúng phần `.lgv-man`, nhưng dòng chú thích
     `.cts-chan` nằm NGOÀI khối ấy nên đội thêm 24px — đo 1366px: khối kết thúc ở
     834, chú thích 842→858, tức thò khỏi đáy màn (844) 14px và trang cuộn được một
     đoạn cụt. `lgvDoTran` trừ luôn cả phần ngoài ấy lẫn thanh đáy. */
  .lgv-man { display:flex; gap:18px; align-items:stretch;
      height:var(--lgv-man-cao, calc(100vh - 101px - var(--dnc-du, 0px))); }
  /* Cột trái co giãn theo bề ngang màn, y như Lịch test.
     ══════════════════════════════════════════════════════════════════════════════
     ⭐⭐ CỘT TRÁI CUỘN RIÊNG, CAO BẰNG KHUNG LỊCH — cô Quỳnh 31/08/2026:
       *"tôi kéo xuống bên dưới thấy công cụ lịch giáo viên đang bị thừa ra nguyên
        1 khoảng trắng trông bị thừa ấy"*

     Đo thật: khung lịch cao 510px (`.lgv-khung` tự chặn theo chiều cao màn), còn
     cột trái thì KHÔNG chặn gì — lịch nhỏ + ô cơ sở + danh sách giáo viên (tối đa
     420px) + danh sách lớp (thêm 420px nữa) cộng lại vượt 1.200px trên máy cô, vì
     trung tâm có 126 lớp. Cột trái dài gấp đôi cột phải, và phần thò ra dưới đáy
     lịch là một mảng trắng mênh mông bên phải — đúng cái cô nhìn thấy.

     ⛔ ĐỪNG chữa bằng cách hạ `max-height` của hai danh sách: hạ đủ để hết trắng
        thì danh sách chỉ còn nhìn được 4–5 dòng, mà đó là chỗ người ta lọc lớp.
     ⛔ VÀ ĐỪNG TRẢ `max-height` VỀ ĐÂY. Bản 31/08 sáng chặn đúng ở dòng này bằng
        `100vh − 258px − --dnc-du` — cùng công thức với khung lịch — mà vẫn hở 108px,
        vì hai cột khác mốc bắt đầu. Chiều cao nay do `.lgv-man` chốt
        (`height` + `align-items:stretch`), cột này chỉ việc nhận và cuộn phần thừa.
        Đặt lại trần ở đây là chặn sớm hơn dòng flex và mảng trắng quay lại y nguyên.
     ⛔ `min-height:0` bắt buộc cho mục con flex: thiếu nó thì cột không co xuống dưới
        cỡ nội dung (1.346px đo thật), `overflow-y:auto` mất tác dụng và cột trái đẩy
        dài cả khối.
     ⛔ Ngăn kéo điện thoại có luật riêng ở `@media` bên dưới (`position:fixed`,
        cao trọn màn) — luật này chỉ áp cho máy tính. */
  .lgv-ben { flex:none; width:clamp(214px, 15vw, 268px); min-height:0;
      overflow-y:auto; overflow-x:hidden; padding-right:2px; }
  /* ⭐ HAI THỨ CHỈ DÀNH CHO ĐIỆN THOẠI, MẶC ĐỊNH ẨN — nút ba sọc và tấm mờ sau ngăn
     kéo. ⛔ Ẩn Ở ĐÂY (ngoài mọi @media), không thì máy tính mọc thêm hai thứ lạ. */
  .lgv-ham, .lgv-mo, .lgv-dong-ngan { display:none; }
  /* ⛔ CỘT PHẢI PHẢI LÀ MỘT CỘT FLEX. `.lgv-man` nay chốt chiều cao, nên khung lịch
     phải TỰ ĂN HẾT phần còn lại sau thanh công cụ, dải nhắc và dải "lớp hỏng" —
     y lối `.lt-chinh` bên Lịch test. Để nguyên khối thường thì khung lại tự đo theo
     trần riêng và hai cột lệch nhau lần nữa.
     ⛔ `min-height:0` bắt buộc, cùng lý do như `.lgv-ben`.
     ⛔ Ba đứa KHÔNG phải khung lịch phải `flex:none`. Thanh công cụ hay dải nhắc bị
        bóp lại là chữ chồng lên nhau — trông y hệt app hỏng mà không lỗi nào báo.
        `.lgv-hong` (dải "lớp chưa hiện trên lịch") CÓ THẬT trên sổ của cô Quỳnh:
        lớp `PV::5z15` thiếu giờ kết thúc, nên dải ấy chiếm 27px kể cả lề. */
  .lgv-chinh { flex:1; min-width:0; display:flex; flex-direction:column; min-height:0; }
  .lgv-chinh > .lgv-top, .lgv-chinh > .lgv-bao, .lgv-chinh > .lgv-hong { flex:none; }

  /* ── Cột trái ── */
  .lgv-mini { border:1px solid var(--vien); border-radius:var(--r-md); background:var(--the);
      padding:9px 10px 11px; margin-bottom:12px; }
  .lgv-mini-dau { display:flex; align-items:center; justify-content:space-between;
      margin-bottom:6px; }
  .lgv-mini-ten { font-size:12.5px; font-weight:700; }
  .lgv-mini-dau button { border:none; background:transparent; color:var(--mo);
      font-family:inherit; font-size:15px; line-height:1; padding:2px 6px; cursor:pointer;
      border-radius:var(--r-sm); }
  .lgv-mini-dau button:hover { background:var(--nen2); color:var(--chu); }
  .lgv-mini-luoi { display:grid; grid-template-columns:repeat(7, 1fr); gap:1px; }
  .lgv-mini-luoi span { font-size:11.5px; color:var(--mo); text-align:center; padding:2px 0; }
  /* ⛔⛔ Ô NGÀY LÀ Ô VUÔNG, KHÔNG BAO GIỜ HÌNH TRÒN — cô Quỳnh 21/08/2026 *"bỏ hình
     tròn đi nhìn tởm quá"*. Cả app chỉ có MỘT lối đánh dấu ngày; xem `.lt-mini-luoi
     button` để biết vì sao `border-radius:50%` còn cắt cụt cả box-shadow vẽ sau. */
  .lgv-mini-luoi button { border:none; background:transparent; color:var(--chu);
      font-family:inherit; font-size:12px; padding:0; height:26px; border-radius:var(--r-sm);
      cursor:pointer; font-variant-numeric:tabular-nums; }
  .lgv-mini-luoi button:hover { background:var(--nen2); }
  .lgv-mini-luoi button.ngoai { color:var(--mo); opacity:.55; }
  .lgv-mini-luoi button.co { font-weight:700; }
  /* HAI DẤU KHÁC NHAU, ĐỪNG GỘP: ô ĐẶC = ngày ĐANG XEM (đổi mỗi lần bấm, đây là phản
     hồi) · ô VIỀN = HÔM NAY (mốc cố định). Thiếu dấu "đang xem" thì bấm sang ngày
     khác nhìn như bấm hụt — lỗi đã xảy ra thật ở Lịch test ngày 14/08. */
  .lgv-mini-luoi button.homnay { box-shadow:inset 0 0 0 1.5px var(--muc); font-weight:700; }
  .lgv-mini-luoi button.dangxem { background:var(--muc); color:#fff; font-weight:700; }
  .lgv-mini-luoi button.dangxem:hover { background:var(--xanh-dam); }

  .lgv-tim-khoi { margin-bottom:10px; }
  .lgv-tim { width:100%; box-sizing:border-box; border:1px solid var(--vien);
      border-radius:var(--r-md); padding:7px 11px; font-family:inherit; font-size:13px;
      background:var(--nen-o); color:var(--chu); }
  .lgv-tim:focus { outline:none; border-color:var(--muc); }
  .lgv-tim-dem { font-size:11.5px; color:var(--mo); margin-top:5px; min-height:15px;
      font-variant-numeric:tabular-nums; }
  /* Không tìm thấy ai thì nói bằng MÀU nữa, không chỉ bằng chữ — dòng xám nhỏ rất dễ
     lướt qua, mà đây đúng lúc người ta đang nhìn một danh sách trống và tự hỏi vì sao. */
  .lgv-tim-dem.khong { color:var(--do); }

  .lgv-nguoi { border:1px solid var(--vien); border-radius:var(--r-md); background:var(--the);
      padding:9px 10px; }
  .lgv-nguoi h4 { font-size:12.5px; font-weight:700; color:var(--chu); margin:0 0 7px;
      letter-spacing:normal; }
  .lgv-nguoi label { display:flex; align-items:center; gap:8px; padding:3.5px 0;
      font-size:12.5px; cursor:pointer; }
  /* ⛔⛔ `input[type="checkbox"]`, ĐỪNG BAO GIỜ VIẾT TRỐNG THÀNH `.lgv-nguoi input`.
     Đã hỏng thật ngày 30/08/2026 và chỉ lộ ra khi ĐO TRÊN MÀN: ô TÌM TÊN GIÁO VIÊN
     nằm trong chính khối này, nên luật viết trống bóp nó xuống còn 14×14 điểm ảnh —
     một ô vuông tí xíu. Gõ vào thì chữ tràn ra ngoài, con trỏ nhảy về đầu sau mỗi
     ký tự có dấu, và "Bình" gõ ra thành "nhBì". Không lỗi nào báo; đọc mã thì luật
     này trông hoàn toàn vô hại.
     Đúng họ với cái bẫy đã ghi ở `.lt-nguoi i` bên Lịch test: một luật viết trống
     cho THẺ trong khối lọc, rồi đè trúng thứ chẳng liên quan gì. */
  .lgv-nguoi input[type="checkbox"] { flex:none; width:14px; height:14px;
      accent-color:var(--muc); margin:0; cursor:pointer; }
  .lgv-cham { flex:none; width:10px; height:10px; border-radius:var(--r-sm); display:inline-block; }
  .lgv-nguoi .lgv-ten { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .lgv-nguoi .lgv-dem { font-size:11px; color:var(--mo); font-variant-numeric:tabular-nums; }
  /* ⭐ Tên các lớp của một giáo viên, nằm dưới tên người — Boss ý ⑤ (19/09/2026).
     ⛔ `display:block` để nó xuống dòng riêng: gắn cùng dòng với tên người thì tên
        dài đẩy con số đếm rơi ra ngoài cột.
     ⛔ Cắt một dòng bằng `text-overflow` chứ đừng cho xuống nhiều dòng — cột lọc
        này có thể có hàng trăm giáo viên. */
  .lgv-lop-cua { display:block; font-size:11px; color:var(--mo); line-height:1.35;
                 white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; }
  /* Danh sách giáo viên có thể tới 34 người — cho cuộn riêng, đừng để nó đẩy lịch
     mini ra khỏi màn. */
  .lgv-ds-gv { max-height:min(46vh, 420px); overflow-y:auto; }
  .lgv-nguoi-nut { display:flex; gap:8px; margin:2px 0 6px; }
  .lgv-nguoi-nut button { flex:1; border:1px solid var(--vien); background:var(--the);
      color:var(--chu); font-family:inherit; font-size:11.5px; padding:3px 6px;
      border-radius:var(--r-sm); cursor:pointer; }
  .lgv-nguoi-nut button:hover { background:var(--nen2); }
  /* Khối lọc CƠ SỞ dùng lại y nguyên kiểu khối giáo viên, thêm quãng cách và ô mã ngắn.
     ⛔ Ô mã là span, KHÔNG phải thẻ i — bên Lịch test thẻ i đã bị ép thành ô vuông
        11×11 nên nhét chữ vào là mất chữ. Ở đây `.lgv-cham` mới là ô vuông, nhưng cứ
        giữ đúng nếp cho khỏi lặp lại bẫy cũ. */
  .lgv-coso { margin-bottom:12px; }
  .lgv-coso .lgv-ma { flex:none; min-width:38px; text-align:center; font-size:12px;
      font-weight:600; letter-spacing:normal; padding:1px 5px; border-radius:var(--r-sm);
      border:1px solid var(--vien); background:var(--nen2); color:var(--chu); }

  /* ── Thanh trên ── */
  .lgv-top { display:flex; align-items:center; gap:8px; margin-bottom:10px; flex-wrap:wrap; }
  .lgv-top button { border:1px solid var(--vien); background:var(--the); color:var(--chu);
      font-family:inherit; font-size:12.5px; padding:5px 11px; border-radius:var(--r-md); cursor:pointer; }
  .lgv-top button:hover { background:var(--nen2); }
  .lgv-mui { padding:5px 9px !important; font-size:15px !important; line-height:1; }
  .lgv-tieude { font-size:16px; font-weight:700; margin:0 4px; }
  /* Số buổi đang hiện. ⛔ Bám vào `.lgv-top` cho hẹp lại: chuỗi `.lgv-dem` còn dùng ở
     cột lọc bên trái, khai trần là hai chỗ ăn chung một cỡ chữ rồi lệch nhau lúc sửa. */
  .lgv-top .lgv-dem { font-size:12px; color:var(--mo); font-variant-numeric:tabular-nums; }
  /* Nút gạt "Xem theo" và cụm Ngày/Tuần/Tháng — cùng một lối liền khối như thanh công
     cụ Google Sheets, không phải thẻ tab màu. */
  .lgv-gat, .lgv-che { display:flex; border:1px solid var(--vien); border-radius:var(--r-md);
      overflow:hidden; }
  /* ⛔ `margin-left:auto` NẰM Ở ĐÂY từ 03/09/2026, trước ở `.lgv-gat`. Đây là thứ
     DUY NHẤT đẩy cả nhóm nút bên phải ra mép phải thanh. Cụm "Xem theo" đã bỏ nên
     luật phải dời sang cụm đứng đầu nhóm còn lại, không thì mọi nút dồn về sát
     tiêu đề. `.lgv-gat` giữ nguyên trong bảng kiểu vì các luật khác dùng chung với
     `.lgv-che`, gỡ ra là phải sửa năm dòng cho một việc không ai thấy. */
  .lgv-che { margin-left:auto; }
  .lgv-gat-nhan { display:flex; align-items:center; padding:0 9px; font-size:11.5px;
      color:var(--mo); background:var(--nen2); border-right:1px solid var(--vien); }
  .lgv-gat button, .lgv-che button { border:none; border-right:1px solid var(--vien);
      border-radius:0; padding:5px 12px; }
  .lgv-gat button:last-child, .lgv-che button:last-child { border-right:none; }
  .lgv-gat button.chon, .lgv-che button.chon { background:var(--muc); color:#fff; }
  /* 🔎 Cụm ba nút zoom dùng lại nguyên lớp `.zoom-nut` của bảng dạng sheet (cô Quỳnh
     xin "nút zoom như các công dạng sheet"), chỉ gỡ hai thứ dành cho hàng riêng phía
     trên bảng: cái lề `margin:0 0 6px auto` và cái bóng đổ. Ở đây nó đứng ngang hàng
     với các nút khác trong thanh trên nên không cần đẩy sang phải, cũng không cần
     nổi khối lên.
     ⛔ ĐỪNG viết CSS mới cho ba nút này — trông khác cụm zoom của bảng là cô Quỳnh
        phải học lại một thứ vốn đã quen. */
  .lgv-top .zoom-nut.lgv-zoom { margin:0; box-shadow:none; }
  /* ⛔ 03/09/2026 — CỤM ZOOM PHẢI GIỮ CHỖ Ở LƯỚI THÁNG.
     Cô Quỳnh: *"tôi ấn ngày là cả mấy cái nút bị thay đổi đẩy sang bên phải,
     ấn tháng thì lại qua lại bên trái, tôi muốn nó cố định lại"*.
     Đo được thủ phạm: cụm zoom rộng ĐÚNG 120px và trước đây KHÔNG ĐƯỢC IN RA ở
     lưới Tháng. Nó nằm giữa hàng, nên mỗi lần hiện/mất là sáu nút bên trái nó
     (Lớp · Giáo viên · Ngày · Tuần · Tháng · Giờ đăng ký) trượt đúng 120px.
     ⛔ VẪN KHÔNG BÀY NÚT ở lưới Tháng — lý do cũ còn nguyên giá trị (bấm vào
        không thấy gì đổi vì lưới Tháng không theo trục giờ). Chỉ GIỮ CHỖ.
     ⛔ `visibility:hidden` chứ KHÔNG `display:none`: display:none là mất chỗ,
        tức quay lại đúng lỗi này. Thêm `pointer-events:none` để không bấm trúng
        một nút vô hình, và `aria-hidden` bên HTML để máy đọc màn hình bỏ qua. */
  .lgv-top .zoom-nut.lgv-zoom-trong { visibility:hidden; pointer-events:none; }

  /* ══════════════════════════════════════════════════════════════════════════════
     DẢI "LƯỢT NÀY CHƯA SỬA ĐƯỢC" — bắt buộc, và cố ý đặt ngay trên lưới
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ ĐỪNG GỠ, ĐỪNG THU NHỎ THÀNH CHỮ MỜ. Đây là màn CHỈ NHÌN: người dùng sẽ bấm
        vào ô rồi chờ một cái gì đó mở ra sửa. Không nói thẳng ra thì họ tưởng app
        hỏng. Bày một lựa chọn chưa dùng được còn tệ hơn chưa bày — luật cô Quỳnh
        chốt 29/08/2026 (skill `cong-cu-cho-nguoi-that`).
     Lượt sau có cơ chế xếp người dạy thay thì XOÁ HẲN khối này, đừng để lại lời hứa cũ. */
  .lgv-bao { border:1px solid var(--vien); border-left:3px solid var(--muc);
      border-radius:var(--r-md); background:var(--nen2); color:var(--chu);
      font-size:12.5px; line-height:1.5; padding:8px 12px; margin-bottom:10px; }
  .lgv-bao b { font-weight:600; }
  /* Bảng chú giải ba màu — nằm cùng dải, để người xem biết ô màu nào nghĩa gì mà
     không phải bấm thử. */
  .lgv-chugiai { display:flex; flex-wrap:wrap; gap:12px; margin-top:6px;
      font-size:11.5px; color:var(--mo); align-items:center; }
  .lgv-chugiai span { display:inline-flex; align-items:center; gap:5px; }
  .lgv-chugiai i { width:11px; height:11px; border-radius:var(--r-sm); border:1px solid currentColor;
      font-style:normal; }
  .lgv-cg-do   { background:var(--lgv-do-n);   color:var(--lgv-do-c); }
  .lgv-cg-vang { background:var(--lgv-vang-n); color:var(--lgv-vang-c); }
  .lgv-cg-xanh { background:var(--lgv-xanh-n); color:var(--lgv-xanh-c); }
  /* 🚦 Ô màu trong CỘT LỌC TRẠNG THÁI ở thanh bên. Mượn đúng ba sắc `.lgv-cg-*`
     ngay trên, nhưng phải TỰ cấp kích thước và viền: `.lgv-chugiai i` mới là chỗ
     cho hai thứ ấy và luật đó chỉ sống bên trong chú giải. Thiếu viền thì ba nền
     nhạt (#FFD3D2 …) gần như tàng hình trên nền trắng thanh bên.
     ⛔ ĐỪNG gộp vào `.lgv-cham` sẵn có — chấm ấy là chấm màu ĐẶC của giáo viên,
        kẻ viền quanh nó là đổi một thứ chẳng ai nhờ. */
  .lgv-tt-cham { flex:none; width:11px; height:11px; box-sizing:border-box;
      border-radius:var(--r-sm); border:1px solid currentColor; }

  /* ── Khung lưới ── */
  /* ⭐ `flex:1 1 auto` + `min-height:0` = khung ăn trọn phần còn lại của `.lgv-chinh`,
     nên đáy khung bám sát đáy cột lọc dù thanh công cụ có xuống hai hàng hay dải
     nhắc dài thêm một dòng. Đúng lối `.lt-khung` bên Lịch test.
     ⛔ `max-height` GIỮ LẠI làm cái chặn cuối, và nay dùng CÙNG công thức với
        `.lgv-man` (`100vh − 101px`) chứ không phải 258px nữa: 258px là trần của
        RIÊNG khung tính từ đỉnh trang, nó chặn sớm hơn dòng flex 108px và kéo đáy
        khung lên khỏi đáy cột lọc — đúng cái vừa đi chữa.
     ⛔ ĐỪNG GỠ chuỗi `var(--dnc-du, 0px)` khỏi khối này: `thu-lich-gv-man.js` dòng
        201-202 canh đúng nó phải nằm TRONG `.lgv-khung {…}`, và
        `thu-thanh-nut-cong-cu.js` dòng 267 đếm tổng số chỗ (cần ≥ 13, sổ nay có 15).
     ⛔ Điện thoại đè lại bằng `100vh − 232px` ở `@media` bên dưới — đừng gỡ. */
  /* ✋ KÉO NGANG BẰNG CHUỘT / NGÓN TAY — Boss 08/09/2026: *"nó cần phải có chức
     năng di ấn kéo sang hai bên trong cái bảng đó"*. Phần chạy nằm ở
     `lgvGanKeoNgang` trong `js/tinh-nang.js`.
     ⛔⛔ ĐÃ ĐỔI `pan-y` → `none` NGÀY 20/09/2026. ĐỪNG TRẢ VỀ `pan-y`.
        Dòng cũ ở đây viết *"pan-y chứ ĐỪNG none: để none là mất luôn cuộn dọc tự
        nhiên"* — câu ấy SAI, và cái giá của nó là Boss báo ngày 20/09:
        *"kéo chéo xuống và sang 2 bên trong bảng lịch rất khựng, khó kéo, cứng đơ"*.
        `none` KHÔNG làm mất cuộn dọc: nó chỉ chuyển việc cuộn dọc sang cho
        `lgvGanKeoNgang`, y như bảng Điểm danh vẫn chạy từ 25/07/2026.
        Cái `pan-y` THẬT SỰ gây ra: trình duyệt phải ĐOÁN xem ngón tay đang vuốt
        ngang hay dọc trước khi chịu nhả sự kiện, nên mỗi cú vuốt chéo đều trễ một
        nhịp rồi mới đi — đúng chữ "cứng đơ". Kho đã ghi bài học này từ 25/07/2026
        ở khối ⭐ của `.khung-cuon` (css/lop.css ~485), lưới này dựng sau
        (08/09) nên không biết mà tránh.
        ⛔ Và `none` là điều kiện BẮT BUỘC của cú chụm hai ngón (thêm 20/09): trình
           duyệt còn giữ cử chỉ thì nó nuốt mất ngón thứ hai.
     ⛔ `user-select` chỉ tắt KHI ĐANG KÉO. Tắt sẵn thì không ai bôi đen chép được
        tên lớp trong ô nữa. */
  .lgv-khung { cursor:grab; touch-action:none; overscroll-behavior:contain; }
  /* ⛔⛔ DÒNG DƯỚI KHÔNG THỪA — đừng dọn đi vì trông như lặp lại.
     `css/lop.css:6535` có `[data-keo-ngang="1"]{touch-action:pan-y}`, và
     `#lgvKhung` MANG đúng thuộc tính ấy (do `ganKeoNgang` cắm vào để làm cử chỉ
     vuốt-đổi-tuần). Hai luật ngang độ nặng (0,1,0), mà `css/lop.css` nạp
     SAU `css/man.css` — nên luật kia thắng và dòng ngay trên VÔ TÁC DỤNG.
     Đo trong Chrome thật ở cả 5 cỡ màn 20/09/2026: vẫn ra `pan-y`.
     Dòng này nặng (0,2,0) nên thắng, mà không đụng tới luật chung của khung khác.
     ⛔ Đừng thay bằng `!important`: luật `[data-keo-ngang]` là luật ĐÚNG cho mọi
        khung vuốt-đổi-trang khác; chỉ riêng lưới lịch này mới cần `none`. */
  .lgv-khung[data-keo-ngang="1"] { touch-action:none; }
  .lgv-khung.dang-keo { cursor:grabbing; user-select:none; -webkit-user-select:none; }
  .lgv-khung { border:1px solid var(--vien); border-radius:var(--r-md); background:var(--the);
      overflow:auto; flex:1 1 auto; min-height:0;
      max-height:calc(100vh - 101px - var(--dnc-du, 0px)); }
  .lgv-trong { padding:30px; text-align:center; color:var(--mo); font-size:13.5px; }
  .lgv-loi { padding:24px; text-align:center; color:var(--do); font-size:13.5px; }

  /* ══════════════════════════════════════════════════════════════════════════════
     Ô LỊCH — DÒNG MỎNG, KHÔNG PHẢI KHỐI MÀU
     ──────────────────────────────────────────────────────────────────────────────
     Một ngày ở view Tháng có thể có mươi lớp. Mỗi lớp một khối màu dày thì ô ngày
     cao gấp ba màn hình; nên mỗi lớp là một Ô MỎNG, đúng lối Google Calendar.

     ⛔⛔ HAI DÒNG, KHÔNG PHẢI MỘT — sửa 30/08/2026 sau khi CHỤP ẢNH RA MÀ NHÌN.
     Bản đầu nhét cả bốn thứ (chấm · giờ · tên lớp · giáo viên) lên MỘT hàng ngang.
     Đo trên màn 1400px: lưới tháng chia 7 cột nên mỗi ô ngày chỉ rộng ~93px; trừ lề,
     trừ chấm màu, trừ "18:00" là còn khoảng 25px cho cả tên lớp lẫn tên giáo viên.
     Ảnh chụp ra đúng như vậy: mọi ô đều là "18:00 L… C…" — tên lớp và tên cô đều
     cụt còn một chữ cái. Bài kiểm vẫn xanh, vì mã chạy đúng.
       dòng 1: giờ + TÊN LỚP        (thứ để tìm ra buổi)
       dòng 2: chấm màu + GIÁO VIÊN (thứ khiến công cụ này tên là "Lịch giáo viên")
     ⛔ Đừng gộp lại một hàng cho "gọn". Gọn mà đọc không ra thì bằng không.
     ⛔ `width:100%` + `box-sizing:border-box` LÀ BẮT BUỘC vì đây là thẻ <button>:
        button không co theo ô chứa như <div>, nó tự nở bằng nội dung và ĐÈ SANG CỘT
        BÊN CẠNH. Lỗi này đã xảy ra thật ở Lịch test ngày 21/08/2026. */
  .lgv-o { display:block; width:100%; box-sizing:border-box;
      border:1px solid currentColor; border-radius:var(--r-sm); padding:1px 5px; margin-bottom:2px;
      font-family:inherit; font-size:12px; line-height:1.45; text-align:left; cursor:pointer;
      /* ⛔ MẶC ĐỊNH LÀ XANH (dạy bình thường), không phải đỏ. Ô nào rơi khỏi ba
         nhánh của `LGV_TRANG_THAI` thì rơi về đây — rơi về ĐỎ là bịa ra một lời
         báo động không có thật. */
      overflow:hidden; background:var(--lgv-xanh-n); color:var(--lgv-xanh-c); }
  .lgv-o:hover { filter:brightness(.96); }
  body.toi .lgv-o:hover { filter:brightness(1.18); }
  .lgv-o.mau-do   { background:var(--lgv-do-n);   color:var(--lgv-do-c); }
  .lgv-o.mau-vang { background:var(--lgv-vang-n); color:var(--lgv-vang-c); }
  .lgv-o.mau-xanh { background:var(--lgv-xanh-n); color:var(--lgv-xanh-c); }
  .lgv-hang { display:flex; align-items:center; gap:5px; min-width:0; }
  .lgv-o .lgv-gio { flex:none; font-variant-numeric:tabular-nums; font-weight:600; }
  .lgv-o .lgv-lop { flex:1 1 auto; min-width:0; font-weight:600; overflow:hidden;
      text-overflow:ellipsis; white-space:nowrap; }
  /* Dòng giáo viên nhẹ hơn dòng trên nhưng KHÔNG mờ đi bằng `opacity` — 11px/400 đã
     bị cô Quỳnh chê thẳng là *"mờ nhạt"* ngày 21/08. Thứ bậc dựng bằng cỡ chữ và độ
     đậm là đủ. */
  .lgv-o .lgv-gv { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis;
      white-space:nowrap; font-size:11.5px; font-weight:500; }
  /* Buổi đã chốt điểm danh: một vạch dọc bên trái, KHÔNG phải vòng quanh ô.
     ⛔ Vòng `inset 0 0 0 2px` chính là "viền đậm" cô Quỳnh chê ở Lịch test 14/08. */
  .lgv-o.xong { box-shadow:inset 3px 0 0 var(--o-tot); padding-left:10px; }
  /* 🎌 NGÀY CẢ TRUNG TÂM NGHỈ LỄ — Coder thêm 08/09/2026, Boss chốt "giữ ô, tô mờ
     + ghi tên lễ". Khối này THUẦN CỘNG THÊM: không sửa một luật nào có sẵn.
     ⛔ Chồng LÊN màu trạng thái chứ không thay nó — ô vẫn giữ đỏ/vàng/xanh của
        việc "có giáo viên chưa", chỉ mờ đi để mắt lướt qua. Đổi `background` ở
        đây là nuốt mất tin kia.
     ⛔ KHÔNG `pointer-events:none` — trung tâm vẫn có thể dạy bù hôm ấy, bấm vào ô
        phải mở được hộp chi tiết như thường.
     ⛔ Không `text-transform:uppercase`, không `letter-spacing`, không
        `font-weight:800` — ba thứ Boss đã chê là "lộ rõ ui AI". */
  .lgv-o.lgv-nghile { opacity:.55; }
  .lgv-nghile-nhan {
    display:block; margin-top:2px; font-size:11px; line-height:1.25;
    color:var(--chu-mo); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  /* Câu trong hộp chi tiết buổi học. Nền nhạt để tách khỏi phần danh sách bên dưới,
     không viền đậm (viền đậm là thứ Boss chê ở Lịch test 14/08). */
  .lgv-hop-nghile {
    margin:6px 0 2px; padding:6px 9px; border-radius:6px;
    /* `--nen2` (không có gạch trước số) là biến có thật, dùng 180 chỗ trong file này.
       Gõ `--nen-2` là biến KHÔNG TỒN TẠI: trình duyệt lặng lẽ rơi về giá trị dự
       phòng, không lỗi nào báo — và nếu quên viết dự phòng thì ô trong suốt. */
    background:var(--nen2, rgba(127,127,127,.10)); color:var(--chu-mo);
    font-size:13px; line-height:1.4;
  }
  /* Số nhỏ góc ô ĐỎ: "N người sẵn sàng" nhận dạy thay (cô Quỳnh chốt 30/08/2026).
     ⛔ CHỈ Ô ĐỎ MỚI CÓ. Ô xanh là lớp đang chạy êm, gắn số "người sẵn sàng" vào đó
        là hỏi một câu chẳng ai hỏi. Ô vàng đã có người rồi. Xem `lgvSan` trong mã.
     ⛔ LƯỢT 1 máy chủ luôn trả `soSanSang: 0` nên chưa ô nào mang số thật — nhưng
        đường vẽ đã NỐI SẴN và bài kiểm có canh (mục ②d của `thu-lich-gv-man.js`),
        chứ không để hở thành dữ liệu chết như `lopHong` từng bị. */
  .lgv-o .lgv-san { flex:none; min-width:15px; text-align:center; font-size:10.5px;
      font-weight:600; line-height:1.5; border-radius:var(--r-sm); padding:0 3px;
      background:currentColor; }
  .lgv-o .lgv-san b { color:var(--the); font-weight:600; }
  .lgv-them-nua { display:block; width:100%; text-align:left; font:inherit;
      font-size:10.5px; color:var(--mo); padding:1px 3px; background:none; border:0;
      cursor:pointer; }
  .lgv-them-nua:hover { text-decoration:underline; }
  /* Bảng kê của hộp "Báo nghỉ nhiều buổi" (Boss 04/09/2026). Chữ nhỏ hơn thân bài
     một nấc vì đây là SỐ LIỆU để liếc, không phải câu để đọc. */
  .lgv-nd-xn { font-size:13px; line-height:1.65; }
  .lgv-nd-ke { margin-top:8px; padding:9px 11px; border:1px solid var(--vien);
      border-radius:var(--r-md); background:var(--nen2); }
  .lgv-nd-ke .mo { color:var(--mo); }
  .lgv-nd-vuong { margin-top:7px; padding-top:7px; border-top:1px solid var(--vien);
      color:var(--cam,#d97706); font-size:12.5px; }

  /* ══════════════════════════════════════════════════════════════════════════════
     THẺ GỘP CỤM CHỒNG GIỜ (`.lgv-cum`) — bản vá lỗi ĐO THẬT 30/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     ⛔⛔ ĐỪNG QUAY LẠI KIỂU "CHIA CỘT LÀ XONG". Đo trên sổ thật: Thứ Bảy 10:00 có
        9 LỚP cùng khung giờ (T3 17:30 và T2 17:30 mỗi chỗ 8 lớp). Chia 8 làn trong
        một cột lưới Tuần rộng 104px thì mỗi thẻ còn 14px và `clientWidth` của
        `.lgv-lop` bằng ĐÚNG 0 — tám vệt màu trống trơn, không một chữ nào. Ảnh
        bằng chứng: `kiem-thu/anh-giao-dien/soi-tuan-8-bung.png`.
     ⭐ Cách chữa: cụm nào đông quá thì KHÔNG chia làn nữa mà gộp thành MỘT thẻ
        rộng nguyên cột, xếp tên lớp CHỒNG DỌC — vì thẻ hẹp ngang (104px) nhưng
        CAO (90 phút = 82px), chỗ trống nằm ở chiều dọc chứ không phải chiều ngang.
        Bấm vào là ra hộp danh sách đầy đủ, mỗi dòng bấm tiếp được.
     ⛔ KHÔNG cho cuộn bên trong thẻ (`overflow:hidden`, không phải `auto`): cuộn
        lồng trong một ô 82px nằm giữa cái lưới cũng đang cuộn là thứ không ai
        dùng nổi bằng chuột. Phần không vừa thì đếm ra thành "+M lớp nữa". */
  /* ⛔⛔ BỐN DÒNG SAU PHẢI CAO ĐÚNG `LGV_CAO_DONG_CUM` VÀ `gap:0`.
     ⛔ ĐỪNG ĐỌC `line-height:13px` DƯỚI ĐÂY RỒI HẠ `LGV_CAO_DONG_CUM` VỀ 13.
        Hằng ấy là 14 và ĐÚNG LÀ 14: đo bằng máy 31/08/2026, ba dòng thật trong
        thẻ gộp ra [14, 13, 14]px chứ không 13px đều — dòng có chấm màu
        (`.lgv-cum-d` là flex chứa một chấm 10px) nhỉnh hơn một điểm ảnh so với
        `line-height` khai ở đây. CSS nói một đằng, trình duyệt dựng một nẻo, và
        thứ đáng tin là số ĐO ĐƯỢC. Lý do đầy đủ nằm ngay trên `LGV_CAO_DONG_CUM`.
        (Chú thích này trước ghi "(13px)" — sửa 04/09/2026, vì để nguyên là phiên
        sau đọc thấy lệch rồi đi "sửa" hằng số về 13, đúng cái nó đang cấm.)
     Mã đếm số dòng nhét vừa bằng phép chia thẳng chiều cao thẻ cho hằng ấy. Để
     `line-height` không đơn vị (1,3 × cỡ chữ) hay để `gap:1px` là mỗi dòng nhỉnh
     hơn hằng một chút, cộng dồn năm dòng thành thừa ra gần một dòng, và dòng
     "+N lớp nữa" ở cuối bị `overflow:hidden` NUỐT MẤT. Đã xảy ra thật 30/08/2026:
     thẻ in ra bốn tên lớp rồi im, người xem không biết còn năm lớp nữa. Bài kiểm
     `thu-lich-gv-man.js` mục ⑥b nay canh `scrollHeight <= clientHeight`. */
  .lgv-cum { display:flex; flex-direction:column; gap:0; padding:2px 5px;
      overflow:hidden; }
  .lgv-cum .lgv-cum-dau { flex:none; font-size:10.5px; font-weight:600;
      line-height:13px; font-variant-numeric:tabular-nums; white-space:nowrap;
      overflow:hidden; text-overflow:ellipsis; }
  .lgv-cum .lgv-cum-d { flex:none; display:flex; align-items:center; gap:3px;
      font-size:11px; line-height:13px; min-width:0; }
  .lgv-cum .lgv-cum-ten { flex:1 1 auto; min-width:0; overflow:hidden;
      text-overflow:ellipsis; white-space:nowrap; }
  .lgv-cum .lgv-cum-con { flex:none; font-size:10.5px; line-height:13px;
      text-decoration:underline; white-space:nowrap; }

  /* Hộp danh sách cụm — dùng chung khung `.lgv-hop`, chỉ thêm phần danh sách. */
  .lgv-ds-cum { margin:2px 0 0; max-height:52vh; overflow-y:auto; }
  /* 🙈 21/09/2026 — ẨN THANH CUỘN Ở MỌI DANH SÁCH CỦA LỊCH GIÁO VIÊN.
     Boss: *"cái thanh scroll đang che mất số tôi muốn bạn bỏ luôn cái thanh đó đi ko
     cần đâu"* — thanh cuộn chiếm mép phải, đè lên con số (số lớp, số giờ) ở cuối dòng.
     Boss chốt bằng nút bấm: ẨN THANH, VẪN CUỘN ĐƯỢC (lăn chuột / vuốt), mép dưới mờ
     dần để biết còn nữa. Áp cho MỌI danh sách trong Lịch GV (cột lọc bên trái, danh
     sách giáo viên / lớp, danh sách trong thẻ cụm).
     ⛔ KHÔNG áp cho lưới lịch `.lgv-khung`: đó là bảng kéo ngang-dọc, không phải danh
        sách — thanh cuộn ở đó là chỗ duy nhất cho biết bảng còn bị khuất.
     ⛔ Mép mờ bằng `mask-image` (chỉ làm trong suốt, không tô màu) nên nền sáng, nền
        tối đều đúng. `padding-bottom` bằng đúng độ cao mép mờ: cuộn tới cuối thì dòng
        cuối nằm TRÊN mép mờ, không bị mờ theo. */
  .lgv-ben, .lgv-ds-gv, .lgv-ds-cum { scrollbar-width:none; -ms-overflow-style:none; }
  .lgv-ben::-webkit-scrollbar, .lgv-ds-gv::-webkit-scrollbar,
  .lgv-ds-cum::-webkit-scrollbar { display:none; width:0; height:0; }
  div.lgv-ds-gv, .lgv-ds-cum { padding-bottom:14px;
      -webkit-mask-image:linear-gradient(to bottom, #000 calc(100% - 14px), transparent);
              mask-image:linear-gradient(to bottom, #000 calc(100% - 14px), transparent); }
  .lgv-ds-cum button { display:flex; width:100%; box-sizing:border-box; gap:8px;
      align-items:center; text-align:left; font:inherit; font-size:13px;
      background:var(--the); color:var(--chu); border:1px solid var(--vien);
      border-radius:var(--r-md); padding:7px 10px; margin-bottom:5px; cursor:pointer; }
  .lgv-ds-cum button:hover { background:var(--nen2); }
  .lgv-ds-cum .lgv-ds-ten { flex:1 1 auto; min-width:0; font-weight:600;
      overflow-wrap:anywhere; }
  .lgv-ds-cum .lgv-ds-gv { flex:none; max-width:48%; font-size:12px; color:var(--mo);
      overflow-wrap:anywhere; text-align:right; }
  /* ⭐ VẠCH MÀU BÊN TRÁI mỗi dòng — cô Quỳnh 31/08/2026: bấm vào thẻ gộp đỏ phải
     thấy NGAY lớp nào đỏ. Vạch dày 4px ở mép trái, không tô nền kín: nền kín thì
     tên lớp chìm nghỉm, mà cả hộp thành một mảng đỏ chẳng chỉ được vào đâu.
     ⛔ Dòng xanh CỐ Ý không có vạch — bình thường thì đừng đòi ai để ý. */
  /* ⛔ Dùng `--lgv-do-c` (màu CHỮ, đậm) làm vạch, KHÔNG dùng `--lgv-do-n` (màu nền,
     nhạt) — nền nhạt đặt cạnh nền thẻ trắng thì gần như không thấy vạch đâu. Bảng
     màu chỉ có hai biến mỗi trạng thái (`-n` nền, `-c` chữ), đừng đẻ thêm biến thứ
     ba cho riêng chỗ này. */
  .lgv-ds-cum button.lgv-ds-do   { border-left:4px solid var(--lgv-do-c); }
  .lgv-ds-cum button.lgv-ds-vang { border-left:4px solid var(--lgv-vang-c); }
  .lgv-ds-cum .lgv-hop-nhan { flex:none; font-size:11px; }
  /* Dòng tóm tắt trên đầu hộp: trả lời thẳng "lớp nào?" trước khi người ta dò. */
  .lgv-ds-tom { display:flex; align-items:center; gap:6px; margin:8px 0 2px;
      padding:6px 9px; border-radius:var(--r-md); font-size:12.5px; font-weight:600;
      line-height:1.45; }
  .lgv-ds-tom.do   { background:var(--lgv-do-n);   color:var(--lgv-do-c); }
  .lgv-ds-tom.vang { background:var(--lgv-vang-n); color:var(--lgv-vang-c); }
  .lgv-ds-tom .ico-the { flex:none; }

  /* ══════════════════════════════════════════════════════════════════════════════
     DÒNG NHẮC "LỚP CHƯA HIỆN TRÊN LỊCH" (`.lgv-hong`)
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ NHẮC NHẸ, ĐỪNG LÀM ỒN. Không có lớp hỏng thì khối này KHÔNG được vẽ ra một
        pixel nào — một dải cảnh báo trống nằm dưới lịch suốt năm là thứ người ta
        học cách không nhìn, tới lúc có lớp hỏng thật cũng không ai đọc.
     ⛔ Và đừng tô đỏ: đây không phải lỗi của app, chỉ là ô thứ/giờ chưa điền xong. */
  .lgv-hong { margin-top:8px; font-size:12.5px; color:var(--mo); line-height:1.5; }
  .lgv-hong button { font:inherit; font-size:12.5px; background:none; border:0;
      color:var(--muc); text-decoration:underline; cursor:pointer; padding:0 2px; }

  /* ── Nhóm theo giáo viên (nút gạt "Xem theo") ── */
  .lgv-nhom { margin-bottom:3px; }
  .lgv-nhom-ten { display:flex; align-items:center; gap:5px; font-size:10.5px;
      color:var(--mo); font-weight:600; padding:0 2px 1px; overflow:hidden;
      text-overflow:ellipsis; white-space:nowrap; letter-spacing:normal; }

  /* ── View THÁNG ── */
  .lgv-thang { display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); }
  .lgv-thang-thu { text-align:center; padding:7px 4px; font-size:10.5px; color:var(--mo);
      border-left:1px solid var(--vien); border-bottom:1px solid var(--vien); }
  .lgv-thang-thu:first-child { border-left:none; }
  .lgv-o-ngay { border-left:1px solid var(--vien); border-top:1px solid var(--vien);
      min-height:clamp(96px, 12vh, 168px); padding:5px 7px; }
  /* ⛔ Ngày của tháng khác KHÔNG tô nền xám — chỉ làm mờ con số là đủ. Mảng xám cắt
     lưới thành từng khối, trông rất gợn (cô Quỳnh 14/08/2026). */
  .lgv-o-ngay.ngoai { background:transparent; }
  .lgv-o-ngay.ngoai .lgv-sn { opacity:.45; }
  .lgv-o-ngay .lgv-sn { font-size:12px; font-weight:600; text-align:right;
      color:var(--mo); margin-bottom:2px; }
  .lgv-o-ngay.homnay .lgv-sn { color:var(--muc); box-shadow:inset 0 0 0 1.5px var(--muc);
      border-radius:var(--r-sm); min-width:20px; height:19px; line-height:19px; text-align:center;
      padding:0 3px; margin-left:auto; }
  .lgv-o-ngay.dangxem .lgv-sn { color:#fff; background:var(--muc); box-shadow:none;
      border-radius:var(--r-sm); min-width:20px; height:19px; line-height:19px; text-align:center;
      padding:0 3px; margin-left:auto; }
  .lgv-o-ngay.dangxem { background:var(--xanh-nhat); }

  /* ══════════════════════════════════════════════════════════════════════════════
     View TUẦN và NGÀY — LƯỚI GIỜ, THẺ ĐẶT THEO PHÚT
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ THẺ ĐẶT BẰNG TOẠ ĐỘ THEO PHÚT, không nhét vào ô giờ. Đây là khác biệt lớn
        nhất giữa "cái bảng" và "cái lịch": lớp 17h30 phải nằm giữa dòng 17h và 18h.
        Nhìn là thấy ngay lớp nào chồng giờ nhau — mà chồng giờ là chuyện thường ngày
        của một trung tâm 127 lớp.
     ⛔ LỚP CHỒNG GIỜ CHIA ĐÔI BỀ NGANG, không đè lên nhau. Đè là mất hẳn thông tin.
     ⛔ `.lgv-cot .lgv-o` phải trả `.lgv-o` về `position:absolute` và bỏ `margin` —
        luật `.lgv-o` gốc dựng cho dòng mỏng trong lưới tháng. */
  .lgv-dau-hang { display:grid; position:sticky; top:0; z-index:5; background:var(--the);
      border-bottom:1px solid var(--vien); }
  .lgv-dau-o { text-align:center; padding:7px 6px 8px; border-left:1px solid var(--vien); }
  .lgv-dau-o:first-child { border-left:none; }
  .lgv-dau-o .lgv-thu { font-size:10.5px; color:var(--mo); }
  .lgv-dau-o .lgv-sn { font-size:18px; font-weight:600; line-height:1.25; margin-top:2px; }
  /* Cùng quy ước hai dấu với lịch mini: ô ĐẶC = đang xem · ô VIỀN = hôm nay. */
  .lgv-dau-o.homnay .lgv-sn, .lgv-dau-o.dangxem .lgv-sn { display:inline-block;
      min-width:26px; height:24px; line-height:24px; border-radius:var(--r-sm); padding:0 5px;
      font-size:15px; font-weight:700; }
  .lgv-dau-o.homnay .lgv-sn { box-shadow:inset 0 0 0 2px var(--muc); color:var(--muc); }
  .lgv-dau-o.dangxem .lgv-sn { background:var(--muc); color:#fff; box-shadow:none; }
  .lgv-dau-o.dangxem { background:var(--xanh-nhat); }
  .lgv-than { display:grid; position:relative; }
  .lgv-cot-gio { border-right:1px solid var(--vien); }
  /* ⛔ NAY LẤY TỪ BIẾN `--lgv-cao-gio` DO JS ĐẶT (`lgvDatZoom`), một chỗ đổi là cả
     hai bên đúng. Trước 31/08/2026 số 68 gõ cứng ở CẢ ĐÂY LẪN hằng `LGV_CAO_GIO`
     bên JS, và lệch một chút là nhãn giờ trôi khỏi vạch giờ.
     ⛔ Con số dự phòng 68px trong `var(…, 68px)` phải bằng `LGV_CAO_GIO_GOC`. */
  /* ⛔⛔ 68px, KHÔNG phải 56px như bản đầu — cô Quỳnh 31/08/2026 gửi ảnh so sánh với
     Google Calendar: *"mấy cái block ở trong lịch bị dồn nhiều vào 1 cái block quá
     trông ko bao quát được"*. Một giờ cao hơn = thẻ cao hơn = xếp được HAI TẦNG thẻ
     đầy đủ ba dòng trong cùng khung giờ, thay vì gom chục lớp vào một thẻ phải bấm.
     Tính thật: buổi 1h45 → 1.75×68−2 = 117px → hai tầng 58,5px, vừa đúng ngưỡng
     `LGV_CAO_3_DONG` (58px) nên mỗi thẻ vẫn in đủ giờ · lớp · giáo viên.
     ⛔ Nó cũng vá luôn lỗi buổi 55 phút bị xén chữ: 0,917×68−2 = 60px ≥ 58px.
     ⛔ ĐỔI SỐ NÀY THÌ PHẢI ĐỔI `LGV_CAO_GIO_GOC` bên JS cho khớp — lệch một chút là
        nhãn giờ trôi khỏi vạch giờ và mọi thẻ đặt sai chỗ theo. */
  .lgv-nhan-gio { height:var(--lgv-cao-gio, 68px); font-size:11.5px; color:var(--mo); text-align:right;
      padding-right:8px; position:relative; top:-7px; font-variant-numeric:tabular-nums; }
  .lgv-cot { position:relative; border-left:1px solid var(--vien); }
  /* ⛔ CUỐI TUẦN KHÔNG TÔ NỀN XÁM (cô Quỳnh 14/08/2026) — mảng xám cắt lưới thành
     từng khối, phá cảm giác các dòng giờ chạy liền một mạch. */
  .lgv-cot.cuoituan { background:transparent; }
  .lgv-cot.dangxem { background:var(--xanh-nhat); }
  .lgv-vach { position:absolute; left:0; right:0; border-top:1px solid var(--vien);
      opacity:.75; }
  .lgv-vach.nua { opacity:.32; }
  /* ══════════════════════════════════════════════════════════════════════════════
     VẠCH ĐỎ GIỜ HIỆN TẠI — thứ khiến người ta tin đây là cái lịch đang sống
     ──────────────────────────────────────────────────────────────────────────────
     ⛔⛔ NÓ LÀ CON CỦA ĐÚNG CỘT HÔM NAY, KHÔNG PHẢI CON CỦA `.lgv-than`. Đặt ở thân
        lưới thì vạch kéo ngang suốt bảy ngày — nhìn ra là "cả tuần đang ở 15h20",
        vô nghĩa. `left:0; right:0` ở đây là mép trái/phải của CỘT.
     ⛔ Và chỉ vẽ khi hôm nay THẬT SỰ nằm trong khoảng đang xem (xem `lgvVeCotNgay`);
        xem tuần sau mà vẫn có vạch đỏ là nói dối. */
  .lgv-baygio { position:absolute; left:0; right:0; height:0; z-index:4;
      border-top:2px solid var(--do); pointer-events:none; }
  .lgv-baygio::before { content:""; position:absolute; left:-4px; top:-5px; width:8px;
      height:8px; border-radius:50%; background:var(--do); }
  /* Thẻ trong lưới giờ: dựng đứng, hai dòng, đặt tuyệt đối theo phút. */
  /* ⛔⛔ PADDING NGANG Ở ĐÂY MỚI LÀ THỨ BÓ CHỮ, KHÔNG PHẢI `.lgv-cum`.
     Hai luật cùng trúng thẻ `<div class="lgv-o lgv-cum">`, và luật này thắng vì
     chuỗi chọn dài hơn (`.lgv-cot .lgv-o` > `.lgv-cum`). Đêm 31/08/2026 tôi nới
     padding của `.lgv-cum` từ 5px xuống 3px và con số đo ra KHÔNG NHÚC NHÍCH —
     đúng vì nó đang bị đè. Sửa nhầm chỗ rồi kết luận "nới cũng không ăn thua" là
     cách bỏ sót lỗi êm nhất.
     ⛔ ĐO TRƯỚC RỒI HÃY SỬA. Đường đi của bề ngang, đo thật trên lưới Tuần:
       cột 104px → thẻ 103px → trừ viền 2px = 101 → trừ padding ngang → còn cho
       `.lgv-cum-d`, rồi trừ tiếp chấm màu 10px + khe của nó = vùng chữ tên lớp.
       Với 6px thì vùng chữ chỉ còn 75px, mà tên lớp thật ("4C3 CD1 NC A") cần
       77px — thiếu 2px là tên lớp bị cắt thành "4C3 CD1 N…".
     Nay 5px + khe 3px → vùng chữ 78px, dư 1px. Đừng nới thêm: padding mỏng quá
     thì chữ dính sát viền, nhìn là biết ngay. */
  .lgv-cot .lgv-o { position:absolute; display:block; margin:0; padding:3px 5px;
      overflow:hidden; }
  .lgv-cot .lgv-o .lgv-gio, .lgv-cot .lgv-o .lgv-lop, .lgv-cot .lgv-o .lgv-gv {
      display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .lgv-cot .lgv-o.xong { padding-left:9px; }
  /* Trong lưới giờ, số "N người sẵn sàng" nép vào GÓC TRÊN BÊN PHẢI thay vì chiếm
     nguyên một dòng. Thẻ ở đây chỉ rộng ~104px và đã phải nuôi ba dòng chữ; cho
     nó một dòng riêng là đẩy tên giáo viên ra khỏi thẻ.
     ⛔ Neo được vì `.lgv-cot .lgv-o` là `position:absolute`. Luật này KHÔNG áp
        cho lưới Tháng — ở đó ô nằm trong dòng chảy, `position:absolute` sẽ nhảy
        ra khỏi ô ngày và bám vào tận khung lưới. */
  .lgv-cot .lgv-o .lgv-san { position:absolute; top:2px; right:3px; }

  /* ── Hộp thông tin một ô ── */
  .lgv-hop-nen { position:fixed; inset:0; background:rgba(15,18,22,.42); z-index:70;
      display:flex; align-items:center; justify-content:center; padding:16px; }
  .lgv-hop { background:var(--the); color:var(--chu); border:1px solid var(--vien);
      border-radius:var(--r-lg); width:min(420px, 100%); max-height:86vh; overflow:auto;
      padding:16px 18px 14px; }
  .lgv-hop h3 { margin:0 0 3px; font-size:16px; font-weight:700; letter-spacing:normal; }
  .lgv-hop-phu { font-size:12.5px; color:var(--mo); margin-bottom:11px; }
  .lgv-hop dl { display:grid; grid-template-columns:auto 1fr; gap:5px 12px; margin:0;
      font-size:13px; }
  .lgv-hop dt { color:var(--mo); }
  .lgv-hop dd { margin:0; font-weight:500; overflow-wrap:anywhere; }
  .lgv-hop-nhan { display:inline-block; border:1px solid currentColor; border-radius:var(--r-sm);
      padding:0 6px; font-size:11.5px; font-weight:600; }
  /* Dòng "lượt sau" — ĐỪNG XOÁ CHO GỌN. Người ta bấm vào ô là để sửa; không nói
     thẳng thì họ ngồi tìm cái nút không tồn tại. */
  .lgv-hop-sau { margin:12px 0 0; padding:8px 11px; border:1px dashed var(--vien);
      border-radius:var(--r-md); font-size:12.5px; line-height:1.5; color:var(--chu);
      background:var(--nen2); }
  /* ── Ô đổi giáo viên cố định (cô Quỳnh 30/08/2026) ────────────────────────────
     ⛔ Khung LIỀN NÉT, khác hẳn khung đứt nét của `.lgv-hop-sau` bên trên: nét đứt
        là "lời nhắn đọc rồi thôi", nét liền + nền thẻ là "chỗ này bấm được". Người
        dùng phân biệt hai thứ bằng mắt trước khi kịp đọc chữ. */
  /* ── 🗂️ KHUNG HỘP NHỎ NỔI GIỮA MÀN — nay chỉ còn hộp Xuất Excel dùng ────────
     ⛔ TÊN `.lgv-gio-*` GIỮ NGUYÊN dù hộp chọn giờ đã gỡ hẳn 03/09/2026. Ba luật
        còn lại (`.lgv-gio-hop`, `h3`, `.lgv-gio-nut`) là thứ `lgvMoHopXuat` dùng
        chung từ đầu; đổi tên cho "sạch" là phải sờ đúng bốn chỗ trong thân bài, mà
        sót một chỗ thì hộp Xuất Excel mất khung hoặc mất nút, không lỗi nào báo.
     Mẫu là hộp thêm sự kiện của Google Calendar: hộp nhỏ nổi giữa màn, tiêu đề ở
     trên, hai nút ở góc dưới phải. */
  .lgv-gio-hop { width:min(430px, 94vw); max-height:86vh; overflow:auto;
      background:var(--nen); border:1px solid var(--vien); border-radius:var(--r-lg);
      box-shadow:0 14px 44px rgba(0,0,0,.24); padding:18px 20px 16px; }
  .lgv-gio-hop h3 { margin:0 0 3px; font-size:17px; font-weight:600; }
  /* Hàng chọn kỳ trong hộp Xuất Excel. Nhãn nằm TRÊN ô chọn chứ không nằm cạnh:
     trên điện thoại nhãn cạnh ô đẩy ô chọn hẹp lại còn nửa dòng chữ. */
  .lgv-xuat-hang { display:flex; gap:10px; flex-wrap:wrap; margin:10px 0 4px; }
  .lgv-xuat-hang label { display:flex; flex-direction:column; gap:4px; flex:1 1 130px;
    font-size:12px; color:var(--mo); }
  .lgv-xuat-hang select { border:1px solid var(--vien); background:var(--the);
    color:var(--chu); border-radius:var(--r-o, 8px); padding:7px 8px; font:inherit; font-size:14px; }
  .lgv-xuat-mo { font-size:12.5px; color:var(--mo); line-height:1.55; margin:6px 0 0; }
  .lgv-gio-nut { display:flex; justify-content:flex-end; gap:8px; margin-top:4px; }
  .lgv-gio-nut button { font-family:inherit; font-size:13.5px; padding:8px 17px;
      border-radius:var(--r-sm); cursor:pointer; border:1px solid var(--vien);
      background:var(--nen); color:var(--chu); }
  .lgv-gio-nut button.chinh { border-color:var(--xanh-dam); background:var(--xanh);
      color:#fff; font-weight:600; }
  .lgv-gio-nut button:disabled { opacity:.5; cursor:default; }
  /* ⛔⛔ PHẢI CÓ ĐỦ `left:0` — ĐỪNG BỎ. Mép trái trước 03/09/2026 do dòng
     `style="left:{mangDk}px"` lúc dựng cấp (máng chừa cho dải giờ đã đăng ký).
     Bỏ máng mà quên khai `left` ở đây thì thẻ `position:absolute` này có `left:auto`
     và TỰ CO VỀ VỪA NỘI DUNG: cột 143px mà thẻ lớp chỉ còn 12px, tên lớp mất sạch.
     Không lỗi JavaScript nào báo; chỉ phép đo pixel trong `thu-lich-gv-man.js` bắt. */
  .lgv-lo { position:absolute; top:0; bottom:0; left:0; right:0; pointer-events:none; }
  .lgv-lo .lgv-o { pointer-events:auto; }
  /* ── 🙋 XIN NGHỈ / DẠY THAY (31/08/2026) ──────────────────────────────────
     ⛔ TÊN `lgv-cc-*` GIỮ NGUYÊN dù cơ chế chấm công đã bỏ. Ba class dưới đây do
        khối XIN NGHỈ và khối ĐĂNG KÝ DẠY THAY dùng chung từ đầu; đổi tên cho "sạch"
        là phải sờ vào bảy chỗ trong thân bài, mỗi chỗ một cơ hội gõ sót — mà sót
        một chỗ thì khối ấy mất hẳn khung viền, không lỗi nào báo.
        Sáu class chỉ riêng chấm công dùng (`.lgv-cc`, `-can`, `-xong`, `-tieu`,
        `-gio`, `-muon`, `-som`) đã gỡ cùng ngày. */
  .lgv-cc-mo { margin:6px 0 0; font-size:11.5px; line-height:1.55; color:var(--mo); }
  .lgv-cc-nut { font-family:inherit; font-size:14px; font-weight:600;
      padding:9px 18px; border-radius:var(--r-sm); cursor:pointer;
      border:1px solid var(--xanh-dam); background:var(--xanh); color:#fff; }
  .lgv-cc-nut:disabled { opacity:.55; cursor:default; }
  .lgv-cc-phu { font-family:inherit; font-size:12.5px; padding:6px 13px;
      border-radius:var(--r-sm); cursor:pointer; border:1px solid var(--vien);
      background:var(--nen); color:var(--chu); }

  .lgv-nghi { margin:11px 0 0; padding:11px 12px 10px; border-radius:var(--r-md);
      border:1px solid var(--vien); background:var(--nen2); }
  .lgv-nghi.lgv-nghi-dang { border-color:var(--lgv-do-c); background:var(--lgv-do-n); }
  .lgv-nghi-tieu { font-size:13px; font-weight:600; margin:0 0 7px; }
  .lgv-nghi.lgv-nghi-dang .lgv-nghi-tieu { color:var(--lgv-do-c); }
  /* ⛔ `wrap` chứ KHÔNG BAO GIỜ `nowrap`: bốn lý do + ô tự điền mà ép một hàng
     thì ở màn hẹp chữ bị cắt cụt, người ta không đọc nổi mình đang chọn gì. */
  .lgv-lydo { display:flex; flex-wrap:wrap; gap:6px; margin:0 0 8px; }
  .lgv-lydo button { font-family:inherit; font-size:12.5px; padding:6px 12px;
      border-radius:999px; cursor:pointer; border:1px solid var(--vien);
      background:var(--nen); color:var(--chu); }
  .lgv-lydo button.chon { border-color:var(--xanh-dam); background:var(--xanh);
      color:#fff; font-weight:600; }
  .lgv-ai-lb { flex:0 0 auto; font-size:12.5px; color:var(--chu2); }
  .lgv-nghi-hang { display:flex; gap:7px; align-items:flex-start; }
  .lgv-nghi-hang input[type=text] { flex:1 1 auto; min-width:0; font-family:inherit;
      font-size:13px; padding:7px 9px; border:1px solid var(--vien);
      border-radius:var(--r-o, 8px); background:var(--nen); color:var(--chu); }
  .lgv-nghi-hang input[type=text].loi { border-color:var(--lgv-do-c); }
  .lgv-nghi-tt { margin:6px 0 0; font-size:11.5px; line-height:1.5; color:var(--mo);
      min-height:1em; }
  .lgv-nghi-tt.loi { color:var(--lgv-do-c); font-weight:600; }
  /* Cảnh báo xếp trùng giờ — VÀNG, không đỏ: đây là lời nhắc, không phải lỗi,
     vì cô Quỳnh chốt vẫn cho xếp tiếp. Đỏ là màu của "không làm được". */
  .lgv-nghi-tt.lgv-trung { color:var(--chu); font-size:12px; margin-top:8px;
      padding:9px 10px; border-radius:var(--r-sm);
      border:1px solid var(--lgv-vang-c); background:var(--lgv-vang-n); }
  .lgv-nghi-tt.lgv-trung .lgv-trung-hoi { font-weight:600; }
  .lgv-nghi-tt.lgv-trung button { margin-top:7px; margin-right:6px;
      font:inherit; font-size:12px; padding:5px 11px; cursor:pointer;
      border:1px solid var(--vien); border-radius:var(--r-sm);
      background:var(--nen); color:var(--chu); }
  .lgv-nghi-tt.lgv-trung button[data-lgv-vanxep]:hover { border-color:var(--lgv-vang-c); }
  .lgv-nghi-tt.lgv-trung button[data-lgv-thoixep] { background:var(--chinh); color:#fff;
      border-color:var(--chinh); }

  /* Danh sách người đã đăng ký nhận dạy thay — chỉ quản lý thấy. */
  .lgv-dk { margin:11px 0 0; padding:11px 12px 10px; border-radius:var(--r-md);
      border:1px solid var(--vien); background:var(--nen2); }
  .lgv-dk-tieu { font-size:13px; font-weight:600; margin:0 0 7px; }
  .lgv-dk-ds { display:flex; flex-direction:column; gap:5px; }
  .lgv-dk-ds button { font-family:inherit; font-size:13px; text-align:left;
      padding:8px 11px; border-radius:var(--r-sm); cursor:pointer;
      border:1px solid var(--vien); background:var(--nen); color:var(--chu); }
  .lgv-dk-ds button.chon { border-color:var(--lgv-xanh-c);
      background:var(--lgv-xanh-n); color:var(--lgv-xanh-c); font-weight:600; }
  .lgv-dk-trong { font-size:12px; color:var(--mo); line-height:1.55; }
  /* 👀 DẠNG CHỈ XEM — ô XANH (lớp không ai nghỉ) chỉ liệt kê ai đang rảnh giờ ấy.
     ⛔ NẰM NGANG, KHÔNG XẾP DỌC như bản có nút bấm: đây là tin tham khảo, xếp dọc
        thành cột nút là mắt đọc nhầm ra "danh sách phải chọn một người".
     ⛔ KHÔNG có viền hộp và KHÔNG con trỏ bàn tay — nhìn phải ra ngay là chữ, không
        phải nút. Bày thứ trông bấm được mà bấm không ăn là đúng lỗi cô Quỳnh chê
        hôm 29/08 (*"sao ko chọn được tự nhiên có ở đó mà ko dùng đưcọ"*). */
  .lgv-dk-ds.lgv-dk-xem { flex-direction:row; flex-wrap:wrap; gap:6px; }
  .lgv-dk-ds.lgv-dk-xem span { font-size:12.5px; padding:3px 9px; border-radius:var(--r-lg);
      background:var(--nen); border:1px solid var(--vien); color:var(--mo); }

  .lgv-suagv { margin:13px 0 0; padding:10px 11px 9px; border:1px solid var(--vien);
      border-radius:var(--r-md); background:var(--nen2); }
  .lgv-suagv label { display:block; font-size:12px; color:var(--mo); margin-bottom:5px; }
  .lgv-suagv-hang { display:flex; gap:7px; align-items:flex-start; }
  /* 👥 Từ 03/09/2026 ô đổi giáo viên có 2–5 ô (lớp hai giáo viên) — LƯỚI HAI CỘT:
     các ô xếp dọc ở cột 1, nút Lưu ở cột 2 hàng đầu.
     ⛔⛔ NÚT LƯU PHẢI Ở HÀNG ĐẦU, ĐỪNG XẾP XUỐNG DƯỚI CÁC Ô. Bảng gợi ý tên của
        `oNguoiTim` bung ra NGAY DƯỚI ô đang gõ; nút nằm dưới là bị bảng phủ kín,
        gõ xong không bấm được gì. Bản đầu của tôi 03/09 xếp nút xuống dưới đúng
        như thế và Playwright bấm 30 giây không trúng — `#ontBang` chặn con trỏ.
     ⛔ DÙNG GRID, ĐỪNG CHÈN Ô TRỐNG GIẢ cho thẳng mép: ô giả lệch ngay khi cỡ
        chữ đổi, còn grid thì mọi ô tự bằng nhau. */
  .lgv-suagv-luoi { display:grid; grid-template-columns:1fr auto; gap:6px 7px;
      align-items:start; }
  .lgv-suagv-luoi .lgv-suagv-o { grid-column:1; min-width:0; }
  .lgv-suagv-luoi .ont { min-width:0; }
  .lgv-suagv-luoi > button { grid-column:2; grid-row:1; }
  /* ⛔ `flex` PHẢI ĐẶT LÊN `.ont`, KHÔNG lên `input`. `oNguoiTim` bọc ô nhập trong
     `<div class="ont">` cùng nút mũi ▾; đặt flex lên input thì thẻ bọc co lại vừa
     nội dung và ô nhập chỉ còn một mẩu bên trái. */
  .lgv-suagv-hang .ont { flex:1 1 auto; min-width:0; }
  /* ⛔ NHẮM CẢ BA NÚT, đừng nhắm riêng `data-lgv-luugv`. Từ 03/09/2026 hàng này
     còn dùng cho thanh chọn người dạy thay (`data-lgv-luuthay`). Luật cũ chỉ nhắm
     một dấu, nên nút mới ra kiểu mặc định của trình duyệt — thô hơn hẳn mọi nút
     khác trong app, đúng thứ Boss chê là "lộ rõ ui AI". */
  .lgv-suagv-hang button[data-lgv-luugv],
  .lgv-suagv-hang button[data-lgv-luuthay] { flex:0 0 auto; font-family:inherit;
      font-size:13px; padding:6px 15px; border:1px solid var(--xanh-dam);
      border-radius:var(--r-sm); background:var(--xanh); color:#fff; cursor:pointer; }
  .lgv-suagv-hang button[data-lgv-luugv]:hover:not(:disabled),
  .lgv-suagv-hang button[data-lgv-luuthay]:hover:not(:disabled) { background:var(--xanh-dam); }
  /* "Bỏ chọn" là việc gỡ, không phải việc chính — nút phụ, nền trắng viền xám.
     Cùng màu xanh với nút Chọn thì hai nút trông ngang nhau và người ta bấm nhầm. */
  .lgv-suagv-hang button.lgv-cc-bo { flex:0 0 auto; font-family:inherit;
      font-size:13px; padding:6px 13px; border:1px solid var(--vien);
      border-radius:var(--r-sm); background:var(--the); color:var(--mo); cursor:pointer; }
  .lgv-suagv-hang button.lgv-cc-bo:hover:not(:disabled) { color:var(--chu); border-color:var(--mo); }
  .lgv-suagv-hang button[data-lgv-luugv]:disabled { opacity:.55; cursor:default; }
  .lgv-suagv-mo { margin:7px 0 0; font-size:11.5px; line-height:1.55; color:var(--mo); }
  .lgv-suagv-tt { margin:6px 0 0; font-size:11.5px; line-height:1.5; color:var(--mo);
      min-height:1em; }
  /* Lỗi phải đọc ra là lỗi ngay từ màu, đừng lẫn với câu ghi chú xám bên trên. */
  .lgv-suagv-tt.lgv-suagv-loi { color:var(--lgv-do-c); font-weight:600; }
  /* ➕ Nút tạo tài khoản, chỉ hiện khi app vừa báo "chưa có tài khoản nào tên này".
     Xuống dòng riêng (`display:block`) chứ đừng nối đuôi câu chữ đỏ: nút nằm lọt
     giữa một câu thì mắt lướt qua mất, mà đây đúng là việc cần làm tiếp. */
  .lgv-taotk-nut { display:block; margin:7px 0 0; font-family:inherit; font-size:12.5px;
      font-weight:600; padding:6px 12px; border:1px solid var(--xanh); border-radius:var(--r-md);
      background:var(--xanh); color:#fff; cursor:pointer; }
  .lgv-taotk-nut:hover:not(:disabled) { background:var(--xanh-dam); }
  .lgv-taotk-nut:disabled { opacity:.55; cursor:default; }
  .lgv-hop-nut { display:flex; gap:8px; margin-top:12px; }
  .lgv-hop-nut button { flex:1; border:1px solid var(--vien); background:var(--the);
      color:var(--chu); font-family:inherit; font-size:13px; padding:7px 12px;
      border-radius:var(--r-md); cursor:pointer; }
  .lgv-hop-nut button:hover { background:var(--nen2); }

  /* ══════════════════════════════════════════════════════════════════════════════
     ĐIỆN THOẠI — cột trái thành ngăn kéo trượt từ trái, đúng lối Google Calendar
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ CỘT TRÁI KHÔNG ĐƯỢC TỤT XUỐNG DƯỚI LỊCH. Nó giữ lịch mini + 3 ô cơ sở + 34
        giáo viên; trên màn 390px xếp dọc là nó ăn nguyên hai màn hình và cái LỊCH —
        thứ người ta mở công cụ ra để xem — bị đẩy xuống dưới hết.
     ⛔ Lưới giờ 7 cột trên màn 390px thì mỗi cột còn 46px, chữ nát hết. Nên màn hẹp
        ép về đúng một khoảng nhìn được: `min-width` cho thân lưới và cho cả hàng đầu,
        rồi CHO CUỘN NGANG TRONG `.lgv-khung` — cuộn trong khung thì THÂN TRANG không
        tràn ngang (bài kiểm đo đúng `document.body.scrollWidth`).
     ══════════════════════════════════════════════════════════════════════════════ */
  @media (max-width: 820px) {
    .lgv-ham { display:inline-block !important; }
    /* ⛔⛔ ĐÓNG NGĂN KÉO BẰNG `visibility`, ĐỪNG CHỈ ĐẨY NÓ RA NGOÀI BẰNG TRANSFORM.
       Đo thật 30/08/2026 trên màn 390px: đẩy −102% mà mép phải vẫn còn nằm ở x=+3,4
       — tức một sợi ngăn kéo 3px thò vào mép trái màn hình. Nguyên nhân là toạ độ
       của `position:fixed` trong app này không khớp đúng mép khung nhìn (app có
       phép phóng to trang), nên cứ nâng lên −105%, −110% là chữa phần ngọn.
       `visibility:hidden` chữa phần gốc, và còn được thêm một thứ quan trọng hơn:
       ngăn kéo đóng thì KHÔNG BẤM VÀO ĐƯỢC và KHÔNG NHẢY PHÍM TAB TỚI ĐƯỢC. Thiếu
       nó thì người dùng bàn phím tab một hồi là rơi vào ba chục ô tích vô hình.
       ⛔ `visibility` phải HOÃN đúng bằng thời gian trượt (`0s linear .18s`), không
          thì nó tắt ngay từ nhịp đầu và ngăn kéo biến mất phựt thay vì trượt ra. */
    /* ⛔ `max-height:none` LÀ BẮT BUỘC. Luật máy tính chặn cột trái ở
       `100vh − 258px` cho khớp khung lịch; ngăn kéo điện thoại thì `top:0;bottom:0`
       nên phải cao trọn màn, để nguyên trần kia là ngăn kéo hụt mất 258px cuối và
       mấy chục ô tích lớp nằm ngoài tầm với. */
    .lgv-ben { position:fixed; top:0; left:0; bottom:0; width:min(280px, 84vw);
        max-height:none;
        z-index:72; background:var(--the); border-right:1px solid var(--vien);
        padding:14px 12px; overflow-y:auto; transform:translateX(-102%);
        visibility:hidden; transition:transform .18s ease, visibility 0s linear .18s; }
    .lgv-man.mo-ngan .lgv-ben { transform:translateX(0); visibility:visible;
        transition:transform .18s ease, visibility 0s; }
    .lgv-man.mo-ngan .lgv-mo { display:block; position:fixed; inset:0; z-index:71;
        background:rgba(15,18,22,.38); }
    .lgv-dong-ngan { display:block !important; margin-left:auto; border:none;
        background:transparent; color:var(--mo); font-size:20px; line-height:1;
        padding:2px 6px; cursor:pointer; }
    .lgv-che { margin-left:0; }
    .lgv-tieude { font-size:14px; }
    /* ⛔ Đặt trên THÂN lưới, không đặt trên `.lgv-khung`: khung là chỗ CUỘN, cho nó
       min-width là chính nó nở ra và đẩy cả trang tràn ngang. */
    .lgv-than, .lgv-dau-hang { min-width:640px; }
    .lgv-thang { min-width:640px; }
    .lgv-o-ngay { min-height:78px; padding:4px 5px; }
    /* ⛔ TRẢ CHIỀU CAO VỀ `auto` — DÒNG NÀY LÀ BẮT BUỘC. Luật máy tính chốt chiều cao
       `.lgv-man` để hai cột kết thúc cùng chỗ; trên điện thoại cột trái là ngăn kéo
       `position:fixed` (nằm ngoài dòng flex) nên chỉ còn cột phải, mà cột phải phải
       cao theo nội dung rồi để `.lgv-khung` tự chặn. Để nguyên trần kia là màn điện
       thoại cụt mất 101px — không lỗi nào báo, chỉ thấy lịch ngắn đi.
       ⛔ `.lgv-ben { max-height:none }` ở trên vẫn là BẮT BUỘC: ngăn kéo `top:0;
          bottom:0` phải cao trọn màn. */
    /* Chú giải ba màu về MỘT HÀNG CUỘN NGANG trên màn hẹp — đo 390px: nó xuống ba
       dòng, ăn 47px trong dải nhắc 108px, mà dải ấy nằm ngay trên lưới nên mỗi
       dòng thừa là một dòng lịch mất đi.
       ⛔ ĐỪNG BỎ HẲN chú giải: ba màu ô lịch không tự giải thích được, bỏ đi là
          người xem đoán màu. Cuộn ngang thì vẫn đọc đủ mà chỉ tốn một dòng.
       ⛔ `flex:none` cho từng mục, không thì chúng co lại và chữ bị cắt cụt. */
    /* ⛔⛔ 09/09/2026 — NHƯỜNG HẾT CHỖ CÒN LẠI CHO LỊCH.
       Boss: *"phần lịch giáo viên vẫn bị gom lại 1 ô và thừa hẳn khoảng trống bên
       dưới, bạn sửa lại cho tôi cho nó chiếm hết sạch khoảng bên dưới ở trên điện
       thoại"*.
       Đo 390px sau lượt trước: lịch cao 395px, mà bên dưới nó còn ngốn 146px —
       dòng nhắc lớp hỏng 38 + chú thích chân trang 45 + thanh đáy 63. Trần đã đo
       thật rồi nên lịch không tràn nữa, nhưng vẫn chỉ được 395/844 = 47% màn.

       ① CHÚ THÍCH CHÂN TRANG ẩn trên điện thoại. Nó giải thích lịch dựng từ thứ và
          giờ cố định — đọc một lần là hiểu, không phải thứ nhìn hằng ngày, mà nó
          ăn 45px trong khi cả cái lịch chỉ có 395px. Máy tính vẫn hiện đủ.
          ⛔ Bắt bằng `.lgv-man + .cts-chan` chứ KHÔNG phải `.cts-chan` trần: lớp
             `cts-` dùng chung với màn Tuyển sinh, ẩn trần là ẩn nhầm cả bên đó.
          ⛔ Và KHÔNG dùng `:has()` — CSS mới của dự án cấm, bài kiểm canh đúng nó.
       ② DÒNG NHẮC "lớp chưa hiện trên lịch" gom về MỘT dòng: chữ và đường dẫn
          "xem danh sách" nằm cùng hàng thay vì hai hàng. 38px → ~22px.
          ⛔ ĐỪNG ẩn dòng này. Nó báo có lớp KHÔNG lên lịch được — giấu đi là người
             dùng tin rằng lịch đã đủ, trong khi thiếu lớp. */
    .lgv-man + .cts-chan { display:none; }
    /* Nội dung là text node + một nút inline — ĐỪNG cho : text node
       thành một mục flex, nút thành mục khác, wrap ra hai dòng và còn phình lên
       45px (đo thật, tệ hơn 38px ban đầu). Để block, chữ tự xuống dòng bình thường
       và nút nằm ngay sau câu. */
    .lgv-hong { padding:4px 8px; font-size:11.5px; line-height:1.3; }
    .lgv-chugiai { flex-wrap:nowrap; overflow-x:auto; gap:12px;
        scrollbar-width:none; }
    .lgv-chugiai::-webkit-scrollbar { display:none; }
    .lgv-chugiai > span { flex:none; white-space:nowrap; }
    .lgv-bao { padding:8px 10px; font-size:12px; }
    .lgv-man { height:auto; }
    /* ⛔ TRẦN NAY ĐO THẬT, hằng số chỉ còn là ĐƯỜNG LUI. `lgvDoTran` đặt
       `--lgv-tran` = chỗ trống thật giữa đỉnh khung và thứ nằm dưới nó (dòng nhắc
       lớp hỏng · chú thích chân trang · THANH ĐÁY). Đo 08/09 trên 390px: hằng số
       cũ cho khung cao 612px, đáy rơi xuống 940 trong khi thanh đáy che từ 781 —
       mất 159px cuối của lịch mà không có gì báo.
       ⛔ Giữ nguyên hằng số trong `var(...)`: JS không chạy thì lịch vẫn như cũ,
          không thành một khung cao vô tận đẩy trang dài mãi. */
    .lgv-khung { max-height:var(--lgv-tran, calc(100vh - 232px - var(--dnc-du, 0px))); }
  }


  /* ══════════════════════════════════════════════════════════════════════════════
     KIỂM TRA NGHE NÓI · KẾT QUẢ TEST NGHE NÓI — cô Quỳnh 14/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     ⛔ Giữ luật giao diện của dự án: không emoji, không đổ bóng, không chuyển màu
        nhiều tông, không bo góc to, không chữ nhạt. Cô Quỳnh đã chê "lộ rõ ui AI"
        ba lần rồi.
     ⛔ Phiếu kết quả phải IN RA GIẤY được: mọi thứ chỉ để điều hướng đều mang lớp
        `khong-in` và biến mất khi in.
     ══════════════════════════════════════════════════════════════════════════════ */
  .nn-tai { padding:28px; color:var(--mo); }
  .nn-thanh { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
  .nn-thanh button { border:1px solid var(--vien); background:var(--the); color:var(--chu);
      font-family:inherit; font-size:13px; padding:7px 13px; border-radius:var(--r-md); cursor:pointer; }
  .nn-thanh button:hover { border-color:var(--xanh); color:var(--xanh); }
  .nn-nut-chinh { border:none !important; background:var(--muc) !important; color:#fff !important;
      font-weight:700; }
  .nn-nut-chinh:hover { background:var(--xanh-dam) !important; }
  .nn-tim { flex:1; min-width:180px; max-width:340px; border:1px solid var(--vien);
      border-radius:var(--r-md); padding:7px 11px; font-family:inherit; font-size:13px;
      background:var(--nen-o); color:var(--chu); }
  .nn-dem { margin-left:auto; font-size:12px; color:var(--mo); font-variant-numeric:tabular-nums; }
  .nn-ma { font-size:11.5px; color:var(--mo); font-variant-numeric:tabular-nums; }
  .nn-trong { padding:34px; text-align:center; color:var(--mo); font-size:13.5px; }

  /* ── Thẻ một bài trong danh sách ── */
  /* Dải "đang hiện X trong Y" nằm hết bề ngang lưới, không lẫn vào hàng thẻ. */
  .nn-them-me { grid-column:1/-1; display:flex; flex-wrap:wrap; align-items:center; gap:10px;
    padding:11px 13px; border:1px dashed var(--vien); border-radius:var(--r-md); font-size:12.5px;
    color:var(--mo); }
  .nn-luoi { display:grid; grid-template-columns:repeat(auto-fill, minmax(248px, 1fr)); gap:11px; }
  .nn-the { text-align:left; border:1px solid var(--vien); border-radius:var(--r-lg);
      background:var(--the); padding:11px 13px; cursor:pointer; font-family:inherit;
      color:var(--chu); display:block; }
  .nn-the:hover { border-color:var(--muc); }
  .nn-the.xong { border-left:3px solid var(--o-tot); }
  /* ⛔⛔ TÊN HỌC SINH KHÔNG ĐƯỢC CẮT — cô Quỳnh 17/08/2026.
     Trước đây `.nn-the-dau b` và `.nn-the-phu` đặt `white-space:nowrap` +
     `text-overflow:ellipsis`, mà thẻ chỉ rộng ~248px và huy hiệu điểm còn giành chỗ
     cứng bên phải → "Nguyễn Thị Hoàng Bảo Ngân" cụt thành "Nguyễn Thị Hoàng Bảo…".
     Ngày 15/08 mới vá được HAI chỗ: màn Hồ sơ kiểm tra (`.kq-the`) và màn hình ≤640px
     (khối @media dòng ~6459) — nên LAPTOP và MÁY BÀN vẫn cụt suốt hai ngày.
     Nay vá thẳng ở luật gốc để mọi cỡ màn đều đủ chữ.
     Tên là thứ DUY NHẤT để nhận ra em nào: thà thẻ cao thêm một dòng còn hơn đọc nhầm.
     ⛔ Đừng đặt lại `nowrap` ở đây. Muốn gọn thì bóp cỡ chữ, đừng nuốt đuôi tên. */
  .nn-the-dau { display:flex; align-items:flex-start; gap:9px; }
  .nn-the-dau b { flex:1; min-width:0; font-size:14px; font-weight:700; line-height:1.3;
      overflow:visible; text-overflow:clip; white-space:normal; overflow-wrap:anywhere; }
  .nn-diem { flex:none; font-size:15px; font-weight:700; font-variant-numeric:tabular-nums;
      padding:1px 8px; border-radius:var(--r-sm); }
  .nn-diem.tot { background:#D7F0DE; color:#14663A; }
  .nn-diem.kha { background:#FBECCB; color:#7A5200; }
  .nn-diem.yeu { background:#FBDCDC; color:#8E2F2F; }
  .nn-diem.chua { background:var(--nen2); color:var(--mo); }
  body.toi .nn-diem.tot { background:#1D4030; color:#9BDCB4; }
  body.toi .nn-diem.kha { background:#42381A; color:#EBCB86; }
  body.toi .nn-diem.yeu { background:#452626; color:#F0AEAE; }
  /* Tên trường của em cũng vậy — cùng lý do với `.nn-the-dau b` ngay trên. */
  .nn-the-phu { font-size:12px; color:var(--mo); margin-top:3px; min-height:16px;
      line-height:1.4; overflow:visible; text-overflow:clip; white-space:normal;
      overflow-wrap:anywhere; }
  .nn-the-chan { display:flex; gap:9px; align-items:center; margin-top:8px;
      font-size:11px; color:var(--mo); }
  .nn-the-chan .nn-xem { margin-left:auto; color:var(--muc); font-weight:700; }
  .nn-xong { margin-left:auto; color:var(--o-tot); font-weight:700; }
  .nn-dodang { margin-left:auto; color:var(--cam); font-weight:700; }

  /* ══════════════════════════════════════════════════════════════════════════
     TRANG THEO NGÀY · TỔNG HỢP · HỒ SƠ MỘT EM (21/08/2026)
     ──────────────────────────────────────────────────────────────────────────
     ⛔ Giữ đúng nếp của cả app: trắng đen, viền mảnh, bo góc nhỏ, không tô nền
        mảng lớn, không gradient. Chỗ duy nhất được dùng màu là NHÃN TIẾN ĐỘ
        (đã xong / đang chấm) — nó nói một trạng thái, không phải trang trí.
     ══════════════════════════════════════════════════════════════════════════ */
  /* Hai trang — một cụm nút liền khối, kiểu thanh công cụ chứ không phải thẻ tab màu. */
  .nn-che { display:inline-flex; border:1px solid var(--vien); border-radius:var(--r-md); overflow:hidden; }
  .nn-thanh .nn-che button { border:none; border-right:1px solid var(--vien); border-radius:0;
      background:var(--the); padding:7px 15px; font-weight:600; }
  .nn-thanh .nn-che button:last-child { border-right:none; }
  .nn-thanh .nn-che button:hover { background:var(--nen2); color:var(--chu); border-color:var(--vien); }
  .nn-thanh .nn-che button.chon { background:var(--chu); color:var(--the); }
  .nn-ngay-nhan { font-size:13px; color:var(--chu); font-variant-numeric:tabular-nums; }
  .nn-ngay-nhan b { color:var(--muc); }

  /* Dải bảy ngày — mỗi ô đếm sẵn số em, khỏi phải bấm mũi tên mới biết mai có ai.
     ⛔⛔ DẢI NÀY PHẢI KHÁC MÀU VỚI THẺ HỌC SINH BÊN DƯỚI — cô Quỳnh 21/08/2026:
        *"các nút thứ 2 3 4 5 6 cn sửa sao cho nổi bật hơn chứ tôi nhìn hơi bị đồng
        màu với các block bên dưới"*. Bản cũ để `.nn-dai` trần không nền không viền,
        và mỗi ô ngày dùng ĐÚNG cặp nền-viền của thẻ học sinh (#FFFFFF + #D6D2CB) —
        trùng khít, không lệch một byte. Nay dải có nền xám nhạt bao ngoài như thanh
        công cụ của Google Sheets, ô bên trong trắng: hai tầng tách hẳn nhau.
     ⛔ Đừng gỡ `background` của `.nn-dai` cho "phẳng" — gỡ là quay lại đúng lỗi cũ. */
  .nn-dai { display:flex; gap:5px; flex-wrap:wrap; margin-bottom:14px;
      background:var(--nen2); border:1px solid var(--vien); border-radius:var(--r-sm); padding:5px; }
  .nn-dai-o { flex:1 1 84px; min-width:84px; border:1px solid var(--vien); border-radius:var(--r-sm);
      background:var(--the); padding:7px 4px 8px; cursor:pointer; font-family:inherit;
      color:var(--chu); text-align:center; }
  .nn-dai-o:hover { border-color:var(--chu); }
  /* ⛔ 09/09/2026 — BẢY Ô × 84px = 588px, KHÔNG ĐỜI NÀO VỪA 366px.
     Dải bảy ngày ở màn Test đầu vào đo được **142px** vì bảy ô bọc thành hai hàng.
     `flex:1 1 84px` là bề rộng tối thiểu, mà 84 × 7 + 6 khe × 5 = 618px.
     Hạ còn 44px: 44 × 7 + 30 = 338px, vừa một hàng trong 366px. Chữ dài nhất trong
     ô là "Chủ nhật" — đã rút xuống cỡ 10,5px và cho xuống dòng, ô vẫn đọc được.
     ⛔ CHỈ bóp NGANG. Chiều cao ô giữ nguyên vì đây là chỗ bấm bằng ngón tay, và
        vì bỏ một hàng đã lấy lại ~70px rồi. */
  @media (max-width:640px){
    .nn-dai { gap:4px; padding:4px; }
    /* ⛔ Bề rộng ô KHÔNG đặt ở đây: `css/lop.css` nạp SAU file này và đã có
       luật riêng cho `.nn-dai-o` trong khối 640px của nó — đặt ở đây là viết một
       luật không bao giờ thắng. Sửa bề rộng thì sửa bên ấy. */
    .nn-dai-thu { font-size:10.5px; }
  }
  /* ⛔ Ô ĐANG CHỌN PHẢI TÔ ĐẶC. Bản cũ tô `var(--nen2)` — lệch trắng đúng 4% độ
     sáng, gần như vô hình, nên bấm sang ngày khác nhìn như bấm hụt. App đã có sẵn
     nếp tô đặc ở `.nn-thanh .nn-che button.chon`; đây là cùng một nếp. */
  .nn-dai-o.chon { border-color:var(--muc); background:var(--muc); color:#fff; }
  .nn-dai-thu { display:block; font-size:11.5px; letter-spacing:normal;
      color:var(--mo); }
  .nn-dai-ngay { display:block; font-size:15px; font-weight:700; line-height:1.3;
      font-variant-numeric:tabular-nums; }
  .nn-dai-o.homnay .nn-dai-ngay { color:var(--muc); }
  .nn-dai-so { display:block; font-size:11px; color:var(--mo); font-variant-numeric:tabular-nums; }
  .nn-dai-o.co .nn-dai-so { color:var(--chu); font-weight:700; }
  /* Ô đang chọn tô đặc rồi thì mọi chữ bên trong phải trắng theo — không thì chữ
     xám #8C8882 nằm trên nền teal #0D8081, đọc không ra. */
  .nn-dai-o.chon .nn-dai-thu,
  .nn-dai-o.chon .nn-dai-so,
  .nn-dai-o.chon .nn-dai-ngay,
  .nn-dai-o.chon.homnay .nn-dai-ngay,
  .nn-dai-o.chon.co .nn-dai-so { color:#fff; }

  /* Thẻ một em. Em chưa có bài nào để viền đứt — nhìn lướt là biết còn phải chấm. */
  .nn-the-em.chua { border-style:dashed; }
  .nn-the-hen { margin-top:6px; display:flex; flex-direction:column; gap:2px;
      font-size:11.5px; color:var(--chu); }
  .nn-the-hen span { border-left:2px solid var(--vien); padding-left:7px; line-height:1.4; }
  .nn-them-me.nn-chua { border-style:solid; color:var(--chu); }

  /* Đầu trang hồ sơ một em. */
  .nn-em { border:1px solid var(--vien); border-radius:var(--r-lg); background:var(--the);
      padding:14px 16px 15px; margin-bottom:13px; }
  .nn-em-ten { font-size:18px; font-weight:700; line-height:1.3; }
  .nn-em-dinh { display:flex; flex-wrap:wrap; gap:2px 18px; margin-top:6px;
      font-size:13px; color:var(--chu); }
  .nn-em-dinh i { font-style:normal; color:var(--mo); }
  .nn-em-hen { margin-top:8px; padding-top:8px; border-top:1px solid var(--vien);
      font-size:12.5px; color:var(--chu); }
  .nn-em-hen i { font-style:normal; color:var(--mo); }
  /* ⛔ HAI NÚT NGANG SỨC NHAU. Một nút tô đặc một nút viền là bảo người chấm "chọn cái
     tô đặc đi" — mà nghe nói với ngữ pháp không có cái nào chính cái nào phụ. */
  .nn-em-nut { display:flex; flex-wrap:wrap; gap:9px; margin-top:12px; }
  .nn-em-nut button { border:1px solid var(--chu); background:var(--the); color:var(--chu);
      font-family:inherit; font-size:13px; font-weight:700; padding:8px 15px;
      border-radius:var(--r-md); cursor:pointer; }
  .nn-em-nut button:hover { background:var(--chu); color:var(--the); }

  /* Danh sách bài của em — một bảng hàng, không phải lưới thẻ: ở đây thứ cần so là
     NGÀY và LOẠI, mà so theo cột thì mắt chạy dọc một lần là xong. */
  .nn-bai-ds { border:1px solid var(--vien); border-radius:var(--r-lg); background:var(--the);
      overflow:hidden; }
  .nn-bai { display:flex; align-items:center; gap:12px; width:100%; text-align:left;
      border:none; border-top:1px solid var(--vien); background:none; font-family:inherit;
      color:var(--chu); padding:11px 14px; cursor:pointer; }
  .nn-bai:first-child { border-top:none; }
  .nn-bai:hover { background:var(--nen2); }
  .nn-bai-loai { flex:none; width:132px; font-size:11.5px; font-weight:700;
 color:var(--mo); line-height:1.35; }
  .nn-bai-ten { flex:1; min-width:0; font-size:13.5px; line-height:1.35;
      overflow-wrap:anywhere; }
  .nn-bai-ten i { font-style:normal; color:var(--mo); }
  .nn-bai-ngay { flex:none; font-size:12px; color:var(--mo); font-variant-numeric:tabular-nums;
      white-space:nowrap; }
  .nn-bai-nc { flex:none; width:104px; font-size:12px; color:var(--mo); text-align:right;
      overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .nn-bai-tt { flex:none; width:74px; text-align:right; font-size:11.5px; font-weight:700; }
  .nn-bai-tt.xong { color:var(--o-tot); }
  .nn-bai-tt.dodang { color:var(--cam); }

  /* ── Màn chấm ── */
  .nn-cham { display:flex; flex-direction:column; gap:14px; max-width:1080px; }
  .nn-khoi { border:1px solid var(--vien); border-radius:var(--r-lg); background:var(--the);
      padding:14px 16px 16px; }
  .nn-khoi h3 { margin:0 0 11px; font-size:13px; font-weight:700;
 color:var(--mo); }
  .nn-mo { margin:0 0 9px; font-size:12.5px; color:var(--mo); }
  .nn-o-luoi { display:grid; grid-template-columns:repeat(auto-fit, minmax(210px, 1fr)); gap:11px; }
  .nn-o { display:flex; flex-direction:column; gap:4px; }
  .nn-o.rong { grid-column:1 / -1; }
  .nn-o label { font-size:12px; color:var(--mo); font-weight:600; }
  .nn-o input, .nn-o select, .nn-o textarea { border:1px solid var(--vien); border-radius:var(--r-o, 8px);
      padding:7px 9px; font-family:inherit; font-size:13px; background:var(--nen-o);
      color:var(--chu); width:100%; }
  .nn-o textarea { resize:vertical; line-height:1.5; }

  /* ── Lần hỏi ── */
  .nn-lan-o { border:1px solid var(--vien); border-radius:var(--r-md); padding:11px 12px;
      margin-bottom:9px; display:grid; grid-template-columns:repeat(auto-fit, minmax(210px, 1fr));
      gap:10px; }
  .nn-lan-so { grid-column:1 / -1; font-size:12px; font-weight:700; color:var(--muc);
      display:flex; align-items:center; gap:8px; }
  .nn-bo-lan { border:none; background:transparent; color:var(--do); cursor:pointer;
      font-size:15px; line-height:1; padding:0 4px; font-family:inherit; }
  .nn-them-lan { border:1px dashed var(--vien); background:transparent; color:var(--mo);
      border-radius:var(--r-md); padding:7px 13px; font-family:inherit; font-size:12.5px; cursor:pointer; }
  .nn-them-lan:hover { border-color:var(--muc); color:var(--muc); }

  /* ── Một tiêu chí chấm ──
     ⛔ HIỆN NGUYÊN CÂU MÔ TẢ trên từng nút mức, không chỉ hiện "3/4". Người chấm phải
        đọc mô tả mới chấm đúng — đó là cả lý do form gốc viết câu dài như vậy. */
  .nn-tc { padding:11px 0; border-top:1px solid var(--vien); }
  .nn-tc:first-of-type { border-top:none; padding-top:0; }
  .nn-tc-ten { display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; margin-bottom:8px; }
  .nn-tc-ten b { font-size:14px; font-weight:700; }
  .nn-tc-anh { font-size:11.5px; color:var(--mo); font-style:italic; }
  .nn-tc-mo { font-size:11.5px; color:var(--mo); }
  .nn-muc { display:grid; grid-template-columns:repeat(auto-fit, minmax(210px, 1fr)); gap:8px; }
  .nn-muc-nut { text-align:left; border:1px solid var(--vien); border-radius:var(--r-md);
      background:var(--the); color:var(--chu); font-family:inherit; cursor:pointer;
      padding:9px 11px; display:flex; flex-direction:column; gap:4px; }
  .nn-muc-nut:hover { border-color:var(--muc); }
  .nn-muc-nut.chon { border-color:var(--muc); background:var(--xanh-nhat); }
  .nn-muc-so { font-size:12px; font-weight:700; color:var(--muc); font-variant-numeric:tabular-nums; }
  .nn-muc-chu { font-size:12px; line-height:1.45; }

  /* ── Lớp phù hợp ── */
  .nn-diem-tam { margin-left:auto; font-size:12.5px; font-weight:700; color:var(--mo);
      font-variant-numeric:tabular-nums; }
  .nn-diem-tam.tot { color:#14663A; }
  .nn-diem-tam.kha { color:#7A5200; }
  .nn-diem-tam.yeu { color:#8E2F2F; }
  body.toi .nn-diem-tam.tot { color:#9BDCB4; }
  body.toi .nn-diem-tam.kha { color:#EBCB86; }
  body.toi .nn-diem-tam.yeu { color:#F0AEAE; }

  .nn-lop { display:grid; grid-template-columns:repeat(auto-fit, minmax(226px, 1fr)); gap:8px;
      margin-bottom:12px; }
  .nn-lop-o { border:1px solid var(--vien); border-radius:var(--r-md); padding:8px 10px;
      display:flex; align-items:center; gap:9px; }
  .nn-lop-o.chon { border-color:var(--muc); background:var(--xanh-nhat); }
  .nn-lop-ten { flex:1; min-width:0; display:flex; align-items:center; gap:7px;
      font-size:12.5px; font-weight:600; cursor:pointer; }
  .nn-lop-ten input { flex:none; width:14px; height:14px; accent-color:var(--muc); margin:0; }
  .nn-chang { display:flex; gap:3px; }
  .nn-chang-nut { border:1px solid var(--vien); background:var(--the); color:var(--mo);
      border-radius:var(--r-sm); padding:2px 7px; font-family:inherit; font-size:11px; cursor:pointer; }
  .nn-chang-nut.chon { background:var(--muc); color:#fff; border-color:var(--muc); font-weight:700; }
  /* Nút xoá một lớp khỏi DANH SÁCH — mờ sẵn, chỉ rõ lên khi rê vào ô đó. Để rõ sẵn
     thì mắt cứ bị kéo vào mấy dấu × trong khi việc chính là tick chọn lớp. */
  .nn-lop-xoa { flex:none; border:none; background:transparent; color:var(--mo);
      font-size:16px; line-height:1; padding:0 3px; cursor:pointer; opacity:.35;
      font-family:inherit; }
  .nn-lop-o:hover .nn-lop-xoa { opacity:1; color:var(--do); }
  .nn-lop-them { grid-column:1 / -1; border:1px dashed var(--vien); background:transparent;
      color:var(--mo); border-radius:var(--r-md); padding:8px 13px; font-family:inherit;
      font-size:12.5px; cursor:pointer; }
  .nn-lop-them:hover { border-color:var(--muc); color:var(--muc); }
  .nn-goi { font-weight:400; color:var(--mo); font-size:11px; }

  /* ── Hai phần tách hẳn: thanh chuyển ── */
  .nn-phan { display:flex; gap:0; margin-bottom:14px; border:1px solid var(--vien);
      border-radius:var(--r-md); overflow:hidden; width:fit-content; max-width:100%; flex-wrap:wrap; }
  .nn-phan-nut { border:none; border-right:1px solid var(--vien); background:var(--the);
      color:var(--chu); font-family:inherit; font-size:13px; font-weight:600;
      padding:9px 16px; cursor:pointer; }
  .nn-phan-nut:last-child { border-right:none; }
  .nn-phan-nut.chon { background:var(--muc); color:#fff; font-weight:700; }

  /* ── Chọn phiếu ── */
  .nn-de-nhom { margin-bottom:12px; }
  .nn-de-nhom h4 { margin:0 0 7px; font-size:11.5px; font-weight:700;
 color:var(--mo); }
  .nn-de-ds { display:grid; grid-template-columns:repeat(auto-fit, minmax(238px, 1fr)); gap:7px; }
  .nn-de-o { display:flex; align-items:center; gap:8px; border:1px solid var(--vien);
      border-radius:var(--r-md); padding:8px 11px; cursor:pointer; font-size:12.5px; }
  .nn-de-o.chon { border-color:var(--muc); background:var(--xanh-nhat); }
  .nn-de-o input { flex:none; width:14px; height:14px; accent-color:var(--muc); margin:0; }
  .nn-de-ten { flex:1; min-width:0; font-weight:600; }
  .nn-de-so { flex:none; font-size:11px; color:var(--mo); font-variant-numeric:tabular-nums; }

  /* ── Bảng điền số câu đúng ── */
  .nn-de-bang { border:1px solid var(--vien); border-radius:var(--r-md); margin-top:12px; overflow:hidden; }
  .nn-de-dau { display:flex; align-items:baseline; gap:10px; padding:9px 12px;
      background:var(--nen2); border-bottom:1px solid var(--vien); }
  .nn-de-dau b { font-size:13px; }
  .nn-de-tong { margin-left:auto; font-size:12px; font-weight:700; color:var(--muc);
      font-variant-numeric:tabular-nums; }
  .nn-bang { width:100%; border-collapse:collapse; font-size:12.5px; }
  .nn-bang th { text-align:left; font-size:11px; font-weight:700; color:var(--mo);
 padding:6px 12px;
      border-bottom:1px solid var(--vien); }
  .nn-bang td { padding:5px 12px; border-bottom:1px solid var(--vien); vertical-align:top; }
  .nn-bang tr:last-child td { border-bottom:none; }
  /* Dòng đầu của một chủ đề nhiều mục: kẻ đậm hơn để mắt tách được nhóm. */
  .nn-bang tr.dau-nhom td { border-top:2px solid var(--vien); }
  .nn-bang .c-lv { width:120px; color:var(--mo); font-size:11.5px;
      font-variant-numeric:tabular-nums; white-space:nowrap; }
  .nn-bang .c-cd b { display:block; margin-bottom:2px; }
  .nn-bang .c-cd .con { display:block; padding-left:12px; color:var(--chu); }
  .nn-bang .c-so { width:118px; white-space:nowrap; text-align:right; }
  .nn-bang .c-so input { width:56px; border:1px solid var(--vien); border-radius:var(--r-o, 8px);
      padding:4px 7px; font-family:inherit; font-size:13px; text-align:center;
      background:var(--nen-o); color:var(--chu); font-variant-numeric:tabular-nums; }
  .nn-bang .c-so .tren { margin-left:4px; color:var(--mo); font-size:12px;
      font-variant-numeric:tabular-nums; }
  @media (max-width: 700px) {
    .nn-bang .c-lv { display:none; }
  }

  /* ── Phần bài viết trên phiếu phụ huynh ── */
  .kq-viet { border:1px solid var(--vien); border-radius:var(--r-md); padding:12px 14px;
      margin-bottom:11px; }
  .kq-viet-dau { display:flex; align-items:baseline; gap:10px; }
  .kq-viet-dau b { font-size:14.5px; }
  .kq-viet-so { margin-left:auto; font-size:14px; font-weight:700; color:var(--xanh-dam);
      font-variant-numeric:tabular-nums; }
  /* Thanh dài tô tới đúng tỉ lệ đúng — nhìn phát biết ngay. */
  .kq-vach { height:9px; border:1px solid var(--vien); border-radius:var(--r-sm); overflow:hidden;
      margin:8px 0 5px; }
  .kq-vach span { display:block; height:100%; background:var(--xanh); }
  .kq-viet-chan { font-size:11.5px; color:var(--mo); font-variant-numeric:tabular-nums; }
  .kq-cd { width:100%; border-collapse:collapse; margin-top:9px; font-size:12.5px; }
  .kq-cd td { padding:4px 0; border-bottom:1px solid var(--vien); }
  .kq-cd tr:last-child td { border-bottom:none; }
  .kq-cd .c-ten { line-height:1.45; }
  .kq-cd .c-so { width:64px; text-align:right; font-weight:700;
      font-variant-numeric:tabular-nums; white-space:nowrap; }
  .kq-cd .c-so.tot { color:#1B8A4B; }
  .kq-cd .c-so.kha { color:#B8860B; }
  .kq-cd .c-so.yeu { color:#B04141; }

  /* ══════════════════════════════════════════════════════════════════════════════
     PHIẾU KẾT QUẢ — MÀN CHO PHỤ HUYNH XEM
     ⛔ Đây là thứ duy nhất trong app người NGOÀI nhìn vào. Chữ to hơn màn nội bộ,
        khoảng cách rộng hơn, và không có một mã số nội bộ nào lọt ra.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ══════════════════════════════════════════════════════════════════════════════
     PHIẾU MANG MÀU TRUNG TÂM — cô Quỳnh 14/08/2026: *"trang trí cái phiếu kết quả
     này có logo MyPAS ở bên góc phải trên cùng phiếu, cho có màu của trung tâm nữa
     để đẹp hơn"*.
     Hai màu lấy đúng logo: teal #14A0A0 (chữ PAS, thanh điều hướng) và cam #F5821F
     (chữ My, sóng banner).
     ⛔ Dùng màu ở VIỀN và VẠCH, không tô nền cả mảng. Tô nền mảng lớn thì in ra tốn
        mực, mà bản in đen trắng lại thành một khối xám che mất chữ.
     ⛔ Không chuyển màu nhiều tông, không đổ bóng — luật giao diện của dự án.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ══════════════════════════════════════════════════════════════════════════════
     TRANG ĐIỀN NỐT THÔNG TIN (kq-form) VÀ TỜ PHIẾU GỬI PHỤ HUYNH (pt-*)
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh 15/08/2026. Hai màn khác hẳn nhau về mục đích nên để riêng:
       .kq-form  — màn NHẬP, cho nhân viên, ở trên máy;
       .pt-to    — tờ GIẤY, cho phụ huynh, phải in ra vừa khổ A4.
     ⛔ Giao diện nghiêm túc: không bo góc to, không đổ bóng màu, không chữ nhạt.
        Tờ phiếu này phụ huynh cầm đi đóng tiền, phải đọc được rõ khi in đen trắng. */
  .kq-form { max-width:960px; margin:0 auto; }
  .kq-form-dau { margin:14px 0 4px; font-size:18px; }
  .kq-form-mo { margin:0 0 14px; font-size:12.5px; color:var(--mo); line-height:1.55; }
  .kq-fs { border:1px solid var(--vien); border-radius:var(--r-md); padding:12px 14px; margin-bottom:12px;
    background:var(--the); }
  .kq-fs > h3 { margin:0 0 10px; font-size:12.5px; font-weight:700;
 color:var(--muc); display:flex; align-items:center; gap:10px; }
  .kq-hang2, .kq-hang3 { display:grid; gap:10px; }
  .kq-hang2 { grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); }
  .kq-hang3 { grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); }
  .kq-o-nhap { display:flex; flex-direction:column; gap:4px; }
  .kq-o-nhap > label { font-size:12px; color:var(--mo); }
  .kq-o-nhap > input { border:1px solid var(--vien); border-radius:var(--r-o, 8px); padding:7px 9px;
    font:inherit; font-size:13px; background:var(--the); color:var(--chu); min-width:0; }
  .kq-o-nhap > input:focus { outline:none; border-color:var(--xanh); }
  .kq-o-dai > input { width:100%; }

  /* Bảng nhập nhiều dòng — dùng lưới chứ không dùng <table>, để thêm/bớt dòng khỏi
     phải dựng lại cả bảng. */
  .kq-bang-nhap { display:flex; flex-direction:column; gap:6px; }
  .kq-bn-dau, .kq-bn-hang { display:grid; gap:6px; align-items:center;
    grid-template-columns:1fr 1fr 1fr 1fr 1fr 30px; }
  /* Học phí: ô chọn gói ở đầu, nút Lưu gói ở cuối. */
  /* ⛔ 21/08/2026 — CÒN NĂM CỘT. Bản cũ bảy cột: cột đầu là ô chọn gói, cột cuối là
     nút "Lưu gói"; cả hai đã bỏ theo yêu cầu cô Quỳnh (xem `kqVeBangPhi`).
     Bỏ cột mà quên sửa dòng này thì hàng tiêu đề lệch hẳn một ô so với hàng nhập —
     "Từ ngày" đứng trên ô "Đến ngày". */
  /* ⛔ 09/09/2026 — SÁU CỘT: thêm cột nút × ở cuối (Boss cho thêm/bớt mốc học phí).
     30px khớp đúng cột nút xoá của bảng Xếp lớp ngay trên — hai bảng đứng cạnh nhau
     trong cùng một tờ phiếu, lệch nhau là nhìn ra ngay. */
  .kq-bn-dau.kq-bn-phi, .kq-bn-hang.kq-bn-phi {
    grid-template-columns:1fr 1fr .75fr 1.05fr 1.2fr 30px; }
  /* Ô Tổng là con số ĐÍCH của cả hàng — in đậm, chữ số thẳng cột. */
  .kq-phi-tong { font-weight:700; font-variant-numeric:tabular-nums; }
  .kq-bn-hang > select { border:1px solid var(--vien); border-radius:var(--r-o, 8px); padding:6px 8px;
    font:inherit; font-size:12.5px; background:var(--the); color:var(--chu); min-width:0; }
  .kq-luu-goi { white-space:nowrap; }
  /* Khối quy định chỉ để XEM — nền chìm hơn một chút để phân biệt với ô nhập. */
  .kq-qd-xem { border:1px solid var(--vien); border-radius:var(--r-md); padding:10px 13px;
    background:var(--nen2); max-height:300px; overflow:auto; font-size:12.5px; line-height:1.6; }
  .kq-qd-muc { font-weight:700; font-size:11.5px; margin:9px 0 4px;
    color:var(--muc); }
  .kq-qd-xem > .kq-qd-muc:first-child { margin-top:0; }
  .kq-qd-d { padding:1px 0; }
  .kq-qd-con { padding-left:18px; color:var(--mo); }
  .kq-goi-ds { display:flex; flex-wrap:wrap; align-items:center; gap:7px; margin-top:9px;
    font-size:12px; color:var(--mo); }
  .kq-goi-chip { display:inline-flex; align-items:center; gap:6px; border:1px solid var(--vien);
    border-radius:var(--r-sm); padding:3px 4px 3px 9px; color:var(--chu); font-size:12px; }
  .kq-goi-chip button { border:none; background:none; color:var(--mo); cursor:pointer;
    font-size:15px; line-height:1; padding:0 3px; }
  .kq-goi-chip button:hover { color:var(--do); }
  .kq-bn-dau > span { font-size:11.5px; color:var(--mo); padding-left:2px; }
  .kq-bn-hang > input { border:1px solid var(--vien); border-radius:var(--r-o, 8px); padding:6px 8px;
    font:inherit; font-size:13px; background:var(--the); color:var(--chu); min-width:0; }
  .kq-bn-hang > input:focus { outline:none; border-color:var(--xanh); }
  .kq-bn-xoa { border:1px solid var(--vien); border-radius:var(--r-sm); background:var(--the);
    color:var(--mo); width:30px; height:30px; cursor:pointer; font-size:16px; line-height:1; }
  .kq-bn-xoa:hover { border-color:var(--do); color:var(--do); }

/* ══════════════════════════════════════════════════════════════════════════════
   🔤 BE VIETNAM PRO — FONT RIÊNG CỦA TỜ PHIẾU GỬI PHỤ HUYNH (Boss 20/09/2026)
   ──────────────────────────────────────────────────────────────────────────────
   Boss: *"Bạn thiết kế lại cái chữ ở phiếu xuất pdf gửi phụ huynh sửa lại font
   chữ là font google sans cho nó đẹp"*.

   ⛔ VÌ SAO KHÔNG PHẢI "Google Sans": đó là font riêng của Google, không phát
      hành công khai — khai tên ấy trong CSS thì máy nào cũng không có, trình
      duyệt lặng lẽ rơi về font hệ điều hành và tờ phiếu y như cũ. Be Vietnam Pro
      là font Việt cùng họ chữ không chân, do người Việt dựng, bộ dấu tiếng Việt
      đầy đủ và dựng sẵn — đúng thứ tờ phiếu này cần. Boss đã chốt bằng nút bấm.

   ⛔ NHÚNG FILE VÀO APP, KHÔNG GỌI fonts.googleapis.com (Boss chốt). App chạy
      trong mạng nội bộ của trung tâm; máy nào chặn Google là tờ phiếu về font
      hệ điều hành mà không ai biết. Nhúng thì in ở đâu cũng ra một kiểu.

   ⛔ SÁU FILE, KHÔNG PHẢI BA. Mỗi nét chữ phải có RIÊNG bản `vietnamese`: bộ
      `latin` KHÔNG chứa chữ có dấu tiếng Việt. Thiếu bản ấy thì chữ thường ra
      đúng font còn chữ có dấu rơi về font khác — một dòng hai kiểu chữ, đúng
      thứ trông rõ là máy làm. `unicode-range` chép nguyên từ Google Fonts.

   ⛔ `font-display: swap` — chữ hiện ngay bằng font tạm rồi đổi sang khi font
      về. Để mặc định thì tờ phiếu trắng trơn mất 3 giây, người dùng tưởng treo.
   ⛔ Ba nét 400/600/700 là đủ cho tờ này (chữ chạy · tên mục · tiêu đề). Thêm
      nét là thêm file phải tải, mà mắt không phân biệt nổi.
   ══════════════════════════════════════════════════════════════════════════════ */
  @font-face { font-family:"Be Vietnam Pro"; font-style:normal;
    font-weight:400; font-display:swap;
    src:url("/font/be-vietnam-pro-400-vietnamese.woff2") format("woff2");
    unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
  @font-face { font-family:"Be Vietnam Pro"; font-style:normal;
    font-weight:400; font-display:swap;
    src:url("/font/be-vietnam-pro-400-latin.woff2") format("woff2");
    unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
  @font-face { font-family:"Be Vietnam Pro"; font-style:normal;
    font-weight:600; font-display:swap;
    src:url("/font/be-vietnam-pro-600-vietnamese.woff2") format("woff2");
    unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
  @font-face { font-family:"Be Vietnam Pro"; font-style:normal;
    font-weight:600; font-display:swap;
    src:url("/font/be-vietnam-pro-600-latin.woff2") format("woff2");
    unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
  @font-face { font-family:"Be Vietnam Pro"; font-style:normal;
    font-weight:700; font-display:swap;
    src:url("/font/be-vietnam-pro-700-vietnamese.woff2") format("woff2");
    unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
  @font-face { font-family:"Be Vietnam Pro"; font-style:normal;
    font-weight:700; font-display:swap;
    src:url("/font/be-vietnam-pro-700-latin.woff2") format("woff2");
    unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
  /* ── TỜ PHIẾU GỬI PHỤ HUYNH ────────────────────────────────────────────────
     Khổ ngang cố định 780px ≈ đúng bề ngang chữ của A4 có lề 15mm. Cố định chứ không
     co giãn theo màn hình: nhìn trên máy thế nào thì in ra đúng thế ấy, không có
     chuyện màn rộng thì chữ dàn ra mà in lại xuống dòng chỗ khác. */
  /* ══════════════════════════════════════════════════════════════════════════════
     MÀU THƯƠNG HIỆU TRÊN TỜ GỬI PHỤ HUYNH — cô Quỳnh 15/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     *"lúc xuất file PDF export nên có thêm viền màu MyPAS và thêm màu đặc trưng của
     MyPAS để gửi đi đẹp và chuyên nghiệp, nhận diện được màu thương hiệu."*

     Dùng ĐÚNG hai màu đã có trong app, không bịa màu mới:
        teal #14A0A0 (--xanh) và cam #F5821F (--cam).
     Theo đúng lối vạch của phiếu nội bộ (.kq-phieu::before) để hai tờ nhìn là cùng
     một nhà.
     ⛔ Vẫn giữ lối business: chỉ vạch và viền mảnh, KHÔNG tô nền màu cả mảng. Tờ này
        phụ huynh cầm đi đóng tiền và trung tâm hay in đen trắng — tô đậm là chữ chìm.
     ⛔ Màu phải IN RA ĐƯỢC. Trình duyệt mặc định bỏ hết nền màu khi in, nên chỗ nào
        cần giữ màu phải khai print-color-adjust (xem khối @media print).
     ══════════════════════════════════════════════════════════════════════════════ */
  .pt-to { width:780px; max-width:100%; margin:14px auto; background:#fff; color:#16202A;
    border:1px solid #C9D6DB; border-top:none; border-radius:6px;
    /* ⛔ ĐỪNG GỠ DÒNG font-family NÀY. Không có nó, cả tờ phiếu ăn font giao diện của
       `body` — tức font MENU của Windows nằm trên giấy tờ gửi phụ huynh.

       📐 20/09/2026 — BE VIETNAM PRO THAY TIMES NEW ROMAN. Boss: *"thiết kế lại
       cái chữ ở phiếu xuất pdf gửi phụ huynh sửa lại font chữ là font google sans
       cho nó đẹp"*, và chốt bằng nút bấm là áp cho CẢ TỜ, nhúng file vào app.

       ⛔ LUẬT CŨ (cô Quỳnh 21/08/2026, *"font chữ phổ biến trong giấy báo cáo,
          VD: Word"* → Times New Roman) NAY HẾT HIỆU LỰC — lệnh mới hơn thắng.
          Giữ lại câu ấy ở đây để ai đọc mã sau không tưởng là mã bị hỏng rồi đi
          "sửa" về Times.
       ⛔ Ba tên sau là ĐƯỜNG LUI, không phải trang trí: máy chưa tải xong sáu file
          font thì chữ vẫn đọc được bằng font gần giống. Đừng để trơ một tên.
       ⛔ Khai ở ĐÂY, không khai trên `body` — Boss chốt CHỈ tờ phiếu này đổi font,
          cả app vẫn giữ font cũ. Khai lên `body` là đổi mặt chữ của 29 màn.
       ⛔ Sáu khối `@font-face` nằm ngay TRƯỚC khối `.pt-to` này, đừng tách xa ra. */
    font-family:"Be Vietnam Pro", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    /* Cỡ 14px chứ không 13px: font chân có phần thân chữ thấp hơn font giao diện, giữ
       nguyên 13px là chữ trông nhỏ đi thấy rõ so với bản cũ. Bản in vẫn 12px như cũ. */
    padding:0 30px 30px; font-size:14px; line-height:1.6; overflow:hidden; }
  /* ══════════════════════════════════════════════════════════════════════════════
     ⭐⭐ TỜ GỬI PHỤ HUYNH — BẢNG MÀU RÚT XUỐNG CÒN MỘT SẮC, 21/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"thiết kế lại hồ sơ khi export pdf phải thật đẹp và ít màu lại nhiều
     quá có màu thương hiệu là tốt nhưng ko được quá nhiều TRONG CHỮ"*.

     ⛔ TÔI ĐÃ ĐẾM BẰNG MÁY (dựng tờ phiếu trong trình duyệt rồi đọc `getComputedStyle`
        của từng phần tử): tờ cũ có BẢY màu chữ — đen #16202A, teal đậm #0D8081 ×13,
        XANH DƯƠNG #0B5FA5 ×5, teal sáng #14A0A0 ×2, CAM #F5821F, #33424F, #44525E.
        Xanh dương chẳng dính gì tới thương hiệu; cam thì đúng là màu MyPAS nhưng đem
        gạch chân tiêu đề thì nó chỉ còn là một vệt màu lạ.

     LUẬT TỪ NAY, ba dòng, đừng phá:
       ① CHỮ CHẠY LUÔN LÀ ĐEN #16202A. Không tô màu chữ để "cho đẹp".
       ② MÀU THƯƠNG HIỆU CHỈ ĐI VỚI KẾT CẤU: số thứ tự mục, nét kẻ, nền hàng tiêu đề
          bảng, và cái vạch đầu tờ. Nó chỉ đường, không phải nội dung.
       ③ CAM CHỈ CÒN TRONG LOGO — đúng chỗ nó vốn thuộc về. Bỏ khỏi mọi chỗ khác.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* Vạch thương hiệu vắt ngang đầu tờ. MỘT tông — bản cũ chia 68% teal / 32% cam,
     nhìn như một thanh tiến trình đang chạy dở chứ không như một dấu nhận diện. */
  .pt-to::before { content:""; display:block; height:5px; margin:0 -30px 22px;
    background:#0D8081;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  body.toi .pt-to { background:#fff; color:#16202A; }
  .pt-dau { display:flex; align-items:flex-start; justify-content:space-between; gap:20px; }
  /* ⛔ MỘT sắc xám phụ duy nhất là #5A6672. Tờ cũ có ba sắc gần giống nhau (#33424F,
     #44525E, #555) — mắt không phân biệt nổi, nên chúng chẳng nói lên điều gì, chỉ
     làm dài thêm danh sách màu. */
  .pt-dau-phai { text-align:right; font-size:11.5px; font-weight:700; color:#16202A; }
  /* ⛔ TÊN TỜ LÀ CHỮ ĐEN, không phải chữ teal. Luật ① ở khối bảng màu: màu thương
     hiệu đi với KẾT CẤU, không đi với chữ. Vệt màu chuyển xuống cái gạch dưới —
     ở đó nó làm đúng việc của nó là chỉ chỗ, mà không ăn vào chữ. */
  .pt-tieude { margin:16px 0 4px; font-size:20px; text-align:center; letter-spacing:normal;
    color:#16202A; font-weight:700; }
  /* Gạch dưới TEAL, không phải cam — cam nay chỉ còn trong logo. */
  .pt-tieude::after { content:""; display:block; width:54px; height:3px; margin:8px auto 0;
    background:#0D8081; border-radius:2px;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-khoi { margin-bottom:10px; }
  /* ⛔ MỌI LUẬT DƯỚI ĐÂY GẮN TIỀN TỐ `.pt-to`. Xem lời cảnh báo dài ở luật `.pt-muc`
     phía trên: cùng một tên lớp còn được form chấm điểm dùng cho việc khác. */
  /* ⛔ MỘT KIỂU TIÊU ĐỀ MỤC DUY NHẤT cho cả tờ (xem `ptMuc`). Bản cũ có bốn kiểu:
     viền trái teal, chữ đậm suông, gạch chân cam, và h1 — đọc xuống không biết mình
     đang ở mục thứ mấy. Nay: số trong ô teal + tên mục + nét kẻ chạy hết dòng. */
  /* ⛔ 21/08/2026 (tối) — ĐỪNG ĐẶT LẠI `text-transform:uppercase` VÀ
     `letter-spacing` Ở ĐÂY. Cô Quỳnh chê tờ phiếu *"nhìn siêu lộ AI"* và dặn *"để
     nét chữ thật bình thường đi"*. Chữ IN HOA TOÀN BỘ + giãn chữ là công thức nhãn
     nhỏ của giao diện web; văn bản hành chính thật viết chữ thường, in đậm.
     ⛔ Và nét 700 chứ không 800: font hệ thống không có nét 800, máy phải bôi giả. */
  .pt-to .pt-muc { display:flex; align-items:center; gap:9px; margin:20px 0 9px;
    color:#16202A; font-weight:700; font-size:14px; padding-left:0; border:none;
    text-transform:none; letter-spacing:normal; }
  .pt-to .pt-muc::after { content:""; flex:1; height:1px; background:#D3DCE2;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-to .pt-muc-so { flex:none; width:19px; height:19px; border-radius:2px; background:#0D8081;
    color:#fff; font-size:11.5px; font-weight:700; letter-spacing:0;
    display:inline-flex; align-items:center; justify-content:center;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-to .pt-muc-ten { flex:none; }
  /* Tiêu đề PHỤ nằm TRONG một mục (ví dụ "Bảng chấm điểm chi tiết" thuộc mục ①).
     Không có số, chữ nhỏ hơn — để phụ huynh không đếm nhầm thành mục thứ bảy. */
  .pt-to .pt-muc2 { margin:13px 0 6px; font-weight:700; font-size:13px;
    color:#16202A; text-transform:none; letter-spacing:normal; }
  /* Bốn dòng hồ sơ học sinh xếp hai cột — xem lời giải thích ở `kqVePhieuTra`. */
  /* ⛔ 21/08/2026 (tối) — KHÔNG NỀN TÔ, KHÔNG BO GÓC. Bản cũ là một tấm thẻ nền
     #F7FAFA bo 6px nằm giữa tờ giấy — đúng lối "card" của giao diện web, thứ cô
     Quỳnh gọi là lộ AI. Nay chỉ còn khung kẻ mảnh, góc vuông, nền trắng như giấy.
     ⛔ Hai dòng print-color-adjust GIỮ NGUYÊN dù nền nay trong suốt: bài kiểm
        thu-phieu-tra.js đếm số lần chuỗi ấy xuất hiện và đòi ít nhất 8. */
  .pt-to .pt-hoso { display:grid; grid-template-columns:1fr 1fr; gap:2px 26px;
    margin-bottom:4px; padding:10px 13px; border:1px solid #C7D0D8; border-radius:0;
    background:transparent;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-to .pt-hoso .pt-nhan { width:auto; min-width:132px; }
  .pt-dong { display:flex; gap:10px; padding:2px 0; }
  .pt-nhan { flex:none; width:118px; font-weight:700; }
  .pt-gt { flex:1; min-width:0; }
  /* Mỗi mục có một vạch teal đứng bên trái — mắt lướt xuống là biết chỗ nào bắt đầu. */
  .pt-muc { margin:14px 0 6px; font-weight:700; color:#0D8081; padding-left:9px;
    border-left:3px solid #14A0A0;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-bang { border-collapse:collapse; width:100%; margin-bottom:10px; }
  .pt-bang th, .pt-bang td { border:1px solid #C7D0D8; padding:5px 8px; text-align:left;
    font-size:12.5px; }
  /* ⛔ Chữ hàng tiêu đề là ĐEN, không phải teal (luật ② ở khối trên). Nền nhạt đã đủ
     tách nó khỏi phần thân bảng rồi; tô thêm chữ là màu chồng màu. */
  .pt-bang th { background:#EFF5F5; font-weight:700; color:#16202A;
    border-color:#A9CFCF; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  /* Hai cột: chương trình bên trái, bảng lớp bên phải — đúng ảnh mẫu. Màn hẹp thì
     xuống dòng, không ép ngang cho cụt chữ. */
  /* ── BẢNG CHẤM ĐIỂM TRÊN TỜ GỬI PHỤ HUYNH (21/08/2026) ────────────────────
     ⛔ TỜ NÀY IN RA GIẤY A4. Ba luật của khối in đã ghi ở trên vẫn phải theo:
        · dùng màu ở VIỀN và CHỮ, không tô nền mảng lớn (in ra tốn mực, mà máy in
          đen trắng thì mảng nền thành một vũng xám nuốt mất chữ)
        · không để một phần bị cắt đôi giữa hai trang giấy
        · cỡ chữ nhỏ hơn phần chính một nấc — đây là phần tra cứu, không phải phần
          đọc đầu tiên */
  .pt-cham { margin-bottom:10px; }
  .pt-cham-phan { margin-bottom:9px; break-inside:avoid; page-break-inside:avoid; }
  .pt-cham-ten { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap;
    font-weight:700; font-size:12.5px; color:#16202A; margin-bottom:3px; }
  .pt-cham-diem { margin-left:auto; font-weight:700; color:#1F1D1A;
    font-variant-numeric:tabular-nums; white-space:nowrap; }
  .pt-cham-chu { font-size:11.5px; color:#5A6672; margin-bottom:4px; }
  .pt-bang-cham td { font-size:11.5px; }
  .pt-bang-cham i { font-style:italic; color:#777; font-weight:400; }
  .pt-cham-so { text-align:center; font-weight:700; white-space:nowrap;
    font-variant-numeric:tabular-nums; width:56px; }
  /* Bảng chủ đề dùng chung với phiếu nội bộ (nnBangChuDePhieu → .kq-cd). Trên tờ
     giấy phải thu nhỏ lại một nấc cho vừa khổ. */
  .pt-cham .kq-cd { width:100%; border-collapse:collapse; font-size:11px; margin-top:2px; }
  .pt-cham .kq-cd td { border:1px solid #C7D0D8; padding:3px 7px; }
  .pt-cham .kq-cd .c-so { text-align:center; width:66px; white-space:nowrap;
    font-variant-numeric:tabular-nums; font-weight:700; }
  /* ── BẢNG SO SÁNH HỌC PHÍ (xem `ptBangPhi` để biết vì sao đổi) ───────────── */
  .pt-phi-moi { margin:0 0 7px; font-size:12.5px; color:#5A6672; }
  .pt-bang-phi { width:auto; min-width:min(100%, 460px); }
  .pt-bang-phi th[scope="row"] { background:#FBFCFC; font-weight:600; color:#16202A;
    white-space:nowrap; }
  .pt-bang-phi thead th { text-align:center; }
  /* ⛔ CĂN PHẢI + CHỮ SỐ ĐỀU CHIỀU RỘNG. Căn trái thì 6.480.000 và 12.240.000 lệch
     hàng đơn vị, liếc qua tưởng hai kỳ suýt soát nhau. */
  .pt-bang-phi .pt-so { text-align:right; font-variant-numeric:tabular-nums;
    white-space:nowrap; }
  /* Hàng TỔNG là con số phụ huynh thật sự cần — kẻ đậm phía trên và in to hơn. */
  .pt-phi-tong th, .pt-phi-tong td { border-top:2px solid #0D8081; font-weight:700;
    font-size:14px; background:#F7FAFA;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-xep { display:flex; gap:14px; align-items:flex-start; flex-wrap:wrap; margin-bottom:10px; }
  .pt-ct { flex:none; min-width:96px; }
  /* ⛔ Chữ ĐEN trong khung viền mảnh, không phải chữ teal trong khung teal. Chữ teal
     trên nền trắng chỉ đạt tương phản ~3,9:1 — bản in giấy và người lớn tuổi đọc
     rất mệt, mà tờ này chính là gửi cho phụ huynh. */
  .pt-ct-o { border:1px solid #C3D2D4; border-radius:4px; padding:6px 11px; margin-bottom:5px;
    font-weight:700; text-align:center; font-size:12.5px; color:#16202A; background:#F7FAFA;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-xep .pt-bang { flex:1; min-width:340px; margin-bottom:0; }
  .pt-lotrinh { display:flex; gap:10px; margin:10px 0; }
  /* ⛔ Đường dẫn dài phải tự xuống dòng, không thì nó đẩy tờ phiếu rộng ra ngoài khổ
     giấy và in bị cắt mất đuôi. */
  /* ⛔ BỎ XANH DƯƠNG #0B5FA5. Đó là màu mặc định của trình duyệt, không phải màu của
     trung tâm, và nó là một trong bảy màu làm tờ phiếu rối. Đường dẫn nay là chữ đen
     gạch chân — vẫn nhìn ra là bấm được, mà bản in giấy cũng đọc bình thường. */
  .pt-lotrinh a { color:#16202A; text-decoration:underline; text-underline-offset:2px; }
  .pt-vach { border-top:2px solid #14A0A0; margin:20px 0 14px;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-batdau { font-weight:700; margin-bottom:8px; }
  /* Chỗ nhân viên điền: gạch chân để nhìn ra ngay đâu là phần điền thêm, giống hệt
     tờ giấy đang dùng. Chưa điền thì vẫn là một khoảng gạch trống để viết tay. */
  .pt-dien { display:inline-block; min-width:110px; border-bottom:1px solid #16202A;
    padding:0 4px; font-weight:700; }
  .pt-phi { padding:3px 0; display:flex; flex-wrap:wrap; gap:4px 14px; }
  .pt-lien { white-space:nowrap; }
  .pt-dien-dai { min-width:230px; }
  .pt-nho { font-size:12px; color:#5A6672; margin:6px 0 2px; }
  .pt-cs { display:flex; gap:8px; align-items:baseline; padding:2px 0; }
  /* ⛔ `width` cố định chứ không phải `min-width`: tên cơ sở dài ngắn khác nhau
     ("Nguyễn Tuân/Nguyễn Chánh" so với "Phố Vọng"), để `min-width` thì địa chỉ mỗi
     dòng bắt đầu ở một chỗ khác nhau, đọc như bảng bị vỡ. */
  .pt-cs b { flex:none; width:236px; }
  .pt-cs span { flex:1; min-width:0; }
  .pt-doan { margin:8px 0; }
  /* ⛔ BỎ XANH DƯƠNG (xem `.pt-lotrinh a`). Số tài khoản đã in đậm là đủ nổi; tô màu
     thêm chỉ làm phụ huynh tưởng bấm vào được. */
  .pt-nh { margin:6px 0; font-weight:700; color:#16202A; }
  .pt-nh div { padding:1px 0; }
  .pt-nh div:last-child { font-variant-numeric:tabular-nums; }
  /* Khối chuyển khoản: chữ bên trái, mã QR bên phải. Màn hẹp thì xuống dòng. */
  .pt-ck { display:flex; gap:18px; align-items:flex-start; flex-wrap:wrap; }
  .pt-ck-chu { flex:1; min-width:250px; }
  .pt-ck-chu .pt-doan { margin:0 0 8px; }
  .pt-ck-chu .pt-doan:last-child { margin:8px 0 0; }
  .pt-ck .pt-nh { margin:0; }
  .pt-qr { flex:none; text-align:center; }
  .pt-qr img { width:150px; height:auto; display:block; }
  .pt-qr-nhan { font-size:11.5px; font-weight:700; margin-top:3px; }
  .pt-qr-nd { font-size:11px; color:#5A6672; max-width:170px; word-break:break-word; }
  /* Ô dán ảnh mã QR. Khung nét đứt để nhìn là biết đây là chỗ thả đồ vào, không phải
     ô chữ. Không dùng màu mè — vẫn giữ lối business. */
  /* Dòng nhận dạng trên thẻ hồ sơ — tách hai em trùng tên, nên phải ĐỌC ĐƯỢC NGAY:
     màu chữ thường, không làm nhạt. Một dòng, không in đậm — đậm hết thì chẳng gì nổi
     lên, và thẻ thành một mảng chữ chi chít.
     ⛔⛔ CÓ NHÃN "Sinh:" / "SĐT:" — cô Quỳnh 15/08/2026: *"phải ghi rõ sđt: 09… chứ
        không phải cách nhau mỗi dấu chấm"*. Bản trước tôi bỏ nhãn cho gọn, tưởng số
        10 chữ số bắt đầu bằng 0 thì ai cũng đoán ra — không, người dùng không có
        nghĩa vụ đoán. */
  /* Dòng "đang chọn N người" dưới danh sách nhân viên của cột TVTS. */
  /* Ô TVTS có nhiều người: tên người đầu + "+N" ghim mép phải ô.
     ⛔ KHÔNG đụng display của td — cuộn ảo của sổ dựa vào chiều cao dòng 30px cố
        định, đổi display là lệch hết phép tính chỗ đang cuộn tới. */
  .cts-bang td.cts-tv { position:relative; }
  /* ⭐ 21/08/2026 — NGƯỜI CHÍNH ĐẬM, BACKUP NHẠT (luật ở `ctsNguoiChinh`).
     ⛔ CHỈ đổi độ đậm và màu chữ — KHÔNG đổi cỡ chữ, không đổi line-height, không
        thêm padding. Chiều cao dòng phải đứng yên ở 30px, cuộn ảo tính chỗ đang xem
        bằng phép nhân số dòng × 30. */
  /* Danh sách "đang chọn" trong hộp chọn nhân viên — mỗi người một dòng, có vai trò. */
  /* ⭐⭐ 21/08/2026 — NHÃN "Chính / Backup" VỀ LỐI BẢNG BIỂU.
     Cô Quỳnh: *"thiết kế cái chữ Chính và backup trông thiếu chuyên nghiệp và màu mè
     thậm chí lộ rõ UI của AI làm mất giá trị app"*.

     Bản cũ sai ở đâu: hai VIÊN THUỐC bo tròn 20px, chữ IN HOA nét 800, giãn chữ,
     mỗi viên một màu nền riêng (teal nhạt cho Chính, hổ phách nhạt cho Backup),
     lại còn viền màu. Đó đúng là bộ nhận dạng của giao diện do máy sinh ra: tô màu
     cho mọi thứ, bo tròn mọi thứ, hét lên bằng chữ hoa.

     Nay: một CỘT NHÃN rộng cố định, chữ thường, không nền, không viền, không bo.
     Phân biệt bằng ĐỘ ĐẬM và SẮC MỰC chứ không bằng màu — "Chính" mực chữ nét 600,
     "Backup" mực mờ nét 400. Các dòng ngăn nhau bằng một vạch 1px như bảng.

     ⛔ ĐỪNG TÔ MÀU LẠI. Vai trò đã nói thẳng bằng CHỮ ("Chính" / "Backup") rồi;
        thêm màu là nói hai lần cùng một chuyện, và là đúng thứ cô Quỳnh vừa bảo bỏ.
     ⛔ Đừng viết hoa lại. Chữ hoa ở nhãn nhỏ là thói quen của mẫu giao diện máy,
        không phải của phần mềm nghiệp vụ. */
  .ns-vaitro { display:flex; align-items:center; gap:12px; padding:6px 0; }
  .ns-vaitro + .ns-vaitro { border-top:1px solid var(--vien); }
  .ns-vt-nhan { flex:none; width:56px; padding:0; background:none; border:0;
    border-radius:0; text-transform:none; letter-spacing:0; text-align:left;
    font-size:12px; font-weight:400; color:var(--mo); }
  .ns-vt-nhan.chinh { font-weight:600; color:var(--chu); }
  .ns-vt-nhan.bu { font-weight:400; color:var(--mo); }
  .ns-vt-ten { flex:1; min-width:0; font-size:13px; }
  .ns-vt-nut { flex:none; font:inherit; font-size:11.5px; cursor:pointer;
    border:1px solid var(--vien); background:var(--the); color:var(--mo);
    border-radius:var(--r-md); padding:2px 9px; }
  .ns-vt-nut:hover { border-color:var(--muc); color:var(--muc); }
  .ns-vt-trong { font-size:12.5px; color:var(--mo); padding:3px 0; }
  .cts-tv-chinh { font-weight:700; }
  .cts-tv-bu { color:var(--mo); }
  /* ⭐⭐ 21/08/2026 (TỐI) — Ô NHIỀU NGƯỜI VỀ LẠI MỘT DÒNG.
     Cô Quỳnh: *"phải hiển thị đầy đủ tên của nhân viên CHÍNH và thêm +1 +2 nếu có
     nhân viên backup đằng sau"*.
     ⛔⛔ ĐÂY LÀ LỆNH ĐẢO NGƯỢC LỆNH BUỔI SÁNG CÙNG NGÀY. Bản sáng cho xuống dòng và
        bóp chữ còn 10px để nhét đủ mọi tên; nhìn thật thì bốn tên nối nhau vẫn bị
        cắt cụt giữa chừng mà chẳng còn dấu ba chấm nào báo, chữ thì bé và dính.
        Đừng "khôi phục" bản ấy.
     ⛔ `padding-right` chừa chỗ cho nhãn "+N" ghim mép phải — thiếu nó thì tên
        người chính chạy thẳng xuống dưới nhãn và hai thứ chồng lên nhau.
     ⛔ Chiều cao dòng vẫn 30px, KHÔNG ĐƯỢC ĐỔI: cuộn ảo tính chỗ đang xem bằng phép
        nhân số dòng × CTS_CAO (30). */
  .cts-bang td.cts-tv-nhieu { padding-right:34px; }
  /* Nhãn "+N" ghim mép phải ô. Chữ xám, không nền màu, không viên thuốc — đúng lối
     bảng biểu. Có nền đặc để phần tên bị cắt không lòi ra dưới nhãn. */
  .cts-tv-them { position:absolute; right:6px; top:0; line-height:30px;
    font-size:11.5px; font-weight:600; padding-left:5px; background:inherit;
    /* ⛔ Nhãn này nay BẤM ĐƯỢC (xem `data-xembu`), nên phải trông như bấm được —
       không thì người dùng không biết mà bấm. Gạch chân chấm + con trỏ bàn tay. */
    cursor:pointer; text-decoration:underline dotted; text-underline-offset:2px; }
  .cts-tv-them:hover { color:var(--muc); }

  /* ⭐ CHIP TÊN NHÂN VIÊN — bắt chước ô tròn màu trong file CTS trên Google Sheets.
     Cô Quỳnh 21/08/2026 (tối): *"File CTS sheet đã có kiểu thiết kế mới trong ô tròn
     block mới trong cột TVTS thì tôi muốn bạn nên bắt chước theo vì nó cũng khá dễ
     nhìn"*.
     ⛔ ĐÂY LÀ CHỖ DUY NHẤT ĐƯỢC BO TRÒN HẲN. Cô ghét hình tròn quanh CON SỐ NGÀY ở
        lịch (*"bỏ hình tròn đi nhìn tởm quá"*) — chuyện khác hẳn. Viên thuốc quanh
        TÊN NGƯỜI đúng là thứ Google Sheets làm và đúng là thứ cô chỉ tay bảo bắt chước.
     ⛔ Cao 18px trong ô cao 30px — còn 6px thở mỗi bên. ĐỪNG nâng cao chip: chiều cao
        dòng khoá cứng 30px vì cuộn ảo nhân số dòng × CTS_CAO. */
  .ctv-chip { display:inline-block; max-width:100%; height:18px; line-height:18px;
    padding:0 8px; border-radius:999px; font-size:11.5px; font-weight:600;
    vertical-align:middle; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* Sáu cặp nền-chữ dùng chung với thẻ ca bên Lịch test — đã đo tương phản, xem khối
     `--ltt-n1` ở đầu file. Một người luôn một màu, băm từ id (xem `ctsMauNguoi`). */
  .ctv-mau1 { background:var(--ltt-n1); color:var(--ltt-c1); }
  .ctv-mau2 { background:var(--ltt-n2); color:var(--ltt-c2); }
  .ctv-mau3 { background:var(--ltt-n3); color:var(--ltt-c3); }
  .ctv-mau4 { background:var(--ltt-n4); color:var(--ltt-c4); }
  .ctv-mau5 { background:var(--ltt-n5); color:var(--ltt-c5); }
  .ctv-mau6 { background:var(--ltt-n6); color:var(--ltt-c6); }
  .ctv-mau0 { background:var(--ltt-n0); color:var(--ltt-c0); }
  /* Chip nằm trong ô bảng thì bỏ nét đậm 700 của `.cts-tv-chinh` — nền màu đã đủ
     làm người chính nổi lên rồi, thêm nét đậm nữa là quá tay. */
  .cts-bang .cts-tv-chinh.ctv-chip { font-weight:600; }

  /* Bảng nhỏ hiện ra khi bấm nhãn "+N". Nền đặc, viền mảnh, bóng nhẹ — đủ để tách
     khỏi bảng bên dưới mà không thành một cái thẻ nổi kiểu web. */
  .cts-hop-bu { position:fixed; z-index:120; background:var(--the);
    border:1px solid var(--vien); border-radius:var(--r-md); padding:6px;
    box-shadow:0 6px 20px rgba(0,0,0,.14); min-width:210px; max-width:340px; }
  .cts-hop-bu-mot { display:flex; align-items:center; gap:8px; padding:4px 6px;
    font-size:12.5px; white-space:nowrap; }
  .cts-hop-bu-ten { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; }
  .cts-hop-bu-vai { flex:none; font-size:11px; color:var(--mo); }
  .cts-hop-bu-vai.chinh { color:var(--muc); font-weight:700; }
  /* Danh sách hồ sơ GIỐNG lúc thêm học sinh mới (21/08/2026). Trắng đen, nét mảnh. */
  /* ══════════════════════════════════════════════════════════════════════════
     ⌘ Ô LỆNH NHANH (Ctrl + K) — cô Quỳnh 22/08/2026
     ⛔ Nằm TRÊN mọi thứ khác: z-index phải hơn thanh bên (11001) và hơn hộp thoại,
        vì bấm Ctrl+K lúc đang mở hộp thoại nào cũng phải ra được.
     ══════════════════════════════════════════════════════════════════════════ */
  #oLenh { position:fixed; inset:0; z-index:12000; }
  .ol2-nen { position:absolute; inset:0; background:rgba(31,29,26,.45);
    -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px); }
  /* ⛔ Đặt ở 14vh chứ không căn giữa dọc: ô lệnh mở ra là mắt phải thấy NGAY, mà
     mắt người đọc màn hình thì nghỉ ở khoảng một phần ba trên, không phải chính giữa. */
  .ol2-hop { position:relative; margin:14vh auto 0; width:min(94vw, 580px);
    background:var(--the); border:1px solid var(--vien); border-radius:var(--r-xl);
    box-shadow:0 16px 48px rgba(31,29,26,.22); overflow:hidden;
    display:flex; flex-direction:column; max-height:70vh; }
  .ol2-dau { display:flex; align-items:center; gap:10px; padding:13px 15px;
    border-bottom:1px solid var(--vien-nhe); flex:none; }
  .ol2-kinh { width:18px; height:18px; flex:none; fill:none; stroke:var(--mo);
    stroke-width:1.8; stroke-linecap:round; }
  /* ⛔ Ô gõ KHÔNG có viền riêng: cả cái hộp này CHÍNH LÀ ô gõ. Thêm viền vào đây
     là thành một ô nhỏ lọt trong một hộp to — hai lớp khung cho một việc. */
  .ol2-dau input { flex:1; min-width:0; border:none; outline:none; background:none;
    font-family:inherit; font-size:16px; color:var(--chu); padding:2px 0; }
  .ol2-dau input::placeholder { color:var(--mo); }
  .ol2-esc { flex:none; }
  #oLenh kbd { font-family:inherit; font-size:11px; color:var(--mo);
    background:var(--nen2); border:1px solid var(--vien-nhe);
    border-radius:var(--r-sm); padding:2px 6px; line-height:1.4; }
  .ol2-than { overflow-y:auto; padding:7px; }
  .ol2-nhom { font-size:11.5px; font-weight:600; color:var(--mo);
    padding:8px 9px 4px; }
  .ol2-muc { display:flex; align-items:center; gap:10px; width:100%; text-align:left;
    background:none; border:none; border-radius:var(--r-md); cursor:pointer;
    font-family:inherit; font-size:13.5px; color:var(--chu); padding:9px 10px; }
  .ol2-muc .cc-ico { width:17px; height:17px; flex:none; color:var(--mo); }
  .ol2-muc .ol2-ten { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ol2-muc .ol2-mo { font-size:11.5px; color:var(--mo); }
  /* ⛔ Dòng ĐANG CHỌN tô bằng nền teal nhạt + vạch teal, GIỐNG HỆT hàng đang mở
     bên thanh công cụ. Cùng một ý nghĩa thì phải cùng một hình hài — không thì
     người dùng phải học hai lần. */
  .ol2-muc.chon { background:var(--xanh-nhat); color:var(--muc);
    box-shadow:inset 2px 0 0 var(--xanh); }
  .ol2-muc.chon .cc-ico { color:var(--muc); }
  .ol2-muc.do { color:var(--do); }
  .ol2-muc.do.chon { background:var(--do-nen); color:var(--do); box-shadow:inset 2px 0 0 var(--do); }
  .ol2-trong { padding:22px 12px; text-align:center; font-size:13px; color:var(--mo); }
  .ol2-chan { display:flex; gap:16px; flex-wrap:wrap; padding:9px 15px; flex:none;
    border-top:1px solid var(--vien-nhe); background:var(--nen2);
    font-size:11.5px; color:var(--mo); }
  .ol2-chan span { display:inline-flex; align-items:center; gap:4px; }
  /* Màn bé: bỏ dòng nhắc phím ở chân — điện thoại không có bàn phím để mà nhắc. */
  @media (max-width:640px) { .ol2-chan { display:none; } .ol2-hop { margin-top:8vh; } }

  /* ── Khối AI trong hộp Thêm học sinh (cô Quỳnh 21/08/2026) ──
     ⛔ KHÔNG nền màu, KHÔNG gradient, KHÔNG emoji. Cô Quỳnh đã chê "lộ rõ ui AI"
        năm lần; một khối tên là "AI" mà lại trang trí như quảng cáo AI thì đúng
        chỗ dễ dính nhất. Viền mảnh + nền xám nhạt, y như mọi khối khác của sổ. */
  .cts-ai { border:1px solid var(--vien); border-radius:var(--r-md); background:var(--nen2);
    padding:11px 12px; margin:0 0 14px; }
  .cts-ai-dau b { display:block; font-size:13.5px; font-weight:600; }
  .cts-ai-dau span { display:block; font-size:12px; color:var(--mo); margin:2px 0 8px; }
  .cts-ai textarea { width:100%; box-sizing:border-box; border:1px solid var(--vien);
    border-radius:var(--r-o, 8px); padding:8px 10px; font-family:inherit; font-size:13px;
    background:var(--the); color:var(--chu); resize:vertical; }
  .cts-ai textarea:focus { outline:none; border-color:var(--muc); }
  .cts-ai-anh { display:flex; flex-wrap:wrap; gap:7px; margin-top:8px; }
  .cts-ai-anh:empty { display:none; }
  .cts-ai-mot { position:relative; display:inline-block; }
  .cts-ai-mot img { display:block; width:64px; height:64px; object-fit:cover;
    border:1px solid var(--vien); border-radius:var(--r-sm); background:var(--the); }
  /* ⛔ Nút bỏ ảnh phải nằm ĐÈ lên góc ảnh và có nền đặc — đặt ngoài thì hàng ảnh
     dài gấp đôi, còn để trong suốt thì dấu × chìm nghỉm trên ảnh sáng. */
  .cts-ai-mot button { position:absolute; top:-6px; right:-6px; width:18px; height:18px;
    line-height:16px; padding:0; border:1px solid var(--vien); border-radius:50%;
    background:var(--the); color:var(--chu); font-size:12px; cursor:pointer; }
  .cts-ai-hang { display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-top:9px; }
  .cts-ai-them { cursor:pointer; }
  /* `<span>` mang lớp nút vì nó nằm trong `<label>` — nút thật bên trong là ô file
     đã ẩn. Nên phải tự khai kiểu, không hưởng luật của `button.nut-nho`. */
  .cts-ai-them span { display:inline-block; border:1px solid var(--vien);
    border-radius:var(--r-md); padding:5px 11px; font-size:12.5px; background:var(--the); }
  .cts-ai-them:hover span { background:var(--nen2); }
  .cts-ai-tt { flex:1 1 100%; font-size:12px; color:var(--mo); min-height:16px; }
  .cts-ai-tt.do { color:var(--do); }

  .cts-trung-ds { max-height:46vh; overflow-y:auto; border:1px solid var(--vien); border-radius:var(--r-lg); }
  .cts-trung-mot { display:flex; align-items:flex-start; gap:10px; padding:9px 11px;
    border-top:1px solid var(--vien); cursor:pointer; font-size:13px; }
  .cts-trung-ds > .cts-trung-mot:first-child { border-top:0; }
  .cts-trung-mot:hover { background:var(--nen2); }
  .cts-trung-mot input { margin-top:3px; flex:none; }
  .cts-trung-ten { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .cts-trung-ten small { color:var(--mo); font-size:11.5px; overflow-wrap:anywhere; }
  .cts-trung-muc { flex:none; font-style:normal; font-size:10px;
 color:var(--mo); border:1px solid var(--vien); border-radius:var(--r-xl); padding:1px 8px; }
  .cts-trung-muc.chac { color:var(--chu); border-color:var(--chu); font-weight:600; }
  /* Màn ghép tên cũ sang tài khoản thật. */
  .ghep-ds { max-height:52vh; overflow-y:auto; }
  .ghep-dong { display:flex; align-items:center; gap:10px; padding:8px 2px;
    border-bottom:1px solid var(--vien); }
  .ghep-cu { width:190px; flex:none; display:flex; flex-direction:column; }
  .ghep-cu span { font-size:11.5px; color:var(--mo); }
  .ghep-moi { flex:1; min-width:0; font-size:12.5px; }
  .ghep-moi i { color:var(--mo); font-style:normal; }
  .ns-dangchon { margin-top:8px; padding-top:8px; border-top:1px solid var(--vien);
    font-size:12.5px; color:var(--mo); }
  .kq-the-dinh { display:flex; flex-wrap:wrap; gap:1px 12px; margin:5px 0 1px;
    font-size:12.5px; color:var(--chu); }
  /* Nhãn: màu phụ, chữ thẳng (không nghiêng) để không lệch tông business. Có mặt để
     đọc là hiểu, nhưng không giành chú ý với giá trị bên cạnh. */
  .kq-the-dinh i { font-style:normal; color:var(--mo); }
  /* ⛔⛔ HAI CHỖ NÀY CẮT MẤT CHỮ — cô Quỳnh 15/08/2026: *"vấn đề là bị thiếu chữ nữa"*.
     `.nn-the-dau b` và `.nn-the-phu` đặt `white-space:nowrap` + `text-overflow:ellipsis`,
     mà thẻ chỉ rộng ~248px và huy hiệu điểm còn giành chỗ cứng bên phải — nên tên dài
     bị nuốt đuôi thành "Nguyễn Thị Hoàng Bảo…", trường dài cũng vậy.
     Ở HỒ SƠ KIỂM TRA thì tên là thứ quan trọng nhất trên thẻ: thà thẻ cao thêm một
     dòng còn hơn đọc nhầm em. Cho xuống dòng, bỏ cắt.
     ⛔ Chỉ đè trong `.kq-the` — màn Test đầu vào dùng chung mấy lớp `nn-` này, không
        đụng tới để khỏi đổi thứ cô chưa yêu cầu. */
  .kq-the .nn-the-dau { align-items:flex-start; }
  .kq-the .nn-the-dau b { overflow:visible; text-overflow:clip; white-space:normal;
    overflow-wrap:anywhere; line-height:1.32; }
  .kq-the .nn-the-phu { overflow:visible; text-overflow:clip; white-space:normal;
    overflow-wrap:anywhere; line-height:1.32; }
  /* Băng chọn bài test của cùng một em. */
  .kq-bang-bai { display:flex; flex-wrap:wrap; align-items:center; gap:8px;
    margin:0 0 12px; padding:9px 12px; border:1px solid var(--vien); border-radius:var(--r-md);
    background:var(--nen2); }
  .kq-bang-nhan { font-size:12.5px; color:var(--mo); margin-right:2px; }
  .kq-bai-nut { display:flex; flex-direction:column; align-items:flex-start; gap:1px;
    border:1px solid var(--vien); border-radius:var(--r-sm); padding:5px 11px; cursor:pointer;
    background:var(--the); color:var(--chu); font:inherit; text-align:left; }
  .kq-bai-nut b { font-size:12.5px; }
  .kq-bai-nut span { font-size:11px; color:var(--mo); }
  .kq-bai-nut:hover { border-color:var(--xanh); }
  .kq-bai-nut.chon { border-color:var(--xanh); background:var(--xanh-nhat); }
  .kq-bai-nut.chon b { color:var(--xanh-dam); }
  /* Nút thêm bài đứng tách hẳn ra cuối băng — nó là việc khác hẳn với việc chọn bài. */
  .kq-bai-them { margin-left:auto; border:1px dashed var(--vien); border-radius:var(--r-sm);
    padding:7px 12px; cursor:pointer; background:none; color:var(--mo); font:inherit;
    font-size:12.5px; }
  .kq-bai-them:hover { border-style:solid; border-color:var(--xanh); color:var(--xanh-dam); }
  .kq-qr-tha { border:1px dashed var(--vien); border-radius:var(--r-md); padding:16px 14px;
    text-align:center; cursor:text; background:var(--nen2); outline:none; }
  .kq-qr-tha:focus, .kq-qr-tha.dang-keo { border-color:var(--xanh); border-style:solid; }
  .kq-qr-tha-chu { font-size:12.5px; color:var(--mo); line-height:1.6; margin-bottom:9px; }
  .kq-qr-link { display:flex; gap:8px; align-items:center; margin-top:10px; }
  .kq-qr-link input { flex:1; min-width:0; border:1px solid var(--vien); border-radius:var(--r-o, 8px);
    padding:7px 9px; font:inherit; font-size:12.5px; background:var(--the); color:var(--chu); }
  .kq-qr-link input:focus { outline:none; border-color:var(--xanh); }
  /* 🔳 Khối "App tự dựng mã QR". Lối bảng biểu: nhãn nhỏ trên ô, không viền màu,
     không nền tô. Chỉ một vạch ngang ngăn nó với đường dán ảnh phía dưới. */
  .kq-qr-dung { margin-bottom:12px; padding-bottom:12px; border-bottom:1px solid var(--vien); }
  .kq-qr-dung-chu { font-size:12.5px; color:var(--mo); line-height:1.55; margin-bottom:9px; }
  .kq-qr-dung-o { display:flex; gap:10px; flex-wrap:wrap; }
  /* ⛔ `min-width:0` bắt buộc: thiếu nó thì ô nhập không chịu co xuống dưới bề rộng
     mặc định của thẻ input (~180px), ba ô không nằm nổi một hàng và ô thứ ba rơi
     xuống dòng — đúng thứ vừa bắt được lúc chụp màn 21/08. */
  /* ⛔ Ô mã lớp KHÔNG bọc trong <label>: bên trong nó có ô tìm của `ganTimChoOChon`,
     mà bấm vào một ô nhập nằm trong <label> thì trình duyệt đẩy con trỏ sang thẻ
     <select> mà label ấy trỏ tới — gõ không được chữ nào. Nên dùng .kq-qr-o1 + một
     thẻ nhãn riêng, trông y hệt mà không dính luật đó. */
  .kq-qr-dung-o label, .kq-qr-dung-o .kq-qr-o1 { display:flex; flex-direction:column; gap:4px;
    flex:1 1 140px; min-width:0;
    font-size:11.5px; font-weight:600; color:var(--mo); }
  .kq-qr-dung-o .kq-qr-o1 { flex:1 1 220px; }
  .kq-qr-dung-o select { font:inherit; font-size:13px; padding:6px 9px; min-width:0; width:100%;
    border:1px solid var(--vien); border-radius:var(--r-o, 8px); background:var(--nen-o); color:var(--chu); }
  .kq-qr-dung-o select:focus { outline:none; border-color:var(--xanh); }
  .kq-qr-dung-o select:disabled { color:var(--mo); }
  /* Nút nhỏ nằm gọn trong khung ô (Lưu mã nhân viên · Thêm mã lớp). Không tô đặc:
     nó là việc phụ, nút chính của khối vẫn là "Dựng mã QR". */
  .kq-qr-luu { flex:none; font:inherit; font-size:11.5px; font-weight:600;
    padding:0 10px; margin:2px; border:1px solid var(--vien); border-radius:var(--r-sm);
    background:var(--nen); color:var(--mo); cursor:pointer; }
  .kq-qr-luu:hover { border-color:var(--xanh); color:var(--xanh); }
  .kq-qr-canh { font-weight:400; font-size:11px; color:var(--mo); line-height:1.5; }
  /* Bỏ một mã tự thêm — việc hiếm và có tính xoá, nên để dạng chữ nhỏ, không
     dựng thành nút to cạnh nút Dựng mã QR. */
  .kq-qr-bo { align-self:flex-start; font:inherit; font-size:11px; font-weight:400;
    padding:0; margin-top:4px; border:0; background:none; color:var(--mo);
    text-decoration:underline; cursor:pointer; }
  .kq-qr-bo:hover { color:var(--do); }
  .kq-qr-dung-o input { font:inherit; font-size:13px; padding:6px 9px; min-width:0; width:100%;
    border:1px solid var(--vien); border-radius:var(--r-o, 8px); background:var(--nen-o); color:var(--chu); }
  .kq-qr-dung-o input:focus { outline:none; border-color:var(--xanh); }
  /* Bốn số năm học in sẵn NGAY TRONG khung ô, không phải một dòng riêng phía trên:
     nhân viên phải nhìn thấy mã lớp đầy đủ hiện ra ngay chỗ mình đang gõ. */
  .kq-qr-ghep { display:flex; align-items:stretch; min-width:0;
    border:1px solid var(--vien); border-radius:var(--r-sm); background:var(--nen-o); }
  .kq-qr-ghep:focus-within { border-color:var(--xanh); }
  .kq-qr-ghep .kq-qr-nam { flex:none; display:flex; align-items:center; padding:0 2px 0 9px;
    font-size:13px; font-weight:400; color:var(--mo); }
  .kq-qr-ghep input { border:0; background:none; border-radius:0; padding-left:0; }
  .kq-qr-ghep input:focus { border-color:transparent; }
  .kq-qr-xem { margin-top:9px; font-size:12px; color:var(--chu);
    font-family:ui-monospace, Consolas, monospace; word-break:break-all; }
  /* Thiếu mã học sinh là thiếu thứ quan trọng nhất — đổi màu chữ cho thấy ngay,
     không thêm khung hay nền tô. */
  .kq-qr-xem.thieu { color:var(--do); font-family:inherit; }
  .kq-qr-dung-nut { display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; }
  /* Nút chính cỡ nhỏ — cùng cỡ nút bên cạnh, chỉ khác ở chỗ tô đặc. Không dùng
     `.nut-chinh` vì lớp ấy khai width:100% (xem chú thích ở `.cts-dau .nut-chinh`). */
  .nut-nho.chinh-nho { background:var(--xanh); border-color:var(--xanh); color:#fff; }
  .nut-nho.chinh-nho:hover { background:var(--xanh-dam); border-color:var(--xanh-dam); }
  .kq-qr-meo { margin-top:8px; font-size:11.5px; color:var(--mo); line-height:1.55;
    text-align:left; }
  .kq-qr-co { display:flex; align-items:center; gap:14px; }
  .kq-qr-co img { width:132px; height:auto; border:1px solid var(--vien); border-radius:var(--r-sm);
    background:#fff; display:block; }
  .kq-qd-ck { display:flex; gap:14px; align-items:flex-start; flex-wrap:wrap; }
  .kq-qd-qr { flex:none; text-align:center; }
  .kq-qd-qr img { width:112px; height:auto; display:block; border:1px solid var(--vien);
    border-radius:var(--r-sm); background:#fff; }
  .kq-qd-qr .pt-qr-nhan { font-size:11px; margin-top:3px; color:var(--mo); }
  .kq-qd-qr .pt-qr-nd { display:none; }
  /* Nút "Sửa" đứng cuối dòng tiêu đề mục, chữ thường để không tranh chỗ với tiêu đề. */
  .kq-qd-muc .nut-nho { margin-left:10px; font-size:11px; padding:2px 8px;
    font-weight:400; text-transform:none; letter-spacing:0; vertical-align:middle; }
  /* ⛔ `.pt-qd-dau` KHÔNG CÒN AI DÙNG từ 21/08/2026 — mục quy định nay dùng `ptMuc(6)`
     như năm mục kia. Giữ lại luật rỗng này thì thừa, nên đã bỏ hẳn.
     Nó từng là: chữ teal + gạch chân CAM — kiểu tiêu đề thứ tư trong cùng một tờ. */
  .pt-qd { margin:6px 0 2px; padding-left:16px; position:relative; }
  /* ⛔ Chấm TRÒN nhỏ, không phải hình thoi teal xoay 45°. Hình thoi là đồ trang trí;
     tờ gửi phụ huynh cần dấu đầu dòng đọc được, không cần hoa văn. */
  .pt-qd { font-weight:600; }
  .pt-qd::before { content:""; position:absolute; left:3px; top:9px; width:5px; height:5px;
    border-radius:50%; background:#0D8081;
    -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .pt-qd-con { padding-left:28px; position:relative; }
  .pt-qd-con::before { content:""; position:absolute; left:16px; top:11px; width:6px;
    height:1px; background:#16202A; }
  .pt-goi { font-size:12px; color:var(--mo); align-self:center; }

  .kq-phieu { max-width:840px; margin:0 auto; border:1px solid var(--vien);
      border-radius:var(--r-xl); background:var(--the); padding:0 0 22px;
      overflow:hidden; position:relative; }
  /* Vạch thương hiệu chạy ngang đỉnh phiếu: teal rồi tới cam, đúng hai màu logo. */
  .kq-phieu::before { content:""; display:block; height:5px;
      background:linear-gradient(90deg, var(--xanh) 0 68%, var(--cam) 68% 100%); }
  .kq-logo { position:absolute; top:22px; right:30px; text-align:right; }
  .kq-logo .logo-mypas .ten { font-size:23px; }
  .kq-logo .logo-mypas .cham { font-size:9px; letter-spacing:.05em; }
  .kq-dau { display:flex; align-items:center; gap:20px; padding:24px 30px 18px;
      border-bottom:2px solid var(--xanh); margin-right:150px; }
  .kq-dau-trai { flex:1; min-width:0; }
  .kq-nhan { font-size:11.5px; font-weight:700;
      color:var(--muc); }
  .kq-dau h1 { margin:5px 0 4px; font-size:27px; font-weight:700; line-height:1.2; }
  .kq-phu { font-size:13.5px; color:var(--mo); }
  .kq-dau-phai { flex:none; text-align:center; }
  /* Vòng điểm: một vòng tròn viền dày, KHÔNG tô nền đặc — in đen trắng vẫn rõ. */
  .kq-vong { width:96px; height:96px; border-radius:50%; border:5px solid var(--vien);
      display:flex; align-items:baseline; justify-content:center; gap:1px; padding-top:26px; }
  .kq-vong.tot { border-color:#1B8A4B; }
  .kq-vong.kha { border-color:#B8860B; }
  .kq-vong.yeu { border-color:#B04141; }
  .kq-so { font-size:34px; font-weight:700; line-height:1; font-variant-numeric:tabular-nums; }
  .kq-tren { font-size:14px; color:var(--mo); font-weight:700; }
  .kq-hang { margin-top:7px; font-size:12.5px; font-weight:700; }
  .kq-hang.tot { color:#1B8A4B; }
  .kq-hang.kha { color:#B8860B; }
  .kq-hang.yeu { color:#B04141; }

  .kq-khoi { margin-top:20px; padding:0 30px; }
  /* Tên mục có một gạch cam ngắn bên trái — nhận ra mục mới mà không cần kẻ ngang
     cả trang. */
  .kq-khoi h2 { margin:0 0 12px; font-size:12px; font-weight:700;
 color:var(--xanh-dam); padding-left:11px;
      border-left:3px solid var(--cam); line-height:1.35; }
  .kq-tc-ds { display:flex; flex-direction:column; gap:15px; }
  .kq-tc-dau { display:flex; align-items:baseline; gap:9px; margin-bottom:6px; }
  .kq-tc-dau b { font-size:15px; font-weight:700; }
  .kq-tc-dau i { font-size:11.5px; color:var(--mo); }
  .kq-tc-diem { margin-left:auto; font-size:14px; font-weight:700; color:var(--muc);
      font-variant-numeric:tabular-nums; }
  /* Bốn ô rời chứ không phải một thanh liền — phụ huynh đếm được ngay "3 trên 4". */
  .kq-thanh { display:flex; gap:4px; margin-bottom:6px; }
  .kq-o { flex:1; height:9px; border-radius:var(--r-sm); border:1px solid var(--vien);
      background:transparent; }
  .kq-o.day { background:var(--xanh); border-color:var(--xanh); }
  .kq-tc-chu { font-size:13.5px; line-height:1.55; }

  .kq-lan { border:1px solid var(--vien); border-radius:var(--r-md); padding:11px 13px; margin-bottom:9px; }
  .kq-lan-dau { display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:12.5px; }
  .kq-bo { background:var(--nen2); padding:2px 9px; border-radius:var(--r-sm); font-weight:700; }
  .kq-nh { color:var(--mo); }
  .kq-chude { margin-top:7px; font-size:13.5px; line-height:1.6; white-space:pre-wrap; }
  .kq-vanban { margin:0; font-size:13.5px; line-height:1.65; }

  .kq-lop-ds { display:flex; gap:9px; flex-wrap:wrap; }
  .kq-lop { display:flex; align-items:baseline; gap:7px; border:1px solid var(--xanh);
      border-radius:var(--r-md); padding:7px 13px; border-left:4px solid var(--cam); }
  .kq-lop b { font-size:14px; font-weight:700; }
  .kq-chang { font-size:11.5px; color:var(--mo); }
  .kq-chan { margin:22px 30px 0; padding-top:13px; border-top:1px solid var(--vien);
      font-size:11.5px; color:var(--mo); display:flex; gap:10px; flex-wrap:wrap; }
  .kq-chan .kq-tt { margin-left:auto; color:var(--xanh-dam); font-weight:700; }

  /* ⛔ IN RA GIẤY: bỏ mọi thứ chỉ để điều hướng, bỏ nền, bỏ viền phiếu. */
  @media print {
    /* ══════════════════════════════════════════════════════════════════════════
       ⛔⛔ IN TỜ PHIẾU GỬI PHỤ HUYNH THÌ CHỈ IN NÓ, KHÔNG IN GÌ KHÁC.
       Cô Quỳnh muốn xuất ra PDF gửi phụ huynh. Nếu để lọt thanh công cụ, thanh bên
       hay bất cứ mảnh giao diện nào của app lên tờ giấy thì tờ đó không gửi ra ngoài
       được nữa. Nên khi trong trang có tờ phiếu, mọi thứ khác bị ẩn hết.
       ⛔ Bỏ luôn viền và bo góc của tờ phiếu — trên giấy chúng thành một cái khung
          thừa. Và phải đặt lề trang, không thì mỗi máy in một kiểu.
       ══════════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════════════
       ⛔⛔ IN RA THÌ CHỈ CÒN TỜ PHIẾU — cô Quỳnh 15/08/2026:
       *"bạn nhìn thấy tôi xuất PDF ảnh mà cũng lộ luôn cả giao diện app và những
       thông báo của app, rất thiếu chuyên nghiệp… ai lại để lộ giao diện app."*

       Cô đúng, và lỗi là của tôi: luật cũ chỉ ẩn những thẻ NẰM TRONG .noi-dung.
       Thanh điều hướng dưới màn, lời mời cài app, các thông báo nổi… đều nằm NGOÀI
       .noi-dung nên vẫn in ra hết.
       Nay đổi cách: giấu TOÀN BỘ trang, rồi chỉ cho hiện lại đúng tờ phiếu và tổ
       tiên của nó. Cách này không cần biết app có thêm bao nhiêu thanh nổi mới —
       thứ gì không thuộc tờ phiếu thì mặc nhiên biến mất.
       ⛔ Dùng visibility chứ không dùng display: display:none làm sập luôn khung chứa
          của tờ phiếu, còn visibility thì giữ nguyên bố cục.
       ══════════════════════════════════════════════════════════════════════════ */
    body:has(#ptTo) * { visibility:hidden !important; }
    body:has(#ptTo) #ptTo, body:has(#ptTo) #ptTo * { visibility:visible !important; }
    /* Kéo tờ phiếu lên góc trên bên trái, khỏi thừa một mảng trắng đầu trang. */
    body:has(#ptTo) #ptTo { position:absolute !important; left:0 !important; top:0 !important; }
    body:has(#ptTo) .noi-dung { max-width:none !important; padding:0 !important; }
    /* ⛔ BỎ VIỀN XÁM — cô Quỳnh: *"viền xám ở khung trông rất xấu, bỏ đi để khung
       trắng của giấy"*. Trên màn hình viền giúp tách tờ phiếu khỏi nền; in ra giấy
       thì nó thành một cái khung thừa. */
    #ptTo { width:auto !important; max-width:none !important; margin:0 !important;
      border:none !important; box-shadow:none !important; border-radius:0 !important;
      padding:0 14mm 0 14mm !important; font-size:12px !important; }
    /* ⛔⛔ 21/08/2026 — CHỖ NÀY TỪNG LÀ MỘT LỖI ẨN. Đọc trước khi sửa.
       Khi dọn màu cho tờ phiếu, tôi đã đổi `.pt-lotrinh a` sang chữ đen ở khối CSS
       màn hình — và tưởng thế là xong. Nhưng khối `@media print` NÀY ép đè bằng
       `!important`, nên bản XUẤT PDF (đúng cái gửi phụ huynh) vẫn ra đường dẫn màu
       xanh dương, trong khi bản xem trên màn hình đã đen. Nhìn màn hình thì không
       tài nào phát hiện ra.
       Bài kiểm `thu-phieu-tra.js` bắt được vì nó soi cả file, không soi mỗi khối CSS
       màn hình. Giữ phép canh đó.
       ⛔ Sửa màu cho tờ phiếu thì tìm cả file, đừng tìm mỗi khối `.pt-to`. */
    #ptTo a { color:#16202A !important; text-decoration:underline; }
    /* ⛔⛔ GIỮ MÀU KHI IN — cô Quỳnh 15/08/2026 muốn tờ gửi đi nhận ra được màu thương
       hiệu. Trình duyệt mặc định BỎ HẾT nền màu lúc in cho tiết kiệm mực; không khai
       dòng này thì bản PDF ra trắng đen và cả công khoác màu thành công cốc. */
    #ptTo, #ptTo * { -webkit-print-color-adjust:exact !important; print-color-adjust:exact !important; }
    /* Lề trên bằng 0 để vạch thương hiệu chạm sát mép giấy như một tờ có tiêu đề in sẵn. */
    #ptTo { padding-top:0 !important; }
    #ptTo::before { margin-left:-14mm !important; margin-right:-14mm !important;
      margin-top:0 !important; }
    /* Chừa lề trên và dưới bằng chính tờ phiếu, vì @page đã bỏ hết lề. */
    #ptTo { padding-bottom:14mm !important; }
    /* ⛔ Mã QR phải in ra ĐỦ NÉT để quét được. 150px trên màn in ra khoảng 4cm — đủ
       cho mọi app ngân hàng. Và đừng để nó bị cắt sang trang khác. */
    #ptTo .pt-ck { break-inside:avoid; }
    #ptTo .pt-qr img { width:132px !important; }
    /* Không để bảng xếp lớp hay khối quy định bị cắt đôi giữa hai trang. */
    #ptTo .pt-bang, #ptTo .pt-qd, #ptTo .pt-qd-con { break-inside:avoid; }
    /* ⛔⛔ LỀ BẰNG 0 ĐỂ TRÌNH DUYỆT BỎ ĐẦU TRANG VÀ CHÂN TRANG.
       Cô Quỳnh chụp lại bản PDF: trên cùng có "8/15/26, 6:46 PM · Điểm danh MYPAS",
       dưới cùng có "localhost:3100/?v=… · 1/2". Đó là dòng do TRÌNH DUYỆT tự thêm,
       không phải của app — và nó làm tờ giấy trông như in vội từ một trang web.
       Đặt lề trang bằng 0 thì Chrome bỏ hẳn hai dòng đó; phần lề giấy chuyển vào
       padding của chính tờ phiếu (xem #ptTo ngay trên). */
    @page { size:A4; margin:0; }
    body { background:#fff !important; }
    .khong-in, .thanh-ben, .thanh-tren, #thanhCC, .noi-dung > .cts-dau { display:none !important; }
    .kq-phieu { max-width:none; border:none; border-radius:0; padding:0 0 8px; }
    /* ⛔ GIỮ vạch thương hiệu và logo khi in — đây là tờ phụ huynh cầm về, phải nhìn
       ra ngay là của trung tâm nào. Trình duyệt mặc định bỏ hết màu nền khi in nên
       phải ép in màu. */
    .kq-phieu::before { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
    .kq-o.day, .kq-vach span { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
    .kq-o.day { background:#111 !important; border-color:#111 !important; }
    .kq-vong { border-color:#111 !important; }
  }

  @media (max-width: 720px) {
    .kq-dau { flex-direction:column; align-items:flex-start; }
    .kq-phieu { padding:18px 16px; }
    .kq-dau h1 { font-size:22px; }
  }

  /* ── BẢNG "CÁC CA CÒN LẠI" bung ra từ nút +N (21/08/2026) ────────────────── */
  .lt-bang-boc { max-height:58vh; overflow:auto; border:1px solid var(--vien); border-radius:var(--r-sheet); }
  .lt-bang { width:100%; border-collapse:collapse; font-size:13px; }
  /* ⛔ BỎ `text-transform:uppercase` + `letter-spacing`. Tiếng Việt IN HOA cỡ 11px
     là MẤT DẤU ("CƠ SỞ" đọc thành "CO SO"), và hai thứ này cộng nét đậm là đúng ba
     dấu hiệu lộ giao diện AI. Cỡ chữ nhích lên 11,5px cho bù phần chữ thường thấp hơn. */
  .lt-bang th { position:sticky; top:0; z-index:1; background:var(--dau-bang-nen); text-align:left;
    font-size:11.5px; font-weight:600;
    color:var(--dau-bang-chu); padding:8px 10px;
    border-bottom:1px solid var(--dau-bang-vien); white-space:nowrap; }
  .lt-bang td { padding:8px 10px; border-bottom:1px solid var(--vien); vertical-align:top; }
  .lt-bang tbody tr { cursor:pointer; }
  .lt-bang tbody tr:hover { background:var(--nen2); }
  .lt-bang tbody tr:last-child td { border-bottom:0; }
  .lt-bang-gio { font-variant-numeric:tabular-nums; font-weight:600; white-space:nowrap; }
  /* Ngày sinh đứng cạnh tên trong chế độ Danh sách — chữ nhạt, không tranh chỗ với tên. */
  .lt-ds-ns { font-style:normal; font-size:11.5px; color:var(--mo); margin-left:7px;
    font-variant-numeric:tabular-nums; }
  /* ⛔ 21/08/2026 — đã gỡ luật `.lt-man.che-thang` cùng với chế độ Tháng. Bộ lọc
     nay hiện ở CẢ BA chế độ còn lại, vì cả ba đều lọc thật sự có tác dụng. */
  .tks-thanh { display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-bottom:12px; }
  /* ⛔⛔ 21/08/2026 — LUẬT NÀY PHẢI NẰM NGOÀI MỌI @media. Bản trước chỉ có một luật
     `.tks-thanh select` và nó bị nhốt trong khối `@media max-width:820px`, nên trên
     MÁY TÍNH ba ô chọn hiện ra trần trụi đúng kiểu widget của hệ điều hành — cô Quỳnh
     gọi là *"nhìn như app đời cũ"*. Đừng chuyển luật này vào trong @media nào.
     Số đo lấy đúng theo `.hang-tk select` (bản mẫu ô chọn có sẵn của app, khoá
     height:32px cho bằng chiều cao `.nut-nho`) — cố ý KHÔNG đẻ bản mẫu thứ tư. */
  .tks-thanh select { height:32px; border:1px solid var(--vien); border-radius:var(--r-o, 8px);
      background:var(--the); color:var(--chu); font-family:inherit; font-size:13px;
      padding:0 8px; cursor:pointer; }
  .tks-thanh select:hover { border-color:var(--xanh); }
  /* Khối "vai trò của <nhân viên>" — chỉ hiện khi đang lọc đúng một người. */
  .tks-vt { border:1px solid var(--vien); border-radius:var(--r-xl); background:var(--the);
    padding:13px 15px; margin-bottom:11px; }
  .tks-vt h3 { margin:0 0 9px; font-size:14px; }
  .tks-vt-so { display:grid; grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));
    gap:10px; }
  .tks-vt-o { border:1px solid var(--vien); border-left:3px solid var(--vien);
    border-radius:var(--r-md); padding:8px 11px; }
  .tks-vt-o b { display:block; font-size:21px; line-height:1.2;
    font-variant-numeric:tabular-nums; }
  .tks-vt-o span { font-size:11.5px; color:var(--mo); }
  /* Hai vai trò dùng đúng hai màu đã có nghĩa sẵn trong app: teal = việc của mình,
     hổ phách = "đã có người nhận / đang đỡ hộ". Không bịa màu mới. */
  .tks-vt-o.chinh { border-left-color:var(--muc); }
  .tks-vt-o.bu { border-left-color:var(--nhan-vien); }
  .tks-vt-phu { margin:11px 0 6px; font-size:12px; color:var(--mo); line-height:1.5; }
  .tks-vt-cung { display:flex; flex-wrap:wrap; gap:7px; }
  .tks-vt-chip { display:inline-flex; align-items:center; gap:7px; font-size:12.5px;
    border:1px solid var(--vien); border-radius:var(--r-xl); padding:2px 5px 2px 11px; }
  .tks-vt-chip b { font-variant-numeric:tabular-nums; background:var(--nen2);
    border-radius:var(--r-xl); padding:1px 8px; font-size:12px; }
  .tks-vt-trong { margin:0; font-size:13px; color:var(--mo); }
  /* Bảng cơ sở trong ⚙ Cài đặt. Rộng vừa phải, không cần cuộn ngang ở máy tính;
     bọc `overflow-x:auto` để điện thoại vẫn xem được cả năm cột. */
  .cs-boc { overflow-x:auto; margin-bottom:11px; }
  .cs-bang { width:100%; border-collapse:collapse; font-size:13px; }
  .cs-bang th { text-align:left; font-size:11.5px; color:var(--mo); font-weight:600;
    padding:6px 10px; border-bottom:1px solid var(--vien); white-space:nowrap; }
  .cs-bang td { padding:8px 10px; border-bottom:1px solid var(--vien); }
  .cs-bang tr:last-child td { border-bottom:0; }
  .cs-ma { font-family:ui-monospace, Menlo, Consolas, monospace; font-size:12px;
    background:var(--nen2); border-radius:var(--r-sm); padding:1px 7px; }
  .tks-moc { display:flex; border:1px solid var(--vien); border-radius:var(--r-md); overflow:hidden; }
  /* Ô tìm của màn thống kê là ô ẩn nên hàng bọc nó chỉ còn mỗi cái nút — đừng để nó
     giãn ra chiếm hết chỗ trống của hàng. */
  .tks-thanh .bl-timhang { flex:none; width:auto; margin:0; }
  /* ⛔ Đệm ngang 13px cho khớp `.nut-nho` — bản cũ để 18px nên ba nút này phình
     rộng hơn hẳn nút "Bộ lọc" đứng ngay cạnh, đúng cái cô Quỳnh gọi là "các nút
     sắp xếp rất xấu". */
  .tks-moc button { border:none; background:var(--the); color:var(--chu); font-family:inherit;
      font-size:13px; font-weight:600; padding:7px 13px; cursor:pointer;
      border-right:1px solid var(--vien); }
  /* Rê chuột phải có phản hồi — nút không đổi gì khi rê vào thì người dùng không
     tin nó là nút. Cả ba nút này trước nay chết trơ. */
  .tks-moc button:not(.chon):hover { background:var(--nen2); }
  .tks-moc button:last-child { border-right:none; }
  .tks-moc button.chon { background:var(--muc); color:#fff; }
  .tks-cuon { overflow:auto; max-height:calc(100vh - 300px - var(--dnc-du, 0px)); border:1px solid var(--vien);
              border-radius:var(--r-sheet); background:var(--the); }
  .tks-bang { border-collapse:separate; border-spacing:0; font-size:13px; width:100%; }
  .tks-bang th, .tks-bang td { border-bottom:1px solid var(--vien); padding:7px 12px;
      white-space:nowrap; text-align:right; }
  .tks-bang th { position:sticky; top:0; z-index:2; background:var(--dau-bang-nen);
      color:var(--dau-bang-chu); border-bottom-color:var(--dau-bang-vien); font-weight:700;
      font-size:11.5px; text-align:right; }
  .tks-bang th:first-child, .tks-bang td:first-child { text-align:left; position:sticky; left:0;
      background:var(--the); z-index:1; font-weight:600; }
  .tks-bang thead th:first-child { z-index:3; background:var(--dau-bang-nen); }
  .tks-bang tbody tr:nth-child(even) td { background:var(--nen2); }
  .tks-bang tbody tr:nth-child(even) td:first-child { background:var(--nen2); }
  .tks-bang tr.tks-tong td { font-weight:700; border-top:2px solid var(--vien); background:var(--nen2); }
  .tks-so { font-variant-numeric:tabular-nums; }
  /* ══════════════════════════════════════════════════════════════════════════════
     THANH SO SÁNH KIỂU BẢNG TÀI CHÍNH — cô Quỳnh 13/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"sửa cái thanh dữ liệu xanh này trong báo cáo tuyển sinh thành kiểu
     thanh chứng khoán đẹp đẹp"*.

     Bản cũ tô một KHỐI MỜ CAO BẰNG CẢ Ô ngay sau con số. Ba cái dở:
       · con số nằm ĐÈ lên khối màu nên đọc mệt, và ô nào giá trị lớn thì chữ chìm
       · khối cao bằng cả ô trông như ô bị tô nhầm nền, không ra biểu đồ
       · không có đường ray nên không biết "đầy" là tới đâu, mắt phải tự đoán

     Nay theo lối bảng tài chính: một THANH MẢNH nằm dưới đáy ô, có ĐƯỜNG RAY mờ chạy
     hết bề ngang làm mốc so sánh. Con số nằm sạch trên nền thường, thanh nằm riêng
     bên dưới — nhìn lướt là so được các tháng với nhau ngay.

     ⛔ MỘT MÀU ĐẶC, KHÔNG GRADIENT, KHÔNG BO GÓC TO, KHÔNG HIỆU ỨNG. Luật cô Quỳnh
        chốt: giao diện business, không được lộ "app do AI làm".
     ⛔ Vẽ bằng CSS thuần. Dự án KHÔNG có thư viện biểu đồ nào và không có bước build.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ⛔⛔ `z-index:0` KHÔNG PHẢI THỪA — thiếu nó là số đè lên tiêu đề cột (Boss 13/09:
     *"các số dữ liệu ở các ô nó đi lên trên xong nó trèn lẫn lộn với tiêu đề tên của
     cột khách vào sổ và cột tổng thu"* — đúng HAI cột có `thanh: true`).
     GỐC: ô này `position:relative` mà KHÔNG khai `z-index`, nên nó không tạo tầng xếp
     riêng; con `span` bên trong khai `z-index:2` liền leo thẳng lên tầng gốc, NGANG CƠ
     với `.tks-bang th { z-index:2 }` — ngang điểm thì thẻ đứng SAU trong tài liệu thắng,
     và số vẽ đè lên chữ tiêu đề. Cột không có thanh thì không có `span` ấy nên sạch,
     đúng vì thế mà chỉ hai cột hỏng.
     `z-index:0` nhốt `span` lại trong lòng ô: nó vẫn nằm trên thanh màu như cũ, nhưng
     cả ô đứng ở tầng 0, thấp hơn tiêu đề.
     ⛔ ĐỪNG chữa bằng cách nâng `th` lên `z-index:9`: đó là chạy đua số, và người sau
        thêm một `z-index` nữa là lỗi quay lại. Nhốt đúng chỗ rò mới là chữa gốc.
     ⛔ Lỗi này CHỈ LỘ RA khi cỡ chữ app ≠ 100% (Boss để "Lớn" 110% thường trực). Đo ở
        100% thì sạch — nên trạng thái mặc định của máy đo KHÔNG phải trạng thái của Boss. */
  .tks-thanh-o { position:relative; z-index:0; padding-bottom:14px !important; }
  /* Đường ray — mốc "đầy" để mắt so, mờ thôi kẻo tranh chỗ với con số. */
  .tks-thanh-o::after { content:""; position:absolute; left:12px; right:12px; bottom:6px;
                        height:3px; background:var(--vien); opacity:.5; z-index:0; }
  /* ⛔ KHÔNG đặt bề rộng tối thiểu: giá trị 0 phải là KHÔNG CÓ VẠCH NÀO. Có vạch mảnh
     ở ô số 0 thì nhìn lướt tưởng có số, mà đó là cột tiền. */
  .tks-thanh-o i { position:absolute; left:12px; bottom:6px; height:3px; z-index:1;
                   background:var(--xanh-dam); display:block; }
  /* Tháng LỖ — hoàn phí nhiều hơn thu. Đỏ để liếc là thấy. */
  .tks-thanh-o.am i { background:var(--do); }
  .tks-thanh-o.am span { color:var(--do); font-weight:600; }
  .tks-thanh-o span { position:relative; z-index:2; }
  /* Cột tiền dùng tông cam để tách hẳn khỏi cột đếm người — liếc là biết đang xem tiền. */
  .tks-thanh-o.tien i { background:var(--cam-dam); }
  /* ═══════ 🎨 MÀU TRẠNG THÁI · TÔ SÁNG Ô · CỘT TỰ THÊM (13/08/2026) ═══════
     Sáu màu nhạt cho sẵn, chữ vẫn đen đọc rõ. CỐ Ý không cho chọn màu tự do: sổ 40
     cột mà thả cửa chọn màu thì vài hôm là thành cầu vồng, nhìn mệt hơn không tô. */
  /* ══════════════════════════════════════════════════════════════════════════
     Ô TVTS GÁNH NHIỀU TÊN THÌ CHỮ NHỎ DẦN — Boss 20/09/2026
     ──────────────────────────────────────────────────────────────────────────
     Boss: *"nếu nhiều hơn 3 càng nhiều thì block tên trong ô đó sẽ bé lại để vừa"*,
     và chốt qua nút bấm: **chữ nhỏ dần theo số tên**.
     Ô rộng 190px (đo tận mắt). Một tên thì chữ cỡ thường; hai tên hẹp hơn nên lùi
     một nấc; ba tên lùi thêm nấc nữa. Dưới 9px là không đọc được nên dừng ở đó.
     ⛔ Chỉ đụng CỠ CHỮ và phần đệm hai bên chip. Đừng đổi màu, đừng đổi độ đậm —
        đậm/nhạt đang là thứ phân biệt nhân viên chính với backup.
     ⛔ `.cts-tv-n2`/`.cts-tv-n3` do `ctsVeO` đặt trên Ô (td), không phải trên chip.
     ══════════════════════════════════════════════════════════════════════════ */
  .cts-tv-n2 .ctv-chip { font-size: 10.5px; padding-left: 5px; padding-right: 5px; }
  .cts-tv-n3 .ctv-chip { font-size: 9.5px;  padding-left: 4px; padding-right: 4px; }
  .cts-tv-n2 .cts-tv-them,
  .cts-tv-n3 .cts-tv-them { font-size: 9.5px; }

  /* ↕️ Cụm hai nút đổi chỗ cột trong hộp "Màu và cột" — Boss 20/09/2026.
     Ghim sát mép phải của hàng để mắt quét dọc thấy chúng thẳng một cột, và để
     ô gõ tên cột ở giữa không bị co lại mỗi khi tên cột dài ngắn khác nhau. */
  .cts-cd-doicho { margin-left:auto; display:flex; gap:4px; flex:0 0 auto; }
  .cts-cd-doicho .nut-nho { padding:2px 7px; line-height:1.1; }

  .cts-m-vang   { background:#FDF0D5 !important; box-shadow:inset 2px 0 0 #E8C97A; }
  .cts-m-xanhla { background:#E7F4EC !important; box-shadow:inset 2px 0 0 #A5D6A7; }
  .cts-m-xanhbi { background:#E4EFF9 !important; box-shadow:inset 2px 0 0 #A8C8E8; }
  .cts-m-hong   { background:#FBEBEA !important; box-shadow:inset 2px 0 0 #F0B4AE; }
  .cts-m-tim    { background:#F0EAF7 !important; box-shadow:inset 2px 0 0 #C9B2E0; }
  .cts-m-xam    { background:#EEF0F4 !important; box-shadow:inset 2px 0 0 #C7CDD6; }
  /* ⛔ Ô ĐÃ TÔ MÀU GIỮ NỀN SÁNG KỂ CẢ TRONG NỀN ĐEN, nên chữ trong đó phải TỐI.
     Không ép thì chữ sáng nằm trên nền vàng nhạt — đúng lỗi cô Quỳnh đã báo ở tờ phiếu. */
  /* 21/09/2026: Boss chọn "dịu màu xuống, chữ sáng" → bản nền tối của 6 màu ô nay nằm ở
     cuối css/lop.css (khối "NỀN TỐI LẦN 5"). Luật cũ ép chữ đen đã gỡ. */
  /* Đang bật chế độ tô sáng: con trỏ thành cây bút, ô nào rê vào cũng viền lên. */
  .cts-cuon.dang-tomau td { cursor:crosshair; }
  .cts-cuon.dang-tomau td:hover { box-shadow:inset 0 0 0 2px var(--cam); }
  .cts-nut-mau { display:inline-flex; align-items:center; gap:6px; }
  .cts-o-mau { width:19px; height:19px; border-radius:var(--r-sm); border:1px solid var(--vien);
               cursor:pointer; padding:0; }
  .cts-o-mau.chon { box-shadow:0 0 0 2px var(--muc); }
  .cts-bang-mau { display:flex; gap:6px; align-items:center; flex-wrap:wrap; }
  .cts-an-ds { max-height:min(46vh,430px); overflow:auto; border:1px solid var(--vien);
    border-radius:var(--r-md); padding:4px; }
  .cts-an-hang { display:flex; align-items:center; gap:9px; padding:6px 8px; border-radius:var(--r-sm);
    cursor:pointer; font-size:13px; }
  .cts-an-hang:hover { background:var(--nen2); }
  .cts-an-hang input { width:15px; height:15px; flex:none; cursor:pointer; }
  .cts-an-ten { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cts-an-ghi { flex:none; font-size:11.5px; color:var(--mo); }
  .cts-cd-hang { display:flex; gap:9px; align-items:center; padding:7px 0;
                 border-bottom:1px solid var(--vien); flex-wrap:wrap; }
  .cts-cd-hang:last-child { border-bottom:none; }
  .cts-cd-ten { flex:1; min-width:170px; font-size:13.5px; }
  /* ═══ 🎓 CHỮ MƯỢN CỦA HỒ SƠ TEST (Coder 2 giao sang, Designer dựng 10/09/2026) ═══
     Cột "Điểm test" và "Lớp đăng ký" của Sổ tuyển sinh không do nhân viên gõ mà lấy
     thẳng từ Hồ sơ test. Nhìn phải BIẾT NGAY là chữ mượn, nhưng vẫn đọc thoải mái —
     nên nhạt hơn một nấc và nghiêng nhẹ, không đổi cỡ chữ.

     ⛔ HAI BIẾN MÀU ĐÃ ĐỔI so với bản Coder 2 cắm tạm trong JS: họ viết
        `var(--chu-nhat)` và `var(--nen-mo)`, mà app KHÔNG CÓ hai biến ấy (đo được:
        0 lần dùng trong toàn bộ CSS). Chúng chỉ hiện đúng nhờ giá trị dự phòng, nên
        đổi nền tối là hỏng. Tên thật là `--mo` (514 chỗ) và `--nen2` (178 chỗ). */
  .cts-tu-test { color:var(--mo); font-style:italic; cursor:pointer; }
  .cts-tu-test:hover { text-decoration:underline; }
  /* Chấm báo lệch: nhỏ, màu cảnh báo, đứng sát chữ. */
  .cts-lech-test { color:var(--cam); margin-left:4px; cursor:pointer; font-size:15px; line-height:1; }
  .cts-lech-test:hover { filter:brightness(.85); }
  /* Dòng chữ nhỏ cạnh tên sổ. */
  .cts-tin-test { font-size:11.5px; color:var(--mo); margin-left:8px; white-space:nowrap; }
  /* Bảng trong hộp — CHỖ DUY NHẤT được xuống dòng cho từng lớp. */
  .cts-hop-lop { width:100%; border-collapse:collapse; margin:6px 0 10px; }
  .cts-hop-lop th, .cts-hop-lop td { border:1px solid var(--vien); padding:5px 8px;
                                     text-align:left; font-size:13px; }
  .cts-hop-lop th { background:var(--nen2); font-weight:600; }
  .cts-hop-diem { font-size:18px; margin:8px 0 12px; }
  .cts-hop-lech { border:1px solid var(--cam); background:var(--nen2); border-radius:var(--r-md);
                  padding:10px; margin-top:10px; }
  .cts-hop-lech p { margin:0 0 6px; }
  .cts-hop-nhac { display:block; margin-top:6px; font-size:12px; color:var(--mo); }
  /* ✏️ Hộp sửa danh sách lựa chọn của một cột (Coder 2 giao sang, Boss 09/09/2026).
     Cùng lý do đổi biến màu như khối 🎓 ở trên: --chu-nhat không tồn tại, tên thật là --mo. */
  .cts-ds-ds { list-style:none; margin:0 0 10px; padding:0; max-height:46vh; overflow-y:auto; }
  .cts-ds-dong { display:flex; align-items:center; gap:6px; margin-bottom:5px; }
  .cts-ds-o { flex:1 1 auto; min-width:120px; padding:5px 7px; border:1px solid var(--vien);
              border-radius:var(--r-sm); font-size:13px; }
  .cts-ds-dem { flex:0 0 auto; min-width:66px; text-align:right; font-size:11.5px; color:var(--mo); }
  .cts-ds-lac { border-top:1px solid var(--vien); margin-top:12px; padding-top:10px; }
  .cts-ds-lac p { margin:0 0 6px; font-size:12.5px; color:var(--mo); }
  .cts-ds-nhat { margin:0 5px 5px 0; }
  /* ═══ 🧑‍🎓 BÁO CÁO TỪNG HỌC SINH TRONG LỚP (13/08/2026) ═══
     Cô Quỳnh: *"báo cáo giáo viên phải có phần báo cáo từng lớp và phải hiển thị đủ
     học sinh trong lớp"*. Bấm tên lớp là bung ra ngay dưới dòng lớp đó — không mở
     màn mới, không mất chỗ đang xem. */
  .bc-hang-lop { cursor:pointer; }
  .bc-hang-lop:hover td { background:var(--xanh-nhat); }
  .bc-hang-lop .tths-ten::before { content:""; display:inline-block; width:0; height:0;
      margin-right:6px; vertical-align:middle;
      border-top:4px solid transparent; border-bottom:4px solid transparent;
      border-left:5px solid var(--mo); transition:transform .12s; }
  .bc-hang-lop.mo .tths-ten::before { transform:rotate(90deg); }
  .bc-hs-o > td { padding:0 !important; background:var(--nen2); }
  .bc-hs-bang { width:100%; border-collapse:collapse; font-size:12.5px; }
  .bc-hs-bang th, .bc-hs-bang td { padding:5px 9px; border-bottom:1px solid var(--vien);
      text-align:center; white-space:nowrap; }
  .bc-hs-bang th { font-size:11px; font-weight:700; color:var(--mo); text-align:center; }
  .bc-hs-bang th:nth-child(2), .bc-hs-bang td:nth-child(2) { text-align:left; }
  .bc-hs-bang td:first-child { color:var(--mo); font-size:11.5px; }
  .bc-hs-bang tr.da-nghi td { opacity:.6; }
  .bc-hs-bang tr.da-nghi td:nth-child(2) { text-decoration:line-through; }
  .bc-hs-chan { padding:7px 10px; font-size:12px; color:var(--mo); }
  /* ═══ TỪNG BUỔI CỦA MỘT EM (13/08/2026) ═══
     Cô Quỳnh: *"tôi cần sự chi tiết chứ không phải tính tổng"*. Bấm vào một em là
     bung ra đủ các buổi em đó đã học. Lùi vào trong một bậc để nhìn là biết đang ở
     bậc sâu hơn — lớp ⟶ học sinh ⟶ từng buổi. */
  .bc-hs-bang tr.bc-hang-em { cursor:pointer; }
  .bc-hs-bang tr.bc-hang-em:hover td { background:var(--xanh-nhat); }
  .bc-hs-bang tr.bc-hang-em.mo td { background:var(--xanh-nhat); font-weight:600; }
  .bc-buoi-o > td { padding:0 0 0 28px !important; background:var(--nen); }
  .bc-buoi-bang { width:100%; border-collapse:collapse; font-size:12.5px; }
  .bc-buoi-bang th, .bc-buoi-bang td { padding:5px 9px; border-bottom:1px solid var(--vien);
      text-align:left; white-space:nowrap; }
  .bc-buoi-bang th { font-size:11px; font-weight:700; color:var(--mo); }
  .bc-buoi-bang tr.trong td { color:var(--mo); }
  .bc-vi-sao { font-size:11.5px; color:var(--mo); font-style:italic; }
  /* ⛔ Dùng NỀN NHẠT + CHỮ ĐẬM MÀU, không dùng chấm tròn hay ký tự thay hình —
     luật cô Quỳnh cấm "ký tự thay hình". Chữ thì máy nào cũng hiện đúng. */
  .bc-tt { display:inline-block; padding:1px 7px; border-radius:var(--r-sm); font-weight:600; font-size:11.5px; }
  .bc-tt.co   { background:#E6F4EA; color:#1E7C45; }
  .bc-tt.vang { background:#FBEAE8; color:#B3403A; }
  body.toi .bc-tt.co   { background:#1B3325; color:#7FD1A0; }
  body.toi .bc-tt.vang { background:#3A2220; color:#F0A29C; }
  /* ===== 🧩 CÔNG CỤ TỰ TẠO (06/08/2026) ===== */
  /* Ô trong bảng: viền chỉ hiện khi rê chuột / đang gõ, để bảng nhiều cột không
     thành một rừng ô vuông. Nền trong suốt cho ăn theo nền tối/sáng. */
  .ct-bang td { padding:3px 4px; }
  .ct-o { width:100%; min-width:96px; box-sizing:border-box; border:1px solid transparent;
    background:transparent; color:var(--chu); border-radius:var(--r-sm); padding:5px 6px;
    font:inherit; font-size:13.5px; outline:none; }
  .ct-o:hover { border-color:var(--vien); }
  .ct-o:focus { border-color:var(--muc); background:var(--nen-o);
    box-shadow:0 0 0 3px color-mix(in srgb, var(--muc) 16%, transparent); }
  select.ct-o { cursor:pointer; }
  /* Đang gửi lên máy chủ / gửi hỏng — người dùng phải THẤY, không được lặng lẽ. */
  .ct-o.ct-dang-luu { border-color:var(--muc); opacity:.65; }
  .ct-o.ct-loi { border-color:var(--do); background:color-mix(in srgb, var(--do) 10%, transparent); }
  .ct-bang td.ct-cuoi { text-align:center; }
  .ct-bang td.ct-cuoi .nut-do { padding:3px 9px; font-size:12px; }
  /* Màn xem trước cột lúc nhập */
  .ct-cot-ds { max-height:44vh; overflow:auto; border:1px solid var(--vien); border-radius:var(--r-md); }
  .ct-cot-hang { display:flex; gap:7px; align-items:center; padding:6px 9px;
    border-bottom:1px solid var(--vien); }
  .ct-cot-hang:last-child { border-bottom:0; }
  .ct-cot-ten { flex:1; min-width:0; height:32px; border:1px solid var(--vien);
    border-radius:var(--r-md); padding:0 8px; font:inherit; font-size:13.5px;
    background:var(--nen-o); color:var(--chu); }
  .ct-cot-kieu { height:32px; border:1px solid var(--vien); border-radius:var(--r-md);
    background:var(--nen-o); color:var(--chu); font:inherit; font-size:13px; }
  .ct-cot-hang .goiy { min-width:82px; font-size:12px; }
  .ct-cot-bo { padding:4px 10px; font-size:12px; }
  .ct-vaitro { display:flex; flex-wrap:wrap; gap:6px 14px; margin-top:5px; }
  .ct-vt { display:inline-flex; align-items:center; gap:6px; font-size:13.5px; cursor:pointer; }

  .home-note-tb { display:flex; gap:5px; margin-bottom:9px; }
  /* Nút công cụ ăn theo tông GIẤY của ô ghi chú cho liền một khối. */
  .hn-nut { border:1px solid #E4DAC0; background:#FDFAF0; color:#7A6E52;
    border-radius:var(--r-md); width:30px; height:28px; display:inline-flex; align-items:center;
    justify-content:center; font-size:13px; line-height:1; cursor:pointer; font-family:inherit;
    transition:color .12s, border-color .12s, background .12s; }
  .hn-nut:hover { color:#3B352A; border-color:#C9A94A; background:#FBF5E2; }
  body.toi .hn-nut { background:#312D20; border-color:#48412F; color:#BDB49D; }
  body.toi .hn-nut:hover { color:#DFD8C6; border-color:#B99A40; background:#3A3526; }
  /* 📝 06/08 (cô Quỳnh: "vẫn nên thiết kế kiểu MỘT CÁI NOTE THẬT chứ không mọi người
     sẽ không hình dung nó là gì — để màu vàng, có các đường kẻ sẵn như các dòng luôn,
     và làm chuyên nghiệp hơn").
     Giữ ĐÚNG dáng cuốn sổ nhưng làm tinh lại, khác bản 03/08 ở bốn chỗ:
       · Giấy ngà TRẦM (#FDFAF0) thay vàng chanh — vẫn ra "giấy" mà không chói.
       · Dòng kẻ MỜ HẲN (đen 5%) thay vì vàng đậm — đủ dẫn mắt, không cắt vụn chữ.
       · Dòng kẻ khớp CHÍNH XÁC với `line-height` (28px) nên chữ nằm ĐÚNG trên dòng.
         Bản cũ lệch nhau nên nhìn rối. Đổi cỡ chữ thì phải sửa cả hai số này.

     ⛔ ĐỪNG THÊM LẠI CÁI LỀ ĐỎ DỌC. Tôi có thử một vạch đỏ bên trái cho giống sổ
     tay thật (06/08 tối) — cô Quỳnh gạt ngay: *"tự nhiên bị 1 thanh đỏ chặn giữa
     tốn diện tích"*. Đúng: nó ăn mất 44px bề ngang của một ô vốn đã hẹp, mà ô ghi
     chú thì cần CHỖ VIẾT chứ không cần trang trí. Dòng kẻ ngang là đủ để nhận ra
     đây là cuốn sổ rồi. */
  .home-note-o { min-height:168px; border:1px solid #E4DAC0; border-radius:var(--r-lg);
    padding:9px 14px 12px; font-size:14.5px; color:#3B352A;
    line-height:28px; overflow-wrap:anywhere; outline:none;
    box-shadow:inset 0 1px 3px rgba(120,100,50,.06);
    background-color:#FDFAF0;
    background-image:
      repeating-linear-gradient(transparent, transparent 27px, rgba(60,50,20,.09) 27px, rgba(60,50,20,.09) 28px);
    background-attachment:local;             /* kẻ CUỘN THEO chữ, không đứng yên */
    transition:border-color .12s, box-shadow .12s; }
  .home-note-o:focus { border-color:#C9A94A;
    box-shadow:inset 0 1px 3px rgba(120,100,50,.06), 0 0 0 3px rgba(201,169,74,.22); }
  .home-note-o:empty::before { content:attr(data-ph); color:#A79A7C; }
  /* 🌙 Nền tối: vẫn là "cuốn sổ" nhưng giấy màu trầm ấm, kẻ mờ — không chói mắt. */
  body.toi .home-note-o { background-color:#312D20; border-color:#48412F; color:#DFD8C6;
    box-shadow:inset 0 1px 3px rgba(0,0,0,.25);
    background-image:
      repeating-linear-gradient(transparent, transparent 27px, rgba(255,246,214,.09) 27px, rgba(255,246,214,.09) 28px); }
  body.toi .home-note-o:empty::before { color:#B8B1A3; }
  body.toi .home-note-o:focus { border-color:#B99A40;
    box-shadow:inset 0 1px 3px rgba(0,0,0,.25), 0 0 0 3px rgba(185,154,64,.24); }
  .home-note-o a { color:var(--muc); text-decoration:underline; }
  /* Nút đang BẬT (đậm · tô sáng · link) — nền nhấn kín đáo, không chói. */
  .hn-nut.active { background:var(--xanh-nhat); border-color:var(--muc); color:var(--muc); }
  /* Riêng nút TÔ SÁNG bật thì giữ sắc vàng — đó là màu của chính việc tô sáng. */
  .hn-nut[data-fmt="highlight"].active { background:#FFF3D9; border-color:#D9AE5A; color:#8A6300; }
  body.toi .hn-nut[data-fmt="highlight"].active { background:rgba(217,174,90,.18); border-color:rgba(217,174,90,.5); color:#E4C88A; }
  /* 🖍 Chế độ bút: con trỏ chuột thành CÂY BÚT tô — bôi chọn chữ nào mới tô chữ đó. */
  .home-note-o.hn-but-mo { cursor: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='26'%20height='26'%3E%3Cg%20transform='rotate(45%2013%2013)'%3E%3Crect%20x='10'%20y='3'%20width='6'%20height='12'%20rx='1'%20fill='%23FFD34D'%20stroke='%237A5A00'%20stroke-width='1'/%3E%3Cpath%20d='M10%2015h6l-3%206z'%20fill='%23FFF0B3'%20stroke='%237A5A00'%20stroke-width='1'/%3E%3C/g%3E%3C/svg%3E") 6 20, crosshair; }
  .home-note-tt { font-size:12px; margin-top:6px; min-height:16px; color:var(--mo); }
  .home-note-tt.xong { color:#2E7D32; } .home-note-tt.loi { color:var(--do); } .home-note-tt.dang { color:var(--mo); }
  /* ⏰ Lớp đến giờ CUỘN trong (cô Quỳnh 03/08: hiện hết ra kéo dài cả trang) — cap ~5 lớp rồi cuộn. */
  /* 🏢 05/08 (cô Quỳnh): đã bỏ lưới công cụ dưới Trang chủ → cho "Tin hôm nay" CAO HẲN
     lên, nhìn được đầy đủ, ít phải cuộn. */
  /* 06/08: BỎ trần chiều cao ở khung ngoài. Từ khi Tin hôm nay đổi sang kiểu bảng
     điều khiển, MỖI THẺ đã tự cuộn trong (`.htin-o-than` cap 236px) — để thêm trần
     ở ngoài nữa thì thành hai lớp cuộn lồng nhau, và thẻ hàng dưới bị cắt cụt. */
  .home-gio-cuon { max-height:none; overflow:visible; }
  /* Khung (Thông báo · Lớp đến giờ · Công cụ) — chiều sâu đồng bộ với thẻ công cụ mới. */
  /* 🔲 05/08 — SẮC NÉT: bo góc gọn lại, viền rõ, bóng ngắn & nét thay vì mờ toả rộng */
  /* 🎨 22/08/2026 — THẺ theo nếp shadcn: bo 14px, bóng gần như không thấy, và
     ĐẦU THẺ KHÔNG CÓ DẢI NỀN RIÊNG.
     ⛔ Dải nền ở đầu thẻ (`background:rgba(255,255,255,.4)` cũ) là thứ chia đôi thẻ
        thành hai mảng màu khác nhau — mắt đọc thành HAI khối chứ không phải một.
        Trong cả bốn ảnh cô Quỳnh gửi, tiêu đề thẻ nằm thẳng trên nền thẻ.
     ⛔ Nét 800 hạ về 600. Nét 800 là một trong ba dấu hiệu lộ giao diện dựng bằng
        AI rõ nhất — đã ghi trong ghi chú, và đây là chỗ nó xuất hiện dày nhất. */
  .home-khoi { border:1px solid var(--vien); border-radius:var(--r-xl); overflow:hidden;
    background:var(--the); box-shadow:var(--bong-1); }
  .home-khoi-dau { display:flex; align-items:center; gap:9px; padding:14px 18px 12px;
    font-weight:600; font-size:15px; letter-spacing:-.01em;
    border-bottom:1px solid var(--vien-nhe); background:transparent; }
  /* 🎨 Biểu tượng đầu thẻ mang màu trung tâm. Tiêu đề vẫn là chữ đen: chữ teal
     giữa trang trắng trông như một đường siêu liên kết bấm được. */
  .home-khoi-dau .ico, .home-khoi-dau i[class^="ic-"] { color:var(--xanh); }
  .home-khoi-than { padding:14px 16px; }
  /* Khung "lớp đến giờ" */
  .home-gio-ds { display:flex; flex-direction:column; gap:8px; }
  /* Khung "Thông báo nhắc việc" CUỘN trong (cô Quỳnh 02/08: nhiều việc thì cuộn, đừng kéo dài cả trang). */
  .home-tb-cuon { max-height:216px; overflow-y:auto; padding-right:4px; }
  /* Bung hết thì nới khung cao hơn hẳn — cuộn 40 việc trong một ô 216px thì bung
     cũng như không. Vẫn có trần theo chiều cao màn để không đẩy khối khác đi mất. */
  .home-tb-cuon.het { max-height:min(70vh, 620px); }
  /* ⛔ Thanh cuộn lấy MÀU VIỀN chung của app. Bản trước gõ thẳng #E0B9B3 — hồng
     đất, không khớp biến nào, và không nói lên điều gì về công việc. */
  .home-tb-cuon::-webkit-scrollbar { width:8px; } .home-tb-cuon::-webkit-scrollbar-thumb { background:var(--vien); border-radius:var(--r-sm); }
  /* ⛔ 22/08/2026 — BỎ `transform:translateX(2px)` khi rê chuột. Dòng nhúc nhích
     khi con trỏ đi qua là thứ gây mất tập trung mà chẳng nói thêm được gì — đổi nền
     đã đủ cho biết "đang trỏ vào dòng này". Danh sách 20 việc mà dòng nào cũng
     nhảy sang phải thì cả cột rung theo con trỏ. */
  .home-gio-1 { display:flex; align-items:center; gap:10px; padding:10px 12px;
    border-radius:var(--r-md);
    border:1px solid var(--vien); cursor:pointer; background:var(--the); transition:background .12s; }
  .home-gio-1:hover { background:var(--xanh-nhat); border-color:var(--xanh); }
  .home-gio-1.dang { border-left:3px solid var(--o-tot); }
  /* Việc QUÁ HẠN: vạch đỏ mảnh bên trái. Trước đây là chấm tròn cam to trước mỗi dòng
     — năm dòng quá hạn là năm chấm cam, nhìn rối và trẻ con. */
  .home-gio-1.sap  { border-left:3px solid #C0504D; }
  /* Icon nét mảnh MỘT MÀU, cùng cỡ, cùng màu xám — không emoji, không mỗi cái một màu. */
  .home-gio-1 .hv-ico { flex:none; display:inline-flex; align-items:center; justify-content:center;
    width:26px; height:26px; border-radius:var(--r-md); background:var(--nen2); color:var(--mo); }
  .home-gio-1 .hv-ico i { width:15px; height:15px; }
  .home-gio-1:hover .hv-ico { color:var(--xanh-dam); }
  .home-gio-1 .hv-chu { min-width:0; line-height:1.45; }
  /* Chữ phụ (người nhận · cơ sở · hạn) nhạt hơn hẳn, để TÊN VIỆC nổi lên một mình. */
  .home-gio-1 .hv-phu { color:var(--mo); font-weight:500; }
  /* "Quá hạn" nói bằng CHỮ, gọn và nghiêm — đọc là hiểu, không phải đoán màu. */
  /* ⛔ 22/08/2026 — BỎ `text-transform:uppercase` VÀ `letter-spacing`.
     Hai thứ này cộng với nét 800 là đúng ba dấu hiệu lộ giao diện AI. Riêng với
     tiếng Việt còn tệ hơn một bậc: chữ IN HOA làm MẤT DẤU trên màn hình nhỏ
     ("QUÁ HẠN" mất dấu sắc thành "QUA HAN") và đọc chậm hơn hẳn chữ thường. */
  .home-gio-1 .hv-qua { display:inline-block; font-size:11px; font-weight:600;
    color:#B03A36; border:1px solid #E4B9B7; background:#FBF0EF;
    border-radius:var(--r-sm); padding:1px 6px;
    margin-right:5px; vertical-align:1px; }
  body.toi .home-gio-1 .hv-qua { color:#F0A9A5; border-color:#5C3230; background:#3A2422; }
  .home-gio-ten { font-weight:700; }
  .home-gio-nhan { font-size:12px; margin-left:auto; padding:3px 10px; border-radius:var(--r-xl); font-weight:700; white-space:nowrap; }
  /* Nhãn "Mở →" là thứ PHỤ, không được tranh chỗ với nội dung việc. Một màu xám
     nhạt duy nhất, chỉ đậm lên khi rê chuột vào dòng. */
  .home-gio-nhan { color:var(--mo); background:var(--nen2); border:1px solid var(--vien);
    font-weight:600; }
  .home-gio-1:hover .home-gio-nhan { color:var(--xanh-dam); border-color:var(--xanh); }
  .home-gio-1.dang .home-gio-nhan, .home-gio-1.sap .home-gio-nhan {
    color:var(--mo); background:var(--nen2); }
  .home-gio-1.sap:hover .home-gio-nhan { color:var(--xanh-dam); border-color:var(--xanh); }
  /* 🎨 Lưới CÔNG CỤ kiểu thẻ dịch vụ chuyên nghiệp (cô Quỳnh 02/08 — theo ảnh app mẫu:
     thẻ có chiều sâu, icon bóng, mô tả đầy đủ, vạch màu đặc trưng từng công cụ). */
  .home-luoi { display:grid; grid-template-columns:repeat(auto-fill,minmax(212px,1fr)); gap:13px; }
  .home-o { display:flex; align-items:center; gap:12px; text-align:left; padding:14px 15px;
    border:1px solid var(--vien); border-radius:var(--r-xl); cursor:pointer; position:relative; overflow:hidden;
    background:linear-gradient(180deg,#fff 0%, var(--tint,#f4f7fa) 165%);
    box-shadow:0 3px 10px rgba(20,50,70,.06), 0 1px 2px rgba(20,50,70,.05);
    transition:transform .13s ease, box-shadow .17s ease;
    animation:homeOvao .42s ease both; animation-delay:calc(var(--i,0) * .035s); }
  .home-o::before { content:""; position:absolute; left:0; top:0; bottom:0; width:5px; background:var(--mau,#14A0A0); }
  .home-o:hover { transform:translateY(-4px); box-shadow:0 16px 32px rgba(20,50,70,.18), 0 3px 8px rgba(20,50,70,.08); }
  .home-o:active { transform:translateY(-1px); }
  /* Icon SVG thay cho emoji (08/08/2026). Icon dùng CSS mask nên ăn theo
     `color` — đặt màu chủ đề của thẻ vào đây là icon tự đổi màu theo. */
  .home-o-ico > i[class^="ic-"] { width:26px; height:26px; margin-right:0; background:var(--mau,#14A0A0); }
  .home-o-ico { flex:none; width:50px; height:50px; border-radius:var(--r-xl); display:flex; align-items:center; justify-content:center;
    font-size:25px; line-height:1; background:var(--tint,#EEF2F6);
    background-image:linear-gradient(140deg, rgba(255,255,255,.75), rgba(255,255,255,0) 60%);
    box-shadow:0 6px 13px -5px var(--mau,#14A0A0), inset 0 0 0 1px rgba(255,255,255,.6); }
  .home-o-txt { display:flex; flex-direction:column; gap:2px; min-width:0; flex:1; }
  .home-o .lb { font-size:14px; font-weight:700; color:var(--chu); line-height:1.2; }
  .home-o .mota { font-size:11.5px; color:var(--mo); line-height:1.32; }
  .home-o-mui { flex:none; color:var(--mau,#14A0A0); font-weight:700; font-size:16px; opacity:0; transform:translateX(-5px);
    transition:opacity .15s, transform .15s; }
  .home-o:hover .home-o-mui { opacity:.85; transform:translateX(0); }
  .home-o .cc-badge { position:absolute; top:8px; right:10px; }
  @keyframes homeOvao { from{opacity:0; transform:translateY(12px)} to{opacity:1; transform:translateY(0)} }
  @media (prefers-reduced-motion:reduce) { .home-o { animation:none; } }
  /* Nút "Hiện hết N việc" / "Thu gọn" — thay cho dòng chữ chết cũ (cô Quỳnh 16/08). */
  .home-viec-them { width:100%; border:1px dashed var(--vien); background:none;
    color:var(--mo); font-family:inherit; font-size:12.5px; font-weight:500;
    padding:7px; border-radius:var(--r-md); cursor:pointer; margin-top:2px; }
  .home-viec-them:hover { color:var(--xanh-dam); border-color:var(--xanh);
    background:var(--xanh-nhat); }
  .home-trong { color:var(--mo); font-size:13px; padding:4px 2px; }
  @media (max-width:820px) {
    /* 📱 Điện thoại (cô Quỳnh 03/08: "nhiều chữ quá, rối mắt, dài, không đẹp"):
       BỎ mô tả từng ô, xếp ô DỌC gọn (icon trên, tên dưới), hero rút gọn. */
    /* ══════════════════════════════════════════════════════════════════════════
       📱 08/09/2026 — CÁC MẢNG TRẮNG DÍNH LIỀN NHAU (nếp Facebook)
       ──────────────────────────────────────────────────────────────────────────
       Boss gửi ảnh chụp app bên cạnh ảnh Facebook: *"nó cứ có 1 số cái chỗ tách
       rời nho nhỏ ở các khu khác nhau, như kiểu ở trên cùng tách ra 1 chút so với
       cái thông báo ở dưới… tôi muốn gom hết tất cả lại"*.

       Ba thứ đẻ ra khe hở, phải dẹp CẢ BA — bỏ sót một là vẫn thấy rời:
         ① `gap:13px` giữa các khối        → 0
         ② `border-radius` bo góc từng khối → 0 (bo góc là hở bốn góc)
         ③ viền TRÁI/PHẢI + bóng đổ         → bỏ; chỉ chừa một VẠCH NGĂN ở đáy

       ⛔ VẠCH NGĂN PHẢI CÒN. "Liền nhau" không phải là "dính thành một cục không
          phân biệt được". Facebook cũng có vạch mảnh giữa các phần — thiếu nó thì
          tiêu đề khối sau dán vào nội dung khối trước, đọc không ra ranh giới.
       ⛔ CHỈ ÁP TRÊN ĐIỆN THOẠI. Máy tính vẫn là các thẻ rời có bo góc — bên ấy
          màn rộng, thẻ rời mới ra bố cục hai cột.
       ══════════════════════════════════════════════════════════════════════════ */
    .home-boc { gap:0; }
    .home-khoi {
      border:0; border-bottom:1px solid var(--vien);
      border-radius:0; box-shadow:none;
    }
    /* Khối cuối không cần vạch — dưới nó đã là khoảng chừa cho thanh đáy. */
    .home-boc > *:last-child .home-khoi,
    .home-boc > .home-khoi:last-child { border-bottom:0; }
    /* ═════════════════════════════════════════════════════════════════════════
       📝 DẢI CHÀO BO HAI GÓC DƯỚI + GHI CHÚ GẬP VÀO TRONG — Boss 08/09/2026
       ─────────────────────────────────────────────────────────────────────────
       *"cái block thanh tên chào buổi sáng và có avatar này tôi muốn thiết kế cho
        nó bo tròn 2 góc như 1 block như cũ… nền đằng sau đã gắn liền rồi nên tôi
        muốn block này bo tròn như cũ cho đẹp"* — và *"thiết kế cho cái note này vào
        trong cái block chào buổi sáng đó… ấn vào cái nút bên phải thì cái note sẽ
        có animation kéo xuống bên dưới cái block avatar"*.

       BO HAI GÓC DƯỚI, không phải bốn: mép trên của dải chào dán thẳng vào thanh
       MyPAS ở trên. Bo cả bốn góc là hở ra hai khe xám ở trên — đúng thứ vừa dọn đi
       sáng nay.

       ⛔ Ô GHI CHÚ KHÔNG BỊ DỜI TRONG HTML. Nó vẫn nằm trong `.home-cot-phai` như
          cũ; ở đây chỉ dùng `order` kéo nó lên nằm ngay dưới dải chào. Dời thẻ thật
          là cột phải của bố cục hai cột (máy tính, ≥1100px) rỗng không.
       ⛔ HAI BÁN KÍNH PHẢI ĐỔI CHỖ CHO NHAU khi ghi chú mở ra: lúc đóng thì dải chào
          giữ góc dưới; lúc mở thì dải chào phải VUÔNG lại và ô ghi chú nhận góc dưới,
          không thì giữa hai thẻ hiện một vệt cắt, nhìn thành hai mảnh rời.
       ═════════════════════════════════════════════════════════════════════════ */
    .home-hero { border-radius:0 0 18px 18px; box-shadow:none; margin:0;
      transition:border-radius .34s cubic-bezier(.22,.9,.28,1); }
    body.home-note-mo .home-hero { border-radius:0; }

    /* Kéo ô ghi chú lên nằm ngay sau dải chào. Mọi khối khác giữ `order` mặc định
       là 0, nên chỉ cần đẩy hai thẻ này xuống số âm. */
    .home-boc > .home-hero { order:-2; }
    .home-boc > .home-cot-phai { order:-1; }

    /* Phần gập. ⛔ Dùng `grid-template-rows: 0fr → 1fr` chứ KHÔNG dùng `max-height`:
       chiều cao ô ghi chú thay đổi theo lượng chữ đã viết, mà `max-height` thì phải
       đoán trước một con số trần. Đoán thấp là cắt cụt chữ, đoán cao là đoạn cuối
       hiệu ứng chạy tuột đi rất nhanh rồi khựng. Cách này trượt đúng bằng chiều cao
       thật, dài ngắn gì cũng mượt.
       ⛔ `min-height:0` ở thẻ con là BẮT BUỘC. Thiếu nó thì thẻ con giữ nguyên chiều
          cao tự nhiên, ô lưới không co lại được, và phần gập không bao giờ đóng. */
    .home-cot-phai { display:grid; grid-template-rows:0fr;
      transition:grid-template-rows .34s cubic-bezier(.22,.9,.28,1); }
    .home-cot-phai > * { overflow:hidden; min-height:0; }
    /* ⛔ ĐO ĐƯỢC 08/09/2026: gập hết cỡ mà ô ghi chú vẫn cao 1px, vì `grid-template
       -rows:0fr` bóp phần RUỘT về 0 nhưng VIỀN thì vẫn vẽ. Kết quả là một vạch kẻ
       mảnh nằm ngay dưới dải chào lúc ghi chú đang đóng — trông như lỗi hiển thị.
       Nên lúc đóng phải bỏ hẳn viền; lúc mở nó tự có lại. */
    body:not(.home-note-mo) .home-cot-phai > .home-note-khoi { border-bottom:0; }
    body.home-note-mo .home-cot-phai { grid-template-rows:1fr; }
    body.home-note-mo .home-note-khoi { border-radius:0 0 18px 18px; }
    @media (prefers-reduced-motion: reduce) {
      .home-cot-phai, .home-hero { transition:none; }
    }

    /* Nút gập/mở: viên tròn trong mờ nằm ở mép phải dải chào — chỗ khối ngày để lại
       khi `@media (max-width:560px)` ẩn nó đi.
       ⛔ 40x40 chứ không bằng đúng cái icon: ngón cái không bấm trúng ô 24px. */
    .home-hero-note { display:flex; align-items:center; justify-content:center;
      gap:1px; flex:none; margin-left:auto; width:40px; height:40px; padding:0;
      border:1px solid rgba(255,255,255,.34); border-radius:50%;
      background:rgba(255,255,255,.16); color:#fff; cursor:pointer;
      -webkit-tap-highlight-color:transparent;
      transition:background .2s ease, transform .2s cubic-bezier(.34,1.5,.64,1); }
    .home-hero-note:active { transform:scale(.9); background:rgba(255,255,255,.3); }
    .home-hero-note:focus-visible { outline:2px solid #fff; outline-offset:2px; }
    .home-hero-note .hn-giay { width:17px; height:17px; flex:none; fill:none;
      stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
    /* Mũi tên quay 180° khi mở — dấu hiệu duy nhất cho biết bấm lần nữa là đóng. */
    .home-hero-note .hn-mui { width:12px; height:12px; flex:none; fill:none;
      stroke:currentColor; stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
      margin-left:-2px; transition:transform .3s cubic-bezier(.22,.9,.28,1); }
    body.home-note-mo .home-hero-note .hn-mui { transform:rotate(180deg); }
    body.home-note-mo .home-hero-note { background:rgba(255,255,255,.3); }
    .home-hero { padding:13px 15px; gap:11px; }
    .home-hero-av { width:44px; height:44px; font-size:17px; }
    .home-hero-chao .loi { font-size:11.5px; }
    .home-hero-chao h2 { font-size:18px; margin:1px 0 3px; }
    .home-khoi-dau { padding:11px 14px; font-size:13.5px; }
    .home-khoi-than { padding:11px 12px; }
    .home-luoi { grid-template-columns:repeat(3,1fr); gap:9px; }
    .home-o { flex-direction:column; align-items:center; text-align:center; gap:7px; padding:13px 6px 11px; border-radius:var(--r-xl); }
    .home-o-txt { align-items:center; flex:none; }
    .home-o .mota { display:none; }                 /* bỏ mô tả dài → gọn, hết rối */
    .home-o-mui { display:none; }                    /* mũi tên → cũng bỏ trên điện thoại */
    .home-o-ico { width:44px; height:44px; font-size:22px; border-radius:var(--r-xl); }
    .home-o-ico > i[class^="ic-"] { width:23px; height:23px; }
    .home-o .lb { font-size:12px; line-height:1.22; }
  }
  @media (max-width:420px) { .home-luoi { grid-template-columns:repeat(2,1fr); } }
  /* 🖥️ 03/08 — Máy tính RỘNG: khung "Thông báo nhắc việc" thành CỘT BÊN PHẢI để xem
     nhiều tin cùng lúc (cô Quỳnh). Điện thoại giữ nguyên (thông báo nằm trong luồng). */
  @media (min-width:1100px) {
    .home-boc { display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:18px; align-items:start; }
    .home-boc > .home-hero { grid-column:1 / -1; }
    /* ⛔⛔ BẪY 06/08/2026 — ĐỪNG tách cột phải thành hai ô lưới nữa.
       Bản cũ đặt Nhắc việc ở (cột 2, hàng 2) và Ghi chú ở (cột 2, hàng 3). Lưới CSS bắt
       mọi ô CÙNG HÀNG phải cao bằng nhau, mà "Tin hôm nay" cũng nằm ở hàng 2 bên trái —
       nên hễ Tin hôm nay dài ra là hàng 2 cao theo, đẩy Ghi chú (hàng 3) tụt xuống tận
       đáy. Cô Quỳnh báo 06/08: "ghi chú cứ bị đẩy xuống nếu tin hôm nay dài ra; tôi muốn
       nó chỉ tụt khi Nhắc việc dài ra thôi."
       Nay gói cả cột phải vào MỘT ô lưới `.home-cot-phai` — bên trong nó tự xếp dọc, cao
       bao nhiêu là việc của riêng nó, không liên quan cột trái nữa. */
    /* 🟢 08/09/2026 — DẢI "ĐANG ONLINE" XUỐNG CUỐI TRANG. Boss: *"cái thanh người
       dùng bạn để ở dưới cùng của app cho tôi, chuyển xuống đó cho tôi nha"*.
       Chiếm trọn bề ngang nhưng KHÔNG ghim số hàng — để nó rơi xuống cuối lưới theo
       đúng thứ tự trong HTML.
       ⛔ LUẬT CŨ 19/08/2026 ĐÃ HẾT HIỆU LỰC: hồi ấy dải này phải nằm ĐÚNG GIỮA thanh
          tài khoản và Tin hôm nay (`grid-row:2`). Nay Boss đổi ý — đừng đọc chú thích
          cũ ở `js/tinh-nang.js` rồi ghim `grid-row` trở lại.
       ⛔ NHƯNG CÁI BẪY CỦA NGÀY 19/08 THÌ VẪN CÒN NGUYÊN, chỉ đổi chiều: khối này
          KHÔNG khai `grid-column:1 / -1` thì nó chui vào một cột và nằm cạnh khối
          khác, mà trên màn hẹp (dưới 1100px, lúc ấy `.home-boc` xếp dọc) lại trông
          đúng chỗ — rất dễ tưởng đã xong. Soi trên màn RỘNG rồi hãy tin. */
    /* ⛔ PHẢI GHIM `grid-row` — KHÔNG ghim thì nó KHÔNG rơi xuống cuối như tưởng.
       Mấy khối kia đều ghim hàng sẵn (`.home-tb-rong` và `.home-cot-phai` hàng 3,
       `.home-cot-trai` hàng 4), nên một khối không ghim sẽ được lưới nhét vào Ô TRỐNG
       SỚM NHẤT — tức hàng 2, ngay dưới lời chào, đúng chỗ Boss vừa bảo dời đi.
       Đã đo được: để trống thì đáy dải còn cách đáy trang 2.403px.
       ⛔ SỐ 5 LÀ "HÀNG SAU CÙNG" — ai thêm một hàng mới vào lưới này thì phải dời số
          này xuống theo, không thì dải online lại chen lên giữa. */
    .home-boc > #homeOnline { grid-column:1 / -1; grid-row:5; }
    /* 📋 21/08/2026 — THÔNG BÁO CÔNG VIỆC CHIẾM TRỌN HÀNG 3, đẩy hai cột xuống hàng 4.
       Cô Quỳnh: *"rất tù và bé và xấu và khó nhìn … nhìn được đầy đủ chữ công việc"*.
       Cột phải rộng đúng 340px — tên việc thật dài hơn thế nhiều, nhét vào đấy thì
       chỉ còn nước cắt cụt. Ra cả bề ngang mới bày đủ chữ được.
       ⛔ Đổi hàng của khối này thì PHẢI đổi hàng của cả hai cột theo, không thì chúng
          chồng lên nhau — cùng cái bẫy đã vấp ngày 19/08 với dải online. */
    /* ══════════════════════════════════════════════════════════════════════════════
       ⛔⛔ SỬA LỚN 21/08/2026 — CỘT PHẢI TỪNG LÀ MỘT DẢI TRẮNG CAO 3.300px
       ──────────────────────────────────────────────────────────────────────────────
       Cô Quỳnh: *"nhìn hổng hẳn 1 bảng trắng xóa ô không có gì nhìn xấu … nhất là ở
       trang chủ"*, và *"ko được để thừa ra khoảng trắng chứ nhìn mất thẩm mĩ lắm"*.

       ⛔ TÔI ĐÃ TỰ MỞ APP BẰNG TRÌNH DUYỆT VÀ ĐO (kiem-thu/soi-giao-dien.js, 21/08):
          trang chủ cao 3.550px, mà cột phải chỉ có mỗi ô "Ghi chú của tôi" cao ~150px.
          Còn lại là 3.300px × 340px TRẮNG TRƠN chạy dọc suốt bên phải màn hình, vì
          mọi khối bên dưới (Tin hôm nay · Thống kê · Báo cáo số) đều nằm trong cột
          TRÁI và dừng lại ở mép 1fr. Đúng thứ cô Quỳnh chê.

       CHỮA — BỎ HẲN CỘT PHẢI Ở PHẦN THÂN. Hai cột CHỈ tồn tại đúng một hàng:
         hàng 3 = [ Thông báo công việc | Ghi chú của tôi ]   ← hai khối đều NGẮN
         hàng 4 = [ ————— cả bề ngang: Tin hôm nay · Thống kê · Báo cáo ————— ]
       Không còn ô lưới nào bỏ trống, và mấy khối bên dưới rộng thêm 358px — bảng
       thống kê, biểu đồ, bảng lớp đều thở ra được.

       ⛔ HAI LUẬT CŨ VẪN GIỮ NGUYÊN, đừng phá:
         · (06/08) Ghi chú KHÔNG được bị "Tin hôm nay" đẩy đi. Nay Ghi chú ở hàng 3
           còn Tin hôm nay ở hàng 4 — hai hàng khác nhau, nên chiều cao của Tin hôm
           nay không với tới nó được nữa. Luật ấy nay đúng chặt hơn cả trước.
         · (21/08 sáng) Thông báo công việc phải đủ rộng để bày hết tên việc, không
           nhét vào cột 340px. Nay nó rộng 1fr ≈ 960px trên màn 1600 — vẫn thoải mái.
       ⛔ Đừng đưa thêm khối nào vào `.home-cot-phai`. Cột ấy nay chỉ dài bằng khối
          bên trái nó; nhét thêm là nó dài ra và lại đẻ khoảng trắng ở cột trái.
       ══════════════════════════════════════════════════════════════════════════════ */
    /* ⛔ ĐO ĐƯỢC 21/08/2026 (kiem-thu/soi-giao-dien.js): Thông báo công việc cao 163px,
       Ghi chú của tôi cao 257px — hở 94px trắng dưới khối bên trái. Lưới CSS kéo ô
       ngắn cho cao bằng ô cao, nhưng KHUNG bên trong nó thì không tự giãn theo, nên
       phần thừa rơi xuống thành khoảng trắng trong lòng thẻ.
       Nay cả hai khối là cột flex, và phần DANH SÁCH bên trong nhận `flex:1` để nuốt
       hết chỗ thừa. Bên nào ngắn hơn thì bên ấy giãn — không cần biết bên nào ngắn. */
    .home-boc > .home-tb-rong { grid-column:1; grid-row:3; align-self:stretch;
      display:flex; flex-direction:column; }
    .home-boc > .home-tb-rong > .home-tb-khoi { flex:1 1 auto; display:flex; flex-direction:column; }
    .home-boc > .home-tb-rong > .home-tb-khoi > .home-khoi-than { flex:1 1 auto; display:flex; flex-direction:column; min-height:0; }
    .home-boc > .home-tb-rong .home-tb-cuon { flex:1 1 auto; }
    .home-boc > .home-cot-phai { grid-column:2; grid-row:3; align-self:stretch; }
    /* Ô ghi chú DÃN ĐẦY chỗ trống bên cạnh Thông báo công việc — thừa mấy trăm pixel
       thì cho cô Quỳnh chỗ viết, đừng để trắng. */
    .home-boc > .home-cot-phai > .home-note-khoi { flex:1 1 auto; display:flex; flex-direction:column; }
    .home-boc > .home-cot-phai > .home-note-khoi > .home-khoi-than { flex:1 1 auto; display:flex; flex-direction:column; min-height:0; }
    .home-boc > .home-cot-phai > .home-note-khoi .home-note-tb { flex:none; }
    .home-boc > .home-cot-phai > .home-note-khoi .home-note-o { flex:1 1 auto; min-height:120px; }
    /* ⛔ 06/08 (lần 2) — CỘT TRÁI cũng phải là MỘT ô lưới, cùng lý do với cột phải.
       Cô Quỳnh: "sao thống kê lại bị tách ra hẳn một đoạn, không có sự gắn liền nếu
       Tin hôm nay ngắn." Vì Tin hôm nay và Thống kê từng là hai ô ở hai HÀNG khác
       nhau, mà hàng 2 bị cột phải (Nhắc việc + Ghi chú) kéo cao lên → Tin hôm nay
       ngắn là hở một khoảng trống hoác. Gói chung thì hai khối dính liền nhau. */
    /* ⛔ 21/08/2026 — CẢ BỀ NGANG (`1 / -1`), không còn kẹp ở cột 1 nữa. Đây chính là
       chỗ vá dải trắng: mọi khối thân trang nay chạy hết bề ngang. */
    .home-boc > .home-cot-trai { grid-column:1 / -1; grid-row:4; }
    /* ⛔ 21/08/2026 — CŨNG ĐỔI SANG CẢ BỀ NGANG. Dòng này bắt mọi khối con trực tiếp
       của .home-boc nằm ở cột 1, tức là chừa cột 2 trống. Sau khi bỏ dải trắng bên
       phải thì đây là chỗ SÓT LẠI cuối cùng còn ép khối vào nửa trái — quên nó là dải
       trắng mọc lại đúng chỗ cũ. */
    .home-boc > .home-khoi:not(.home-note-khoi) { grid-column:1 / -1; }
    /* Nhắc việc cap ~10 tin rồi cuộn (cô Quỳnh 03/08: đừng kéo dài trang chủ). */
    /* ⛔⛔ CÓ TRẦN CHIỀU CAO VÀ CÓ THANH CUỘN — cô Quỳnh 15/08/2026: *"khi hiện nhắc việc
     của mọi giáo vụ trong cơ sở ở trang chủ, khi dài ra sẽ có thanh cuộn cho đỡ bị quá
     dài, khuất luôn công cụ note bên dưới"*.
     Xem việc CẢ CƠ SỞ thì danh sách dài gấp mấy lần việc của một người — không chặn là
     nó đẩy ô Ghi chú của tôi xuống tận đáy trang, không ai thấy nữa.
     ⛔ 300px ≈ sáu dòng việc: đủ liếc thấy việc gấp, mà vẫn chừa chỗ cho ô ghi chú. */
  /* ⛔ 21/08/2026 — trần nâng từ 300px lên 460px. Khối này nay chiếm cả bề ngang và
     nằm TRÊN hai cột, nên nó không còn đẩy ô "Ghi chú của tôi" đi đâu được nữa —
     lý do đặt trần 300px ngày 15/08 không còn. Vẫn giữ trần để trang chủ không dài
     vô tận khi xem việc cả cơ sở. */
  /* ⛔ 21/08/2026 — HẠ TRẦN 460 → 360px. Khối nay chỉ còn việc CỦA HÔM NAY nên ngắn
     hẳn; giữ trần cũ là chừa một khoảng trống to đùng, đúng thứ cô Quỳnh gọi là
     "chiếm chỗ". Vẫn PHẢI có trần — ngày nhiều việc thì cuộn trong khối, không đẩy
     ba khối kia của Trang chủ xuống mất hút. */
  #homeThongBao .home-tb-cuon { max-height:360px; }
  #homeThongBao .home-tb-cuon.het { max-height:70vh; }

  /* ══════════════════════════════════════════════════════════════════════════════
     📋 THẺ VIỆC Ở TRANG CHỦ — cô Quỳnh 21/08/2026
     ──────────────────────────────────────────────────────────────────────────────
     *"nhìn được đầy đủ chữ công việc và thậm chí có thể tick xong công việc luôn"*.
     Nên: chữ XUỐNG DÒNG chứ không cắt cụt, và mỗi đầu mục có ô tích thật.
     ⛔ Không `white-space:nowrap`, không `text-overflow:ellipsis` ở `.hv-ten` —
        đó chính là thứ làm cụt chữ ở bản cũ. Cắt chữ là cách giấu vấn đề, không
        phải cách giải quyết.
     ══════════════════════════════════════════════════════════════════════════════ */
  /* ⛔ 21/08/2026 — LƯỚI THẺ, KHÔNG PHẢI DẢI NGANG. Cô Quỳnh gửi ảnh và bảo *"hơi
     chiếm chỗ và hơi xấu và bẹp dí"*: khối chiếm hết bề ngang mà mỗi việc lại là một
     thẻ dẹt kéo dài 1.700px, chữ dồn về mép trái, còn lại trống trơn.
     Nay xếp thành lưới — màn rộng thì hai ba thẻ một hàng, màn hẹp tự về một cột.
     Kèm bo góc mềm cho khỏi "cứng vuông góc" như cô nhận xét ở màn Công việc. */
  .home-tb-rong .home-tb-cuon { display:grid; gap:10px;
    grid-template-columns:repeat(auto-fill, minmax(300px, 1fr)); align-items:start; }
  /* Nút "Hiện hết …" và dòng việc trễ phải chiếm trọn hàng, không đứng thành một ô
     lưới lẻ loi bên cạnh mấy cái thẻ. */
  /* ⛔ 21/08/2026 — `.hv-rong2` PHẢI CÓ TRONG DANH SÁCH NÀY.
     Ruột thẻ là lưới `auto-fill minmax(300px, 1fr)` → trên màn rộng nó chia làm ba
     cột. Thứ gì KHÔNG khai `grid-column:1 / -1` thì rơi vào đúng MỘT ô lưới.
     Tôi chụp màn lại và thấy: khối "hôm nay không có việc nào" chỉ rộng bằng một
     phần ba thẻ, hai phần ba còn lại trắng trơn — tức là bản vá "chống ô trắng" tự
     nó lại đẻ ra một ô trắng to hơn. Đúng thứ cô Quỳnh chê.
     ⛔ Thêm khối mới vào ruột thẻ này thì NHỚ khai luôn ở đây, không thì lặp lại. */
  .home-tb-rong .home-tb-cuon > .hv-bang,
  .home-tb-rong .home-tb-cuon > .home-viec-them,
  .home-tb-rong .home-tb-cuon > .hv-tretruoc,
  .home-tb-rong .home-tb-cuon > .hv-rong,
  .home-tb-rong .home-tb-cuon > .hv-rong2,
  .home-tb-rong .home-tb-cuon > .home-gio-1 { grid-column:1 / -1; }
  }
  /* ⛔⛔ ĐÂY LÀ CHỖ ĐÓNG @media (min-width:1100px) — ĐỪNG XOÁ DẤU } NGAY TRÊN.
     Trước 22/08/2026 khối ấy chạy tuột thêm 150 dòng nữa và nuốt mất 54 luật của
     THẺ VIỆC, BĂNG CHUYỀN và CẶP NÚT ĐỔI — nên điện thoại không có tí thiết kế nào
     cho mấy thứ đó, đúng lời cô Quỳnh *"nút thay đổi xong nó ko load đúng thiết kế"*.
     Mọi luật viết TỪ ĐÂY TRỞ XUỐNG là luật CHUNG cho mọi khổ màn. Cần luật riêng cho
     màn rộng thì mở một @media MỚI, đừng nối vào khối trên. */

  /* Dòng đếm việc quá hạn từ hôm trước. */
  .hv-tretruoc { display:flex; align-items:center; gap:8px; width:100%; text-align:left;
    font:inherit; font-size:12.5px; color:var(--mo); cursor:pointer;
    background:var(--nen2); border:1px solid var(--vien); border-radius:var(--r-lg); padding:8px 12px; }
  .hv-tretruoc b { color:var(--do); font-variant-numeric:tabular-nums; }
  .hv-tretruoc:hover { border-color:var(--chu); color:var(--chu); }
  .hv-tretruoc i { width:14px; height:14px; flex:none; }
  /* ⛔ Bo góc 8px, không phải 12px: thẻ nhỏ mà bo to thì trông như miếng kẹo.
     ⛔ Đệm 11/13 chứ không 9/11 — thẻ này chứa BA tầng (tên việc · danh sách đầu
        mục · chân thẻ) trong ~83px, đúng cái cô Quỳnh gọi là "bẹp dí". */
  /* ══════════════════════════════════════════════════════════════════════════
     🎠 BĂNG CHUYỀN VIỆC — cô Quỳnh 22/08/2026
     ──────────────────────────────────────────────────────────────────────────
     ⛔ Dựng bằng CUỘN NGANG THẬT + `scroll-snap`, KHÔNG bằng `transform` như phần
        lớn băng chuyền trên mạng. Lý do: cuộn thật thì lăn chuột ngang, vuốt trên
        điện thoại, phím Tab nhảy vào thẻ khuất, và trình đọc màn hình — cả bốn thứ
        chạy sẵn, không phải viết. Bản `transform` phải tự làm lại từng thứ một và
        thường quên ba thứ cuối.
     ⛔ CAO CỐ ĐỊNH. Đây mới là lý do băng chuyền đáng làm ở đây: khối này nằm cùng
        hàng lưới với Ghi chú, trước đây phải CẮT còn 5 việc kẻo đẩy khuất khối bên
        cạnh. Nằm ngang thì 3 việc hay 30 việc cũng cao như nhau — nên nay bày HẾT,
        đúng điều cô Quỳnh đòi 16/08 (*"phải hiện hết"*), mà không tốn thêm một pixel. */
  /* ⛔ `padding:0 32px` — CHỖ ĐỨNG RIÊNG cho hai nút mũi tên, đừng bỏ.
     Bản đầu để nút nổi đè lên dải; chụp ảnh nhìn lại thì nút "‹" nằm chình ình
     giữa tên việc, che mất chữ. Nút điều khiển không được ăn vào chỗ của nội dung
     nó đang điều khiển. */
  .hv-bang { position:relative; padding:0 32px; }
  .hv-ray { display:flex; gap:10px; overflow-x:auto; overflow-y:hidden;
    scroll-snap-type:x mandatory; scroll-behavior:smooth;
    scrollbar-width:none; -ms-overflow-style:none; padding:1px; }
  .hv-ray::-webkit-scrollbar { display:none; }
  /* ⛔ `flex:0 0` — KHÔNG cho co. Để `flex:1` là mọi thẻ tự bóp cho vừa một màn,
     tức là hết trượt, băng chuyền thành cái lưới chật. */
  .hv-ray > .hv-the { flex:0 0 clamp(230px, 88%, 340px); scroll-snap-align:start;
    margin:0; display:flex; flex-direction:column; }
  /* ⛔⛔ CẮT Ở DANH SÁCH ĐẦU MỤC, TUYỆT ĐỐI KHÔNG CẮT CẢ THẺ.
     Bản đầu tôi đặt `max-height` + `overflow-y` lên chính cái thẻ. Chụp ảnh nhìn
     lại thì thấy ngay: việc có 3 đầu mục bị xén mất CHÂN THẺ — mất dòng hạn, mất
     chip người nhận, mất luôn nút "✓ Đã xong việc này". Người dùng nhìn vào tưởng
     việc ấy không có nút hoàn thành.
     Nay chỉ danh sách đầu mục mới cuộn; đầu thẻ và chân thẻ LUÔN thấy được.
     ⛔ Đừng đưa `max-height` trở lại `.hv-the`. */
  .hv-ray > .hv-the > .hv-ct { max-height:104px; overflow-y:auto; }
  /* Chân thẻ bị đẩy xuống đáy để các thẻ trông đều nhau dù ít hay nhiều đầu mục. */
  .hv-ray > .hv-the > .hv-chan { margin-top:auto; }
  /* Lúc đang cầm chuột kéo: tắt trượt mượt và tắt nam châm, không thì thẻ giật về
     chỗ cũ ngay dưới tay. Bỏ tay ra mới bật lại rồi cho nó ăn khớp. */
  .hv-ray.dang-keo { scroll-behavior:auto; scroll-snap-type:none; cursor:grabbing; }
  .hv-ray.dang-keo > .hv-the { cursor:grabbing; }
  .hv-nut { position:absolute; top:calc(50% - 12px); transform:translateY(-50%); z-index:3;
    width:28px; height:28px; padding:0; display:flex; align-items:center; justify-content:center;
    border:1px solid var(--vien); border-radius:50%; background:var(--the); color:var(--chu);
    cursor:pointer; box-shadow:var(--bong-1); opacity:.92; }
  .hv-nut:hover { background:var(--nen2); border-color:var(--xanh); color:var(--muc); opacity:1; }
  .hv-nut svg { width:15px; height:15px; fill:none; stroke:currentColor;
    stroke-width:2.1; stroke-linecap:round; stroke-linejoin:round; }
  .hv-lui { left:0; } .hv-toi { right:0; }
  /* ⛔ Một việc thì GIẤU HẲN nút và chấm, đừng để nút bấm không ra gì. */
  .hv-bang[data-mot] .hv-nut, .hv-bang[data-mot] .hv-cham { display:none; }
  .hv-cham { display:flex; justify-content:center; align-items:center; gap:5px;
    margin-top:9px; flex-wrap:wrap; }
  .hv-cham i { width:6px; height:6px; border-radius:50%; background:var(--vien);
    transition:width .18s, background .18s; }
  .hv-cham i.dang { width:16px; border-radius:var(--r-sm); background:var(--xanh); }
  /* 🔒 Việc của người khác — nói bằng CHỮ, vì ô tích mờ đi thì người ta tưởng app lỗi. */
  .hv-khoa { font-size:11.5px; color:var(--mo); border:1px dashed var(--vien);
    border-radius:var(--r-xl); padding:2px 9px; }
  /* 📱 Màn hẹp: 64px dành cho hai nút là quá nhiều so với bề ngang còn lại.
     Bỏ nút đi — vuốt ngón tay vẫn chạy, hàng chấm vẫn cho biết đang ở thẻ mấy. */
  @media (max-width: 700px) {
    .hv-bang { padding:0; }
    .hv-nut { display:none; }
  }
  @media (prefers-reduced-motion: reduce) { .hv-ray { scroll-behavior:auto; } }
  .hv-the { border:1px solid var(--vien); border-left:3px solid var(--vien); border-radius:var(--r-md);
    padding:11px 13px; background:var(--the); }
  /* ⛔ Dùng biến `--do` chứ đừng gõ #C0504D: cả app có đúng một sắc đỏ, gõ tay là
     đẻ ra sắc thứ hai lệch một chút, nhìn như lỗi in. */
  .hv-the.qua { border-left-color:var(--do); }
  /* ⛔⛔ LUẬT NÀY KHÔNG ĐƯỢC KHOÁ SAU TỔ TIÊN NÀO. Chữ "Quá hạn" được phát vào cả
     `.home-gio-1` (dòng giờ học) LẪN `.hv-the` (thẻ việc). Bản trước chỉ có luật
     `.home-gio-1 .hv-qua`, nên trong thẻ việc nó rơi về chữ đen 14px nét thường —
     TO HƠN cả tên việc và không hề đỏ, tức dấu khẩn cấp nhất lại trông nhạt nhất. */
  .hv-qua { display:inline-block; font-size:11.5px; font-weight:700; color:var(--do);
    border:1px solid var(--do-nen2); background:var(--do-nen); border-radius:var(--r-sm);
    padding:1px 6px; white-space:nowrap; }
  /* ⭐⭐ 21/08/2026 — TRANG CHỦ PHẢI NÓI AI ĐANG ÔM VIỆC.
     ──────────────────────────────────────────────────────────────────────────────
     Cô Quỳnh: *"trang chủ app cũng phải thể hiện rõ công việc nào đã được ai tiếp
     nhận"*. Trước đây Trang chủ hoàn toàn im về chuyện này — muốn biết ai nhận thì
     phải mở công cụ Công việc ra dò. Hai giáo vụ dễ cùng ôm một việc mà không biết.
     Nay mỗi thẻ có nét trái hổ phách + một chip ghi thẳng TÊN người đã nhận.
     ⛔ Cùng ba biến màu `--nhan-*` với công cụ Công việc và Yêu cầu giáo viên.
        Đừng gõ mã màu thẳng vào đây — đổi một chỗ mà quên chỗ kia là app có hai
        sắc hổ phách hơi lệch nhau, nhìn như lỗi in. */
  .hv-the.danhan { border-left-color:var(--nhan-vien); }
  .hv-the.qua.danhan { border-left-color:#C0504D; }   /* gấp thắng, xem luật ở .nv-the */
  .hv-nhan { display:inline-flex; align-items:center; gap:4px; font-size:12px; font-weight:700;
    color:var(--nhan-chu); background:var(--nhan-nen); border:1px solid var(--nhan-vien);
    border-radius:var(--r-xl); padding:1px 9px; }
  .hv-nhan i { width:12px; height:12px; background:var(--nhan-chu); }
  /* Chưa ai nhận thì cũng phải NÓI RA, không để trống — trống thì người đọc không
     biết là "chưa ai nhận" hay là "app quên hiện". Nhưng để chữ mờ, vì đó là trạng
     thái thường, không phải tin tức. */
  .hv-chuanhan { display:inline-flex; align-items:center; gap:4px; font-size:12px;
    color:var(--mo); font-style:italic; }
  .hv-dau { display:flex; align-items:flex-start; flex-wrap:wrap; gap:7px; }
  .hv-ten { flex:1 1 auto; min-width:0; font-size:13.5px; font-weight:700; line-height:1.45;
    overflow-wrap:anywhere; }
  .hv-mo { flex:none; margin-left:auto; cursor:pointer; font-family:inherit;
    border-radius:var(--r-md); }
  .hv-mo:hover { color:var(--xanh-dam); border-color:var(--xanh); }
  /* ⛔ Khe 6px, đừng hạ về 3px. Mỗi dòng đầu mục cao 18,85px; khe 3px là tỉ lệ
     chữ/khoảng-trắng 6:1, các dòng dính thành một mảng chữ đặc — chính là "bẹp dí". */
  .hv-ct { list-style:none; margin:9px 0 0; padding:0; display:flex; flex-direction:column; gap:6px; }
  .hv-ct li { display:flex; align-items:flex-start; gap:7px; font-size:13px; line-height:1.45; }
  .hv-ct li.xong > span { text-decoration:line-through; color:var(--mo); }
  .hv-ct input { flex:none; margin-top:3px; width:15px; height:15px; cursor:pointer; accent-color:var(--xanh); }
  .hv-ct input:disabled { cursor:default; opacity:.5; }
  .hv-ct li > span { min-width:0; overflow-wrap:anywhere; }
  .hv-chan { display:flex; flex-wrap:wrap; align-items:center; gap:6px 12px; margin-top:11px;
    padding-top:9px; border-top:1px solid var(--vien); font-size:12px; }
  .hv-chan .hv-phu { display:inline-flex; align-items:center; gap:4px; color:var(--mo); }
  .hv-chan .hv-phu i { width:13px; height:13px; }
  .hv-tien { font-variant-numeric:tabular-nums; }
  .hv-xong { margin-left:auto; border:1px solid var(--xanh); background:none; color:var(--xanh);
    border-radius:var(--r-md); padding:4px 11px; font:inherit; font-size:12px; font-weight:700; cursor:pointer; }
  .hv-xong:hover { background:var(--xanh); color:#fff; }
  .hv-xong:disabled { opacity:.5; cursor:default; }
  @media (max-width:640px) {
    .hv-mo { margin-left:0; }
    .hv-xong { margin-left:0; flex:1 1 100%; }
  }
  /* 🔀 CÔNG TẮC GẠT CHỈ CÓ ICON, nằm CẠNH tiêu đề — Boss chốt 08/09/2026
     *"2 cái nút việc của tôi và cả cơ sở cần để gọn lại và thay vào bằng icon"*.
     Trước: hai nút CHỮ 180×30 chiếm trọn một hàng riêng cao 39px.

     Hai nút dính liền trong một khung viền, kiểu công tắc gạt của app văn phòng —
     nhìn ra ngay là "hai lựa chọn của cùng một thứ", khác hẳn hai nút rời.
     ⛔ 30px cao chứ không 36px: đây KHÔNG phải nút thao tác mà là công tắc phụ nằm
        trong hàng tiêu đề; ép 36px là hàng tiêu đề phình theo và khối lệch hẳn.
        Sàn 36px của luật chung dành cho nút đứng riêng.
     ⛔ Đừng bỏ `flex:none` ở tiêu đề: tên cơ sở dài làm co nút thành hình bầu dục. */
  .home-tb-dau .home-tb-tieude { flex:1 1 auto; min-width:0;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .home-tb-chon { display:inline-flex; flex:none; margin-left:auto;
    border:1px solid var(--vien); border-radius:8px; overflow:hidden; background:var(--the); }
  .home-tb-nut { width:34px; height:30px; flex:none; border:0; background:none;
    color:var(--mo); cursor:pointer; padding:0;
    display:inline-flex; align-items:center; justify-content:center; }
  .home-tb-nut + .home-tb-nut { border-left:1px solid var(--vien); }
  .home-tb-nut > i { width:17px; height:17px; margin:0; }
  .home-tb-nut:hover { background:var(--nen2); color:var(--chu); }
  .home-tb-nut.chon { background:var(--xanh); color:#fff; }
  .home-tb-nut.chon:hover { background:var(--xanh); color:#fff; }


/* ══════════════════════════════════════════════════════════════════════════════
   📊 CÔNG CỤ THỐNG KÊ — Boss 18/09/2026
   ──────────────────────────────────────────────────────────────────────────────
   Boss chốt bằng nút bấm: lưới BLOCK BO TRÒN ở màn đầu, bấm vào mới mở nhánh ·
   mỗi block có số chính + mũi tên tăng/giảm + đường biểu đồ nhỏ · animation NHIỀU
   (block bay vào lần lượt, chuyển nhánh có hiệu ứng trượt) · điện thoại HAI CỘT.

   Tham khảo kỹ thuật: mẫu "Stats Card" của 21st.dev (kavikatiyar) — lấy đúng ba
   thứ và dịch từ framer-motion sang CSS thuần:
     · block nâng lên khi rê chuột (scale 1.03, dịch lên 5px, nhịp lò xo)
     · số đếm tăng dần (bên JS, easeOutCubic)
     · các phần tử hiện ra LẦN LƯỢT chứ không cùng lúc (stagger)

   ⛔ BO TRÒN ĐẶT THẲNG SỐ Ở ĐÂY, KHÔNG nâng `--r-lg`/`--r-xl`: hai nấc ấy Boss chốt
      02/09 phải là 0px cho panel, có ghi chú cấm đụng trong css/nen.css.
      Boss xin tròn cho BLOCK thống kê, không xin tròn cho cả app.
   ⛔ MỌI MÀU LẤY TỪ BIẾN. Nền tối đổi theo mà không phải viết lại khối này —
      Boss chốt "nền tối có, đổi theo cho đồng bộ".
   ════════════════════════════════════════════════════════════════════════════ */
/* 📐 18/09/2026 — Boss chê *"biểu đồ to và bẹp dí quá"*, *"mấy cái bảng trông
   to và bẹp dí"*. Nguyên nhân đo được: SVG khai `preserveAspectRatio="none"` nên
   trên màn 2238px nó KÉO GIÃN NGANG viewBox 760 ra gấp ~2,9 lần trong khi chiều
   cao giữ nguyên 300px — nét vẽ và chữ bị dẹt theo.
   ⛔ Cách chữa là BÓP NGANG, không phải hạ chiều cao (hạ chiều cao chính là dựng
      lại cái dẹt ấy). 1280px giữ méo dưới 1,2 lần ở cột biểu đồ, và khớp nếp
      `max-width` app đang dùng ở các màn khác (1120–1500px). */
.tk-man { padding: 4px 0 30px; }
/* ⛔ TRẦN 1280px ĐÃ BỎ — Boss chốt 20/09/2026 cho màn Thống kê rộng hết cỡ.
   Khối chú thích ngay trên giải thích vì sao từng có trần ấy: ở màn siêu rộng, cột
   biểu đồ kéo ngang ra mà chiều cao giữ nguyên 300px nên nét vẽ bị dẹt. Cách chữa
   nay KHÔNG phải bóp cả màn lại, mà là để LƯỚI TỰ THÊM CỘT (xem `.tkm-luoi`): thẻ
   nhiều hơn mỗi hàng thì từng thẻ vẫn giữ đúng tỉ lệ cũ, không cái nào bị kéo dẹt.
   ⛔ ĐỪNG TRẢ LẠI `max-width` Ở ĐÂY. Muốn chống dẹt thì chặn bề rộng của MỘT THẺ
      (`.tkm-luoi` đang chặn bằng `minmax`), đừng chặn cả màn — chặn cả màn là bỏ
      đi đúng chỗ trống Boss vừa xin lấy lại. */
.tk-man .tkm-nhom,
.tk-man .tk-nhanh-than { max-width: none; margin-left: 0; margin-right: 0; }
/* Nhánh chi tiết có bảng và biểu đồ lớn thì vẫn cần trần, không thì dòng bảng dài
   quá tầm mắt. Con số 1600 đo theo nếp `max-width` các màn khác (1120–1500).
   📐 20/09/2026 — Boss: *"phần thống kê ở màn hình cho ra giữa nha"*. Dòng ngay
   trên đã gỡ canh giữa (`margin-left/right: 0`) để nhánh danh sách rộng hết cỡ,
   nhưng nhánh chi tiết thì vẫn giữ trần 1600 — nên khối dính sát TRÁI và dồn hết
   chỗ trống sang PHẢI. Đo trên Chrome thật, màn 1905px: hở trái 65 · hở phải 240.
   `margin-inline: auto` chia đôi lại chỗ trống ấy. Khổ hẹp hơn 1674px thì khối
   chưa chạm trần nên không đổi gì.
   ⛔ Phải khai Ở ĐÂY, không phải ở dòng trên: hai luật ngang cơ, luật đứng SAU
      mới thắng. Sửa dòng trên là `.tkm-nhom` cũng bị canh giữa theo, mà nhánh ấy
      Boss đã chốt cho rộng hết cỡ. */
.tk-man .tk-nhanh-than { max-width: 1600px; margin-inline: auto; }

.tkm-dau {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
/* 🎨 Icon cạnh tiêu đề (Boss 18/09). `inline-flex` + `gap` chứ ⛔ đừng dùng
   `margin-right` trên icon: bộ icon chung đã có margin riêng ở vài chỗ, cộng dồn
   vào là lệch. Màu lấy biến thương hiệu, không gõ cứng mã màu. */
.tk-tieu-de .ico {
  width: 19px; height: 19px; flex: none; margin: 0; color: var(--xanh);
}
.tk-tieu-de {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0;
  font-size: 20px;
  /* ⛔ 600 chứ không 800: luật "đừng để lộ ra là máy làm" cấm 800 + IN HOA. */
  font-weight: 600;
  color: var(--chu);
  letter-spacing: -.01em;
}
.tk-mo-ta {
  margin: 3px 0 0;
  font-size: 13px;
  color: var(--mo);
  /* Câu này đổi theo nhánh đang mở — cho nó mềm một nhịp để mắt bám kịp. */
  transition: opacity .18s ease;
}

.tk-nut-ve {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px 7px 10px;
  border: 1px solid var(--vien-ro);
  border-radius: 999px;
  background: var(--the);
  color: var(--chu);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.tk-nut-ve:hover { background: var(--nen2); transform: translateX(-2px); }
.tk-nut-ve svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; }

/* ── LƯỚI BLOCK ───────────────────────────────────────────────────────────── */
.tkm-luoi {
  display: grid;
  /* Tự xuống hàng theo bề ngang thật, không ghim số cột: không phải viết @media
     cho từng khổ màn.
     ⛔ 20/09/2026 — HẠ SÀN THẺ 268px XUỐNG 240px. Boss chốt "xếp nhiều thẻ hơn mỗi
        hàng" sau khi bỏ thanh bên. Đo trên màn 1920: bỏ thanh bên lấy lại 276px,
        hạ sàn thẻ lấy thêm một cột nữa — 4 thẻ một hàng thành 7.
     ⛔ ĐỪNG GHIM CỨNG SỐ CỘT (`repeat(6, 1fr)`). Ghim rồi thì màn 1366 của nhân
        viên ra sáu thẻ bẹp dí, còn màn 2560 của Boss vẫn thừa chỗ. `auto-fill` để
        chính bề ngang thật quyết, mỗi khổ màn ra đúng số thẻ vừa với nó.
     ⛔ 240px là SÀN, không phải cỡ thẻ: số lớn nhất trong thẻ đặt 26px nên dưới
        240px là con số bắt đầu xuống dòng. Hạ nữa là được thêm cột mà mất chữ. */
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}

.tk-block {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 18px 14px;
  border: 1px solid var(--vien);
  /* ⭐ BO TRÒN — thứ Boss gọi là "dạng block ý bo tròn". */
  border-radius: 18px;
  background: var(--the);
  color: var(--chu);
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(16, 24, 32, .04);
  /* Nhịp lò xo mượt hơn ease thường — đúng cảm giác của mẫu framer-motion. */
  transition: transform .26s cubic-bezier(.34, 1.4, .5, 1),
              box-shadow .26s ease, border-color .2s ease;
  /* ⭐ BAY VÀO LẦN LƯỢT. `--i` do JS đặt trên từng block (0,1,2…).
     `backwards` là bắt buộc: thiếu nó thì trong lúc chờ tới lượt, block đứng ở
     trạng thái CUỐI (hiện rõ) rồi mới biến mất để chạy lại — chớp một cái rất xấu. */
  animation: tkBay .5s cubic-bezier(.2, .8, .25, 1) backwards;
  animation-delay: calc(var(--i, 0) * 80ms);
}
@keyframes tkBay {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.tk-block:hover {
  transform: translateY(-5px) scale(1.02);
  box-shadow: 0 10px 26px rgba(16, 24, 32, .10);
  border-color: var(--vien-ro);
}
.tk-block:active { transform: translateY(-1px) scale(.995); }
.tk-block:focus-visible { outline: 2px solid var(--sheet-chon-vien, #00793A); outline-offset: 2px; }

.tk-block-dau { display: flex; align-items: center; gap: 8px; }
.tk-ico { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--mo);
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  transition: stroke .2s ease; }
.tk-block:hover .tk-ico { stroke: var(--chu); }
.tk-block-ten { font-size: 13px; font-weight: 500; color: var(--mo); }
.tkm-mui {
  width: 15px; height: 15px; margin-left: auto; flex: none;
  fill: none; stroke: var(--mo); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .5;
  transition: transform .22s ease, opacity .22s ease;
}
.tk-block:hover .tkm-mui { transform: translateX(3px); opacity: 1; }

.tk-block-so { display: flex; align-items: baseline; gap: 2px; }
.tk-so {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -.02em;
  /* Số đang chạy thì bề rộng chữ số phải bằng nhau, không thì cả dòng giật ngang. */
  font-variant-numeric: tabular-nums;
  color: var(--chu);
}
.tk-so-trong { color: var(--mo); font-weight: 500; }
.tk-dv { font-size: 14px; font-weight: 500; color: var(--mo); }
.tk-chenh {
  margin-left: 8px;
  font-size: 12px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  /* Hiện sau con số một nhịp — mắt đọc số trước, đọc chênh lệch sau. */
  animation: tkHienMuon .45s ease .5s backwards;
}
@keyframes tkHienMuon { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; } }
/* Cùng quy ước màu với khối trang chủ: lên xanh lá · xuống đỏ · ngang xanh nước biển. */
.tk-chenh.len   { color: #1E7C45; }
.tk-chenh.xuong { color: #C0392B; }
.tk-chenh.ngang { color: #2A6FB5; }

.tk-block-mt { font-size: 12px; color: var(--mo); line-height: 1.4; }

/* ── ĐƯỜNG BIỂU ĐỒ TÍ HON ─────────────────────────────────────────────────── */
/* `margin-top: auto` DAY DUONG BIEU DO XUONG DAY BLOCK. Thieu no thi block nao
   khong co duong (chua du 2 diem) se thap hon han cac block cung hang — do that
   tren anh: hang 4 block, hai cai co duong cao 150px, hai cai khong co 146px,
   mep duoi le nhau nhin nhu bang vo. Grid da `stretch` san nen chi can day. */
.tk-spark { position: relative; display: block; height: 30px;
  margin: 2px -18px -14px; margin-top: auto; }
.tk-spark svg { width: 100%; height: 100%; display: block; }
.tk-spark-duong {
  fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  /* ⭐ VẼ DẦN TỪ TRÁI SANG. 260 là đủ dài cho mọi đường trong hộp 100×28 —
     dư thì chỉ tốn một quãng chờ vô hình, thiếu thì đường bị cắt cụt giữa chừng. */
  stroke-dasharray: 260;
  stroke-dashoffset: 260;
  animation: tkVeDuong 1.1s cubic-bezier(.3, .7, .3, 1) .25s forwards;
}
@keyframes tkVeDuong { to { stroke-dashoffset: 0; } }
/* ⛔⛔ NỀN PHẢI CÓ KEYFRAME RIÊNG — vá 18/09/2026, Boss gửi hai ảnh so nhau:
   *"ở các block có hiệu ứng biểu đồ nhưng nó hơi lỗi"*.
   Trước đây dòng này mượn `tkHienMuon`, mà keyframe ấy viết cho chữ:
       @keyframes tkHienMuon { from { opacity: 0; transform: translateY(3px) }
                                 to { opacity: 1 } }
   Hai chỗ hỏng, ĐO THẬT bằng `do-spark-nen.js` (nạp đúng file CSS này, quay từng
   khung hình suốt 2 giây đầu):
     ① `to { opacity: 1 }` kéo vùng nền từ .13 lên **1,000 lúc 1339ms** — tức giữa
        chừng nó TÔ ĐẶC kín màu, xong mới rơi về .13 khi hiệu ứng hết. Đúng mảng
        màu đặc trong ảnh Boss chụp.
     ② `translateY(3px)` trên `<path>` đẩy hình xuống, đo được **tràn 3,2px** khỏi
        mép dưới khung lúc 94ms — đúng chỗ màu trào ra ngoài thẻ trong ảnh.
   Giá trị nghỉ vẫn đúng .13, nên đứng yên mà soi thì KHÔNG thấy gì sai; chỉ ai
   nhìn đúng lúc màn đang mở mới bắt được. Boss bắt được.
   ⇒ Keyframe riêng, chỉ mờ dần TỚI ĐÚNG .13 và không dịch chuyển gì. */
.tk-spark-nen { stroke: none; opacity: .13; animation: tkNenHien .6s ease .7s backwards; }
@keyframes tkNenHien { from { opacity: 0; } to { opacity: .13; } }
.tk-spark.len   .tk-spark-duong { stroke: #1E7C45; } .tk-spark.len   .tk-spark-nen { fill: #1E7C45; }
.tk-spark.xuong .tk-spark-duong { stroke: #C0392B; } .tk-spark.xuong .tk-spark-nen { fill: #C0392B; }
.tk-spark.ngang .tk-spark-duong { stroke: #2A6FB5; } .tk-spark.ngang .tk-spark-nen { fill: #2A6FB5; }
/* Chấm ở điểm cuối — cho biết "số hôm nay đang ở đây". */
.tk-spark-cham {
  position: absolute; width: 6px; height: 6px; border-radius: 50%;
  transform: translate(-50%, -50%);
  background: currentColor;
  animation: tkChamHien .4s ease 1.2s backwards;
}
.tk-spark.len   .tk-spark-cham { color: #1E7C45; }
.tk-spark.xuong .tk-spark-cham { color: #C0392B; }
.tk-spark.ngang .tk-spark-cham { color: #2A6FB5; }
@keyframes tkChamHien { from { opacity: 0; transform: translate(-50%, -50%) scale(0); } }

/* ── NHÁNH ĐANG MỞ ────────────────────────────────────────────────────────── */
.tk-dang-nhanh .tk-nhanh-than {
  /* ⭐ TRƯỢT VÀO TỪ PHẢI khi mở nhánh — Boss chốt "chuyển nhánh có hiệu ứng trượt". */
  animation: tkTruotVao .34s cubic-bezier(.2, .8, .25, 1) backwards;
}
@keyframes tkTruotVao {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}

/* ── ĐIỆN THOẠI — Boss chốt: block xếp HAI CỘT cho đỡ phải cuộn ────────────── */
@media (max-width: 720px) {
  .tkm-luoi { grid-template-columns: 1fr 1fr; gap: 10px; }
  .tk-block { padding: 12px 13px 10px; border-radius: 15px; gap: 6px; }
  .tk-so { font-size: 22px; }
  .tk-dv { font-size: 12px; }
  .tk-block-ten { font-size: 12px; }
  /* Hai cột thì hộp hẹp, câu mô tả dài sẽ đẩy block cao gấp đôi — cắt còn hai dòng.
     ⛔ Cắt bằng `-webkit-line-clamp` chứ đừng `height` cứng: cỡ chữ hệ thống to
        lên là chữ bị xén ngang thân, không ai đọc được. */
  .tk-block-mt {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-size: 11px;
  }
  .tk-spark { height: 24px; margin: 0 -13px -10px; }
  .tk-tieu-de { font-size: 17px; }
}

/* ── Ai tắt hiệu ứng thì tắt hẳn, đừng để chạy nửa vời ────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .tk-block, .tk-chenh, .tk-spark-nen, .tk-spark-cham,
  .tk-dang-nhanh .tk-nhanh-than { animation: none; }
  .tk-spark-duong { animation: none; stroke-dashoffset: 0; }
  .tk-block { transition: none; }
  .tk-block:hover { transform: none; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   THỐNG KÊ — ĐỢT 2 (18/09/2026). Boss gửi 5 mẫu 21st.dev, bảo "làm theo y hệt".

   ⛔ MÀU LẤY TỪ BIẾN CỦA APP, không viết mã màu cứng. Boss chốt bằng nút bấm:
      *"theo bảng màu app"* — mẫu 21st dùng cam/tím/xanh dương, bê nguyên vào là
      màn Thống kê lạc quẻ với 28 màn còn lại.
   ⛔ Phần JS còn đọc `--xanh`, `--cam`, `--o-tot`… bằng `getComputedStyle` để tô
      đường biểu đồ. Đổi tên biến ở `css/nen.css` thì phải đổi cả `tkMau()`
      trong man-hinh/thong-ke.js — hai chỗ, đừng sửa một.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── Nhóm block có tiêu đề (Boss chốt chia nhóm) ───────────────────────────── */
.tkm-nhom { margin-bottom: 22px; }
.tkm-nhom-dau {
  display: flex; align-items: baseline; gap: 10px;
  margin: 0 0 10px; padding-bottom: 7px;
  border-bottom: 1px solid var(--vien);
}
.tkm-nhom-dau h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--chu); }
.tkm-nhom-dau span { font-size: 12px; color: var(--mo); }

.tkm-trong, .tkd-trong {
  padding: 22px 16px; text-align: center;
  font-size: 13px; color: var(--mo);
  background: var(--nen2); border: 1px dashed var(--vien); border-radius: 10px;
}
.tk-cho-coder { line-height: 1.6; }

/* ── Thanh lọc: mốc thời gian · cơ sở · xuất Excel ─────────────────────────── */
.tkm-thanh {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  margin-bottom: 14px;
}
.tkm-loc { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.tkm-loc-nhan { font-size: 12px; color: var(--mo); margin-right: 2px; }
.tkm-loc-nut {
  font: inherit; font-size: 12.5px; line-height: 1;
  padding: 7px 12px; border-radius: 7px;
  border: 1px solid var(--vien); background: var(--the); color: var(--chu);
  cursor: pointer; transition: background .15s ease, border-color .15s ease;
  /* ⛔ Đích bấm tối thiểu 44px trên điện thoại (chuẩn Apple/Material đã đo trong
     skill `do-giao-dien-app-lon`). Padding 7px + chữ 12,5px mới được ~30px nên
     phải nới thêm bằng min-height ở khối @media bên dưới. */
}
.tkm-loc-nut:hover { background: var(--nen2); border-color: var(--vien-ro); }
.tkm-loc-nut.chon {
  background: var(--xanh); border-color: var(--xanh); color: #fff; font-weight: 500;
}
.tk-xuat {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 12.5px; padding: 7px 12px;
  border: 1px solid var(--vien); border-radius: 7px;
  background: var(--the); color: var(--chu); cursor: pointer;
}
.tk-xuat:hover { background: var(--nen2); border-color: var(--vien-ro); }
.tk-xuat svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.tkd-tron-de { display: flex; align-items: center; gap: 8px; }

/* ⛔⛔ MỘT NÚT EXCEL MỖI MÀN — Boss chốt 18/09/2026. Nhánh Báo cáo số còn dựng
   khối `veHomeBaoCaoSo` cũ ở cuối màn, mà khối ấy mang theo nút "Tải Excel"
   (`#bcsTai`) của riêng nó ⇒ đo được HAI nút Excel cùng hiện trên một màn
   (`do-tk-nut-xuat.js`: baocaoso 2 nút — "Xuất Excel | Tải Excel").
   ⇒ Giấu nó KHI VÀ CHỈ KHI nó nằm trong màn Thống kê. Không xoá, không sửa màn
     Báo cáo số gốc: mở thẳng màn ấy thì nút vẫn còn nguyên như cũ.
   ⛔ Đừng "dọn" bằng cách xoá nút trong JS — nút ấy là của màn khác, xoá đi là
     đụng vào phần người khác đang giữ. */
.tk-dang-nhanh #bcsTai { display: none; }


.tk-canh {
  margin: 0 0 12px; padding: 9px 12px; font-size: 12.5px; line-height: 1.5;
  color: var(--nhan-chu, #9A6400);
  background: var(--nhan-nen, #FDF6E7); border: 1px solid var(--nhan-vien, #D9A441);
  border-radius: 8px;
}
.tk-ghi { margin: 8px 0 0; font-size: 12px; color: var(--mo); }

/* ── ① Dải thẻ số — mẫu line-charts-6 ─────────────────────────────────────────
   Mẫu gốc: bốn thẻ ngang bằng nhau, ngăn nhau bằng ĐƯỜNG KẺ DỌC (không phải bốn
   hộp rời có bóng), thẻ đang chọn nền sáng hơn. Giữ đúng hình dạng ấy. */
.tkm-the-dai {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  border: 1px solid var(--vien); border-radius: 12px;
  background: var(--the); overflow: hidden; margin-bottom: 14px;
}
.tkm-the {
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
  padding: 13px 15px; text-align: left;
  font: inherit; color: inherit; cursor: pointer;
  background: transparent; border: 0;
  border-left: 1px solid var(--vien);
  transition: background .16s ease;
}
.tkm-the:first-child { border-left: 0; }
.tkm-the:hover { background: var(--nen2); }
.tkm-the.chon { background: var(--xanh-nhat, #E8F5F5); }
/* Vạch màu đánh dấu thẻ đang chọn — mẫu gốc dùng nền, app này thêm vạch cho rõ
   trên nền sáng. Vẽ bằng inset box-shadow để KHÔNG đẩy chữ dịch đi 2px khi chọn. */
.tkm-the.chon { box-shadow: inset 0 -2px 0 var(--xanh); }
.tkm-the-dau { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tkm-the-ten { font-size: 12.5px; color: var(--mo); }
.tkm-the-so {
  font-size: 24px; font-weight: 600; letter-spacing: -.4px; color: var(--chu);
  font-variant-numeric: tabular-nums;
}
.tkm-the-so i { font-style: normal; font-size: 12px; font-weight: 400; color: var(--mo); }
.tkm-the-cu { font-size: 11.5px; color: var(--mo); }
/* Thẻ đang chờ máy chủ: mờ đi để không ai tưởng số "—" là số thật bằng 0. */
.tkm-the-cho { opacity: .6; }
.tkm-the-cho .tkm-the-cu { font-style: italic; }

/* ── Biểu đồ lớn ───────────────────────────────────────────────────────────── */
.tk-do-lon {
  background: var(--the); border: 1px solid var(--vien); border-radius: 12px;
  padding: 14px 14px 8px; margin-bottom: 14px;
}
.tk-do-de {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 13.5px; font-weight: 500; color: var(--chu); margin-bottom: 10px;
}
.tk-do-de span { font-size: 12px; font-weight: 400; color: var(--mo); }
.tk-nam-doi { margin-left: auto; display: flex; gap: 4px; }

/* ── Khung SVG ──────────────────────────────────────────────────────────────
   ⛔ Boss chốt ĐIỆN THOẠI CUỘN NGANG chứ không rút gọn số mốc. Khung ngoài cuộn,
      SVG giữ `min-width` (đặt nội tuyến theo số mốc) để 12 tháng không dính nhau. */
.tkd-cuon { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
/* 📐 18/09/2026 — CHỮA TẬN GỐC chỗ Boss chê hai lần *"bẹp dí"*, *"mấy con số
   vẫn bị bẹp quá"*.
   Trước: `height: 300px` cứng + `preserveAspectRatio="none"` ⇒ khung rộng bao
   nhiêu thì khổ vẽ 760×300 bị kéo ngang bấy nhiêu, chữ số dẹt theo. Bóp bề ngang
   chỉ làm ĐỠ dẹt chứ không hết: nhánh nào biểu đồ ăn trọn hàng 1280px vẫn còn
   méo 1,64 lần — đúng cái Boss chụp gửi.
   Nay `aspect-ratio` giữ khung LUÔN đúng tỉ lệ khổ vẽ, nên `none` không còn gì
   để kéo. Chiều cao tự tính theo bề rộng: cột hẹp ~740px ⇒ cao ~292px, trọn
   hàng ~920px ⇒ cao ~363px. ⛔ Đừng đặt lại `height` cứng ở đâu nữa. */
.tkd-svg {
  display: block; width: 100%; height: auto;
  aspect-ratio: 760 / 300; touch-action: pan-x;
}
.tkd-ke { stroke: var(--vien); stroke-width: 1; stroke-dasharray: 2 4; }
.tkd-nhan-doc, .tkd-nhan-ngang {
  font-size: 11px; fill: var(--mo); font-variant-numeric: tabular-nums;
}
.tkd-nen { opacity: .12; }
.tkd-duong { fill: none; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
/* ② Đường thứ hai NÉT ĐỨT — đúng mẫu line-charts-5, đây là cách phân biệt năm
   trước với năm nay mà không cần nhìn chú giải. */
.tkd-duong.dut { stroke-dasharray: 6 5; stroke-width: 2; }
.tkd-cham { fill: var(--the); stroke-width: 2; }
.tkd-so-san { font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.tkd-doc { stroke: var(--vien-ro); stroke-width: 1; stroke-dasharray: 3 3; }
.tkd-cot { transition: opacity .15s ease; }
.tkd-svg:hover .tkd-cot { opacity: .92; }

/* ── 🏫 TĂNG TRƯỞNG THEO KHỐI (Boss 20/09/2026) ────────────────
   ⛔ Ba dòng `.tkk-luu` là ĐIỀU KIỆN ĐỬĐỌC ĐÚNG mấy con số dưới, không phải
      chú thích trang trí — đừng thu nhỏ thêm hay giấu sau một dấu ⓘ. */
.tkk-khung { border: 1px solid var(--vien); border-radius: var(--r-xl); padding: 12px 14px; margin: 0 0 14px; }
.tkk-dau { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.tkk-ky { font-size: 12.5px; color: var(--mo); }
.tkk-chon { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.tkk-nut { border: 1px solid var(--vien); background: transparent; color: var(--chu);
  border-radius: var(--r-lg); padding: 3px 10px; font-size: 12.5px; cursor: pointer; }
.tkk-nut.chon { background: var(--xanh); color: #fff; border-color: var(--xanh); }
.tkk-luu { margin: 0 0 10px; padding-left: 18px; font-size: 12.5px; color: var(--mo); }
.tkk-luu li { margin: 2px 0; }
.tkk-bd { margin-bottom: 10px; }
.tkk-bang th, .tkk-bang td { text-align: right; }
.tkk-bang th:first-child, .tkk-bang td:first-child { text-align: left; }
.tkk-ten { font-weight: 700; }
.tkk-nho { font-size: 11px; font-weight: 400; color: var(--mo); }
.tkk-tong td { border-top: 2px solid var(--vien); font-weight: 700; }
.tkk-len { color: var(--o-tot, #1E7C45); font-weight: 700; }
.tkk-xuong { color: var(--do, #C0392B); font-weight: 700; }
.tkk-moi { color: var(--cam, #F5821F); font-weight: 700; }
.tkk-trong { color: var(--mo); }
.tkk-chua { font-size: 13px; color: var(--mo); margin: 0; }
@media (max-width: 640px) {
  .tkk-chon { margin-left: 0; }
  .tkk-khung { padding: 10px; }
}
.tkd-cg-dai { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-bottom: 8px; }
.tkd-cg { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--chu); }
.tkd-cg i { width: 14px; height: 3px; border-radius: 2px; flex: 0 0 auto; }
/* Chú giải của đường nét đứt cũng phải đứt, không thì hai ô màu trông y hệt nhau. */
.tkd-cg i.dut {
  background: none !important;
  border-top: 3px dashed currentColor; height: 0; opacity: .85;
}

/* ── ③ Biểu đồ tròn ────────────────────────────────────────────────────────── */
/* 📐 Hàng chứa biểu đồ lớn + biểu đồ tròn. Cột trái rộng hơn vì đường/cột cần
   bề ngang để đọc mốc thời gian; cột phải chỉ có vòng tròn và chú giải.
   `minmax(0, …)` là bắt buộc: thiếu nó thì cột lưới lấy sàn `auto` = bề rộng nội
   dung, bảng hay SVG min-width sẽ đẩy cột phình ra ngoài màn. */
.tk-hang-do {
  display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: 14px; align-items: stretch; margin-bottom: 14px;
}
/* Boss chốt 18/09: *"tất cả thống kê đều có 2 biểu đồ cạnh nhau là đẹp"*. Mọi
   nhánh nay đều có biểu đồ tròn bên cạnh, nên biểu đồ đường luôn nằm ở cột
   1,55fr — một bề rộng duy nhất, không còn chỗ lúc to lúc bé.
   `.mot` giữ lại làm ĐƯỜNG LUI: nhánh nào vì lý do gì đó không dựng được biểu
   đồ tròn thì vẫn kẹp 920px rồi căn giữa, chứ để trọn 1280px thì đúng tỉ lệ nó
   cao 505px, chiếm quá nửa màn và đẩy bảng khỏi tầm nhìn. */
.tk-hang-do.mot { grid-template-columns: minmax(0, 1fr); }
.tk-hang-do.mot > .tk-do-lon { max-width: 920px; margin-left: auto; margin-right: auto; }
.tk-hang-do > .tk-do-lon, .tk-hang-do > .tk-phu { margin-bottom: 0; }
.tk-phu { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin-bottom: 14px; }
.tkd-tron {
  background: var(--the); border: 1px solid var(--vien); border-radius: 12px; padding: 14px;
}
.tkd-tron-de { margin: 0 0 10px; font-size: 13.5px; font-weight: 500; color: var(--chu); }
.tkd-tron-ve { position: relative; width: 140px; margin: 0 auto 12px; }
.tkd-tron-ve svg { display: block; width: 140px; height: 140px; }
.tkd-mieng { transition: opacity .15s ease; }
.tkd-tron-ve:hover .tkd-mieng { opacity: .9; }
/* Số tổng nằm GIỮA vòng — mẫu ③. Dùng lớp phủ tuyệt đối chứ không <text> trong
   SVG: chữ trong SVG không thừa hưởng được cỡ chữ hệ thống của người dùng. */
.tkd-tron-giua {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px; pointer-events: none;
}
/* Kẹp bề rộng nhãn trong lỗ donut. Nhãn dài hơn thì xuống dòng chứ ⛔ đừng để
   nó tràn ra đè lên vòng — nới lỗ ở JS rồi vẫn phải chặn ở đây, vì tên nhãn do
   từng nhánh tự đặt và sớm muộn có cái dài hơn. */
.tkd-tron-giua span {
  font-size: 10.5px; color: var(--mo); max-width: 76px;
  text-align: center; line-height: 1.25;
}
.tkd-tron-giua b { font-size: 22px; font-weight: 600; color: var(--chu); font-variant-numeric: tabular-nums; }
.tkd-ct { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--vien); }
.tkd-ct li {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 2px; font-size: 12.5px; border-bottom: 1px solid var(--vien);
}
.tkd-ct li:last-child { border-bottom: 0; }
.tkd-ct i { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.tkd-ct-ten { flex: 1 1 auto; color: var(--chu); overflow-wrap: anywhere; }
.tkd-ct-so { color: var(--chu); font-variant-numeric: tabular-nums; font-weight: 600; }

/* ── ⑤ Bảng kiểu financial-markets-table ──────────────────────────────────── */
.tkm-bang-de { margin: 0 0 8px; font-size: 13.5px; font-weight: 500; color: var(--chu); }
.tkb-boc {
  background: var(--the); border: 1px solid var(--vien); border-radius: 12px;
  overflow: hidden; margin-bottom: 14px;
}
/* ⛔ Bảng rộng thì CUỘN TRONG KHUNG của nó, không để tràn ra làm cả trang cuộn
   ngang — luật bố cục chung của app. */
.tkb-boc > table { width: 100%; }
.tkb { border-collapse: collapse; font-size: 13px; }
.tkb thead th {
  /* Đầu bảng chữ HOA nhỏ màu mờ — đúng mẫu ⑤. Cỡ 11px + giãn chữ, KHÔNG in đậm
     hơn 500: Boss đã chê "lộ ra là máy làm" đúng ở chỗ chữ hoa + rất đậm. */
  text-transform: uppercase; letter-spacing: .04em;
  font-size: 11px; font-weight: 500; color: var(--mo);
  text-align: left; padding: 10px 12px; white-space: nowrap;
  border-bottom: 1px solid var(--vien); background: var(--nen2);
}
.tkb thead th.so, .tkb td.so { text-align: right; }
.tkb td {
  padding: 9px 12px; border-bottom: 1px solid var(--vien);
  color: var(--chu); vertical-align: middle;
  font-variant-numeric: tabular-nums;
}
.tkb tbody tr:last-child td { border-bottom: 0; }
.tkb tbody tr:hover td { background: var(--nen2); }
/* Tên chính + dòng phụ nhỏ bên dưới — đúng mẫu ⑤ */
.tkb-ten { min-width: 130px; }
.tkb-chinh { display: block; font-weight: 500; }
.tkb-phu { display: block; font-size: 11px; color: var(--mo); margin-top: 1px; }
/* Huy hiệu % nền xanh/đỏ — mẫu ⑤ */
.tkb-huy {
  display: inline-block; padding: 2px 7px; border-radius: 999px; font-size: 11.5px;
}
.tkb-huy.len   { color: var(--o-tot); background: rgba(30,124,69,.10); }
.tkb-huy.xuong { color: var(--do);    background: rgba(192,57,43,.10); }
.tkb-spark { width: 92px; }
.tkb-spark .tk-spark { position: relative; display: block; height: 26px; width: 88px; }
.tkb-chua { color: var(--mo); }
.tkb-them {
  display: block; width: 100%; padding: 10px; font: inherit; font-size: 12.5px;
  color: var(--xanh); background: var(--nen2); border: 0;
  border-top: 1px solid var(--vien); cursor: pointer;
}
.tkb-them:hover { background: var(--xanh-nhat, #E8F5F5); }

/* ── Hộp chi tiết khi rê chuột ──────────────────────────────────────────────
   ⛔ `position: fixed` + toạ độ theo `clientX/clientY`: hộp nằm ngoài mọi khung
      cuộn nên không bị khung nào cắt mất. Đặt trong `.tkd-cuon` là hộp bị xén
      ngay khi trỏ tới mốc cuối. */
.tk-tip {
  position: fixed; z-index: 90; pointer-events: none;
  min-width: 132px; padding: 8px 10px;
  background: var(--the); color: var(--chu);
  border: 1px solid var(--vien-ro); border-radius: 8px;
  box-shadow: 0 6px 18px rgba(16,24,32,.12);
  font-size: 12.5px; line-height: 1.5;
}
.tk-tip b { display: block; margin-bottom: 4px; font-weight: 600; }
.tk-tip span { display: flex; align-items: center; gap: 7px; }
.tk-tip span i { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.tk-tip span b { margin: 0 0 0 auto; font-weight: 600; font-variant-numeric: tabular-nums; }

.tk-duoi { margin-top: 6px; }

/* ── ĐIỆN THOẠI ───────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  /* Dải thẻ số: mẫu gốc xếp ngang bốn thẻ, màn 390px thì mỗi thẻ còn 90px —
     chữ "Số buổi đã dạy" rơi dọc từng ký tự. Xếp HAI CỘT, cùng kiểu Boss đã chốt
     cho lưới block. */
  .tkm-the-dai { grid-auto-flow: row; grid-template-columns: 1fr 1fr; }
  .tkm-the { border-left: 0; border-top: 1px solid var(--vien); padding: 11px 12px; }
  .tkm-the:nth-child(odd) { border-right: 1px solid var(--vien); }
  .tkm-the:first-child, .tkm-the:nth-child(2) { border-top: 0; }
  .tkm-the-so { font-size: 20px; }
  /* Đích bấm ≥44px cho mọi nút lọc — chuẩn Apple 44 / Material 48. */
  .tkm-loc-nut, .tk-xuat { min-height: 38px; padding: 9px 12px; }
  .tkm-thanh { gap: 8px 10px; }
  .tk-xuat { margin-left: 0; }
  /* ⛔ Đặt lại `height` ở đây là làm hỏng `aspect-ratio` phía trên — luật này
     viết sau nên nó THẮNG, và biểu đồ trên điện thoại dẹt trở lại. Chỉ hạ trần
     bề ngang, chiều cao cứ để tỉ lệ tự lo. */
  .tk-hang-do.mot > .tk-do-lon,
  .tk-man .tk-nhanh-than > .tk-do-lon { max-width: none; }
  .tk-do-lon { padding: 12px 10px 6px; }
  .tkm-nhom-dau { flex-direction: column; gap: 1px; align-items: flex-start; }
  .tkb { font-size: 12.5px; }
  .tkb thead th, .tkb td { padding: 8px 9px; }
  .tkb-spark { display: none; }   /* màn hẹp: bỏ cột đường cho ba cột số đủ chỗ */
  .tk-phu { grid-template-columns: 1fr; }
  /* Điện thoại không đủ chỗ cho hai cột — xếp dọc lại, và bỏ trần bề ngang vì
     màn đã hẹp sẵn (để trần ở đây thì thừa một lớp căn giữa vô nghĩa). */
  /* ⛔ `minmax(0, 1fr)` chứ KHÔNG phải `1fr` trần. Đo được 18/09: viết `1fr` thì
     cột lấy sàn `auto` = bề rộng nội dung, mà SVG biểu đồ có `min-width` đặt nội
     tuyến theo số mốc — cột phình lên 442px trên màn 390px và đẩy tràn cả trang
     64px. Tôi đã ghi đúng lời nhắc này ở khối trên rồi vẫn quên áp xuống đây. */
  .tk-hang-do { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .tk-man .tkm-nhom, .tk-man .tk-nhanh-than { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .tkm-the, .tkd-cot, .tkd-mieng { transition: none; }
}

/* ⛔⛔ NÂNG BẬC CHO BẢNG — vá 18/09/2026, đo bằng CSSOM chứ không đoán.
   App TỰ KHOÁC lớp `sheet-moi` cho bảng lúc chạy (xem `sheetGan` trong js/tinh-nang.js),
   nên bảng của màn này cũng ăn luật:
       `.sheet-moi tbody tr.sheet-hang td > span` (0,3,3) -> display: inline-flex
   Luật ấy nặng hơn `.tkb-chinh` (0,1,0) nên `display:block` của tôi THUA, và tên lớp
   với dòng phụ bị kéo vào cùng một hàng: "Toàn trung tâmgộp mọi cơ sở".
   ⛔ Không grep ra được chuyện này — `sheet-moi` gắn lúc chạy, đọc file không thấy.
      Phải hỏi `el.matches(...)` trên CSSOM. Đây là lần thứ 10 cùng một ổ.
   ⛔ Chuỗi chọn dưới đây cố ý dài để đủ nặng (0,5,2). Rút gọn cho "sạch" là hỏng lại. */
.tk-man .tkb-boc .tkb tbody td > .tkb-chinh { display: block; }
.tk-man .tkb-boc .tkb tbody td > .tkb-phu   { display: block; }
.tk-man .tkb-boc .tkb tbody td > .tkb-huy   { display: inline-block; }
.tk-man .tkb-boc .tkb tbody td > .tk-spark  { display: block; position: relative; }

/* ══════════════════════════════════════════════════════════════════════════════
   🧱 LƯỚI BENTO TRANG CHỦ — Boss chốt 18/09/2026, dựng theo mẫu 21st.dev
   `@manuarora700/components/bento-grid` (Boss gửi thẳng link).

   Boss chốt qua 10 câu hỏi:
     ① ô TO NHẤT là "Tin hôm nay"        ⑥ chiều cao CỐ ĐỊNH, dài thì cuộn trong ô
     ② thêm 3 ô: Lớp đến giờ · Việc      ⑦ điện thoại 1 cột, thứ tự Tin → Việc →
        của tôi · Đang online                Lớp → Thông báo → Ghi chú → Online
     ③ hiệu ứng rê: áp y hệt mẫu         ⑧ bóng + bo góc theo mẫu, MÀU theo app
     ④ ô Ghi chú: tắt hiệu ứng khi gõ    ⑨ không có quyền → ô mờ, ghi rõ
     ⑤ mở trang: các ô hiện lần lượt     ⑩ ô nào có chỗ để đi mới có nút "Xem →"

   ⛔⛔ KHÁC MẪU ĐÚNG MỘT CHỖ, CÓ LÝ DO: mẫu đặt cụm chữ Ở ĐÁY ô rồi cho nó trượt
      lên khi rê chuột. Mẫu ấy là trang giới thiệu — mỗi ô chỉ có một dòng mô tả.
      Ô ở đây chứa DANH SÁCH VIỆC, mà đầu đề nằm dưới danh sách thì người dùng
      phải đọc hết mới biết mình đang xem mục gì. Nên: đầu đề ở TRÊN, còn cú
      "nhường chỗ cho nút" thì giữ nguyên — phần thân nhích lên, biểu tượng thu
      nhỏ, nút "Xem →" trượt lên từ đáy, nền sạm nhẹ. Cùng nhịp 300ms của mẫu.
   ⛔ MÀU LẤY TỪ BIẾN CỦA APP (`--the`, `--vien`, `--chu`, `--mo`), KHÔNG chép màu
      trắng/xám của mẫu — nếu không thì nền tối vỡ hết. Bóng thì chép đúng ba lớp
      của mẫu vì chính nó tạo ra dáng bento.
   ══════════════════════════════════════════════════════════════════════════════ */
.home-bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* ⛔ Hàng cao CỐ ĐỊNH — Boss chọn "cố định như mẫu, dài thì cuộn trong ô". Mẫu
     dùng 22rem = 352px; giữ nguyên con số ấy. Ô nào nhiều dòng thì `.hb-noi` tự
     cuộn bên trong, KHÔNG kéo cả trang dài ra. */
  grid-auto-rows: 352px;
  gap: 16px;
}
.hb-o {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 12px;
  background: var(--the);
  /* Bóng ba lớp của mẫu: một nét viền mảnh + một bóng gần + một bóng xa rất nhạt.
     ⛔ Đừng rút còn một lớp cho "gọn" — chính ba lớp này làm thẻ nổi lên mà không
        cần viền đậm, và đó là thứ tạo dáng bento. */
  box-shadow: 0 0 0 1px rgba(0,0,0,.03), 0 2px 4px rgba(0,0,0,.05), 0 12px 24px rgba(0,0,0,.05);
  transform: translateZ(0);          /* nhờ máy vẽ, cho hiệu ứng mượt */
  /* ⑤ Hiện lần lượt: mỗi ô chờ thêm 60ms so với ô trước (`--i` do JS đặt). */
  animation: hbVao .34s cubic-bezier(.22,.7,.3,1) backwards;
  animation-delay: calc(var(--i, 0) * 60ms);
}
@keyframes hbVao { from { opacity: 0; transform: translateY(10px); } }
body.toi .hb-o {
  /* Nền tối: mẫu dùng viền trắng mờ + bóng hắt từ trên xuống trong lòng thẻ. */
  box-shadow: 0 0 0 1px rgba(255,255,255,.10), 0 -20px 80px -20px rgba(255,255,255,.12) inset;
}

/* ── Đầu đề ô ─────────────────────────────────────────────────────────────── */
.hb-dau {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 16px 10px;
  font-weight: 600; font-size: 14px; color: var(--chu);
  /* ⑪ 18/09/2026 — Boss chụp được cảnh chữ ĐÈ NHAU khi rê chuột:
     *"lúc lia chuột vào thì đang bị xung đột trèn đè chữ nhau nên là khi di vào
      thì cái tên block ẩn đi cho tôi"*.
     Gốc: thân ô nhích lên 34px để nhường chỗ cho nút, nhưng tên ô thì đứng yên —
     nên dòng đầu của danh sách trèo lên đúng chỗ tên. `.hb-o` có `overflow:hidden`
     nên bị cắt ở mép Ô, không cắt ở mép tên. ⇒ Tên mờ đi và đi lên cùng nhịp. */
  /* ⛔ TÊN PHẢI TAN TRƯỚC, THÂN MỚI ĐƯỢC TRƯỢT LÊN. Cho hai bên cùng chạy 300ms
     thì suốt quãng giữa vẫn trông thấy hai lớp chữ chồng nhau — vẫn đúng cái Boss
     chê, chỉ là mờ hơn. Nên: tên tan trong 120ms, thân chờ 110ms rồi mới đi
     (xem `.hb-noi`). Số 110 phải LỚN HƠN 120 × 0,9 — sửa một bên thì sửa cả hai. */
  transition: opacity .12s ease, transform .12s ease;
}
/* ⛔⛔ HAI BẪY CỦA BỘ ICON `ic-*`, cả hai đều HỎNG LẶNG LẼ:
   ① Luật chung là `i[class^="ic-"]` — khớp theo ĐẦU chuỗi class. Viết
      `class="hb-ico ic-but"` là KHÔNG khớp và icon biến mất sạch, không lỗi nào
      nổ. Phải viết `class="ic-but hb-ico"`, tên `ic-*` đứng TRƯỚC.
   ② Luật chung ấy có độ đặc hiệu (0,1,1) — `.hb-ico` trơn chỉ (0,1,0) nên THUA,
      khai width/height ở đó không ăn. Phải `.hb-dau i.hb-ico` = (0,2,1).
   (Cùng họ với bẫy `ccIcon` khoá sai: `ccIcon("note")` không có khoá "note" nên
    từ trước tới nay nó vẫn lặng lẽ vẽ ra một HÌNH TRÒN ở ô Ghi chú.) */
.hb-dau i.hb-ico {
  width: 20px; height: 20px; flex: none; margin-right: 0; color: var(--mo);
  /* Mẫu cho biểu tượng thu nhỏ còn 75% khi rê chuột, gốc neo bên trái. */
  transform-origin: left center;
  transition: transform .3s ease-in-out, color .3s ease;
}
.hb-dau .phu { font-weight: 400; font-size: 12px; color: var(--mo); }

/* ── Thân ô: phần cuộn được ───────────────────────────────────────────────── */
.hb-noi {
  flex: 1 1 auto; min-height: 0;
  overflow: auto; overscroll-behavior: contain;
  padding: 0 16px 14px;
  transition: transform .3s ease .11s;   /* chờ tên tan hết — xem `.hb-dau` */
}
.hb-trong {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 9px;
  height: 100%; margin: 0; padding: 10px;
  font-size: 13px; color: var(--mo); text-align: center;
}
/* Biểu tượng mờ phía trên câu chữ — nói cho người dùng biết ô này VỐN chứa gì.
   ⛔ Mờ vừa phải (.34): đậm hơn là nó tranh mất chỗ của câu chữ, nhạt hơn nữa thì
      trên nền tối coi như không có. */
.hb-trong-ico {
  width: 30px; height: 30px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .34;
}

/* ── Nút "Xem →" trượt lên từ đáy ─────────────────────────────────────────── */
/* ⑩ Chỉ ô nào có chỗ để đi mới có nút này — ô Ghi chú và Đang online không có.
   Bày một cái nút bấm vào không đi đâu là đúng thứ Boss đã chê một lần. */
.hb-cta {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center;
  padding: 10px 14px;
  background: linear-gradient(180deg, transparent, var(--the) 46%);
  transform: translateY(40px); opacity: 0;
  transition: transform .3s ease, opacity .3s ease;
  pointer-events: none;
}
.hb-cta button {
  pointer-events: auto;
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 13px; font-weight: 500;
  padding: 6px 10px; border: 0; border-radius: 7px;
  background: transparent; color: var(--chu); cursor: pointer;
}
.hb-cta button:hover { background: var(--nen2); }
.hb-cta svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; }

/* ── Lớp phủ sạm nhẹ khi rê chuột (mẫu: bg-black/[.03]) ───────────────────── */
.hb-phu {
  position: absolute; inset: 0; pointer-events: none;
  background: transparent; transition: background .3s ease;
}

/* ── Cú rê chuột ──────────────────────────────────────────────────────────── */
/* ⛔ `.hb-co-cta` mới được nhích thân lên: ô không có nút thì nhích lên là để hở
   một dải trống ở đáy, chẳng nhường chỗ cho ai. */
@media (hover: hover) {
  .hb-o.hb-co-cta:hover .hb-dau { opacity: 0; transform: translateY(-10px); }
  .hb-o.hb-co-cta:hover .hb-noi { transform: translateY(-34px); }
  .hb-o:hover .hb-dau i.hb-ico { transform: scale(.75); color: var(--chu); }
  .hb-o.hb-co-cta:hover .hb-cta { transform: translateY(0); opacity: 1; }
  .hb-o:hover .hb-phu { background: rgba(0,0,0,.03); }
  body.toi .hb-o:hover .hb-phu { background: rgba(255,255,255,.04); }
}
/* ④ Ô ghi chú: đang gõ thì tắt hẳn hiệu ứng — Boss chọn "có hiệu ứng, nhưng tắt
   khi đang gõ". `hb-dang-go` do JS gắn lúc ô ghi chú nhận con trỏ. */
.hb-o.hb-dang-go .hb-dau { opacity: 1 !important; transform: none !important; }
.hb-o.hb-dang-go .hb-noi { transform: none !important; }
.hb-o.hb-dang-go .hb-dau i.hb-ico { transform: none !important; }
.hb-o.hb-dang-go .hb-phu { background: transparent !important; }

/* ⑨ Không có quyền: ô vẫn hiện nhưng mờ và nói thẳng lý do — Boss chọn kiểu này
   thay vì ẩn hẳn.
   ⛔⛔ Ô MỜ CHỈ ĐƯỢC GHI TÊN CHỨC NĂNG, TUYỆT ĐỐI KHÔNG TẢI VÀ KHÔNG BÀY SỐ LIỆU.
      Người không có quyền nay nhìn thấy app có mục gì — đó là điều Boss đồng ý;
      nhưng thấy TÊN MỤC khác hẳn thấy NỘI DUNG. `hienHome` không gọi hàm tải của
      ô bị khoá, nên trong ô không có gì để rò. Đừng "cho tiện" mà vẽ sẵn rồi phủ
      mờ lên trên — phủ mờ là che bằng CSS, mở F12 ra là đọc được hết. */
.hb-o.hb-khoa { opacity: .55; }
.hb-o.hb-khoa .hb-noi { display: flex; align-items: center; justify-content: center; }
.hb-khoa-chu {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  font-size: 13px; color: var(--mo); text-align: center;
}
.hb-khoa-chu i { width: 22px; height: 22px; }

/* ── Chỗ đứng từng ô trên máy tính ────────────────────────────────────────── */
/* ⛔ Thứ tự trong HTML đã là thứ tự Boss chốt cho ĐIỆN THOẠI (Tin → Việc → Lớp →
   Thông báo → Ghi chú → Online), nên màn hẹp không cần luật gì thêm — chỉ việc
   hạ xuống một cột. Chỗ đứng kiểu bento chỉ áp cho màn rộng. */
/* ⛔⛔ KHÔNG GHIM `grid-row` CHO TỪNG Ô — sửa 18/09/2026 khi tách "Tin hôm nay".
   Bản đầu ghim cứng từng ô vào đúng một hàng. Ghim như thế thì mỗi lần thêm hoặc
   bớt một ô (mà nay có tới mười ô, ẩn/hiện theo bề rộng và theo quyền) là phải đi
   sửa lại cả bảng toạ độ; quên một dòng là lưới thủng một lỗ. Nay để lưới TỰ XẾP
   theo đúng thứ tự trong HTML, chỉ khai bề rộng cho hai ô cần rộng hơn một cột.
   Thứ tự HTML trên máy tính (bốn ô đầu ẩn/hiện theo màn):
     hàng 1: Việc của tôi · Lớp đến giờ · Phụ đạo
     hàng 2: Lịch thi · Dự giờ · Yêu cầu GV
     hàng 3: Thông báo công việc (2 cột) · Ghi chú
     hàng 4: Đang online (cả bề ngang)
   ⇒ Không ô nào bỏ trống, và thêm ô mới chỉ việc chèn đúng chỗ trong HTML. */
@media (min-width: 1000px) {
  .hb-chi-dt { display: none; }              /* băng vuốt: chỉ dùng trên điện thoại */
  .hb-tb     { grid-column: span 2; }
  .hb-online { grid-column: 1 / -1; }
}
/* ⛔ Ngưỡng 1000px này phải KHỚP `matchMedia("(min-width:1000px)")` trong
   `veHomeTinMuc`. Lệch nhau là có một dải bề rộng mà tin không hiện ở đâu cả:
   băng đã bị giấu, còn mục thì chưa được nhả sang ô riêng. */
@media (max-width: 999.98px) {
  .hb-chi-mt { display: none; }              /* năm ô mục: chỉ dùng trên máy tính */
}
/* Màn vừa (máy tính bảng): 2 cột, ô Tin vẫn to nhất. */
@media (min-width: 700px) and (max-width: 999.98px) {
  .home-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hb-tin, .hb-tb, .hb-online { grid-column: 1 / -1; }
}
@media (max-width: 699.98px) {
  .home-bento { grid-template-columns: 1fr; grid-auto-rows: 268px; gap: 12px; }
  /* ⛔ Trên điện thoại KHÔNG có con trỏ nên cú rê chuột không bao giờ chạy — nút
     "Xem →" phải hiện sẵn, không thì tính năng chết trên đúng thiết bị hay dùng
     nhất. Đây là bài học đã ghi ở thanh định dạng bảng (`sheetGanHienThanh`). */
  .hb-cta { position: static; transform: none; opacity: 1;
    background: none; padding: 0 16px 12px; }
  .hb-noi { padding-bottom: 8px; }
  /* Ô ghi chú cần chỗ viết, cho cao hơn các ô khác. */
  .hb-note { grid-row: auto; min-height: 268px; }
}
/* Ai tắt hiệu ứng trong hệ điều hành thì tắt hết, kể cả lượt hiện lần lượt. */
@media (prefers-reduced-motion: reduce) {
  .hb-o, .hb-noi, .hb-dau i.hb-ico, .hb-cta, .hb-phu { animation: none !important; transition: none !important; }
}

/* ⛔⛔ TRẢ `.home-boc` VỀ MỘT CỘT — vá 18/09/2026, bắt buộc đi kèm lưới bento.
   Luật cũ ở `@media (min-width:1100px)` phía trên cho `.home-boc` thành lưới
   `minmax(0,1fr) 340px` và ghim `grid-row` cho từng khối con. Nay `.home-boc`
   chỉ còn HAI con: thanh avatar và `.home-bento`. Để nguyên luật cũ thì cả lưới
   bento bị nhét vào CỘT TRÁI rộng 1fr, chừa một dải 340px trắng bên phải —
   đúng cái dải trắng cô Quỳnh đã chê ngày 21/08/2026.
   ⛔ Đặt SAU luật cũ trong file để thắng bằng thứ tự (hai bên ngang cơ đặc hiệu).
      Dời khối này lên trước là dải trắng mọc lại mà không lỗi nào báo.
   ⛔ Không xoá luật cũ: mấy dòng `.home-boc > .home-tb-rong`, `.home-cot-phai`,
      `.home-cot-trai` trong ấy nay không khớp phần tử nào nữa nên vô hại, nhưng
      chúng còn ghi lại vì sao từng phải xếp như thế — xoá là mất cả lời dặn. */
@media (min-width: 1100px) {
  /* ⛔⛔ `align-items: stretch` LÀ BẮT BUỘC, ĐỪNG BỎ. Luật cũ ngay phía trên khai
     `.home-boc { ... align-items: start }` cho kiểu lưới hai cột. Đổi `display`
     sang flex mà KHÔNG ghi đè dòng ấy thì nó vẫn còn hiệu lực, và với
     `flex-direction: column` nó có nghĩa là "con co lại vừa nội dung" —
     ĐO THẬT 18/09/2026 trên màn 2000px: `.home-boc` rộng 1944px nhưng
     `.home-bento` bên trong chỉ 1495px, HỞ 449px trắng chạy dọc bên phải.
     Đúng cái Boss chụp ảnh báo: *"đang bị hở nguyên 1 mảng bên phải"*.
     Lưới grid vốn tự chiếm hết bề ngang cha, nên rất dễ tưởng lỗi nằm trong lưới
     mà đi sửa `grid-template-columns` — không phải, thủ phạm nằm ở THẺ CHA. */
  .home-boc { display: flex; flex-direction: column; gap: 18px; align-items: stretch; }
}

/* ⛔⛔ BỎ VỎ THẺ LỒNG TRONG THẺ, VÀ BỎ TÊN TRÙNG — vá 18/09/2026.
   Mấy hàm vẽ cũ (`veHomeThongBao`, `veHomeOnline`) tự dựng lấy một cái thẻ
   `.home-khoi` CÓ VIỀN và một dòng tiêu đề `.home-khoi-dau` mang đúng cái tên mà
   ô bento đã ghi ở `.hb-dau`. Để nguyên thì Boss thấy "Thông báo công việc" hai
   lần chồng nhau trong một ô, và một cái khung bo góc nằm lọt trong khung bo góc
   khác — chính là cảnh trong ảnh Boss gửi.
   ⛔ CHỈ giấu CHỮ và BIỂU TƯỢNG của dòng tiêu đề ấy, ĐỪNG giấu cả dòng: hai nút
      "Chỉ việc của tôi / Cả cơ sở" nằm ngay trong đó, giấu cả dòng là mất nút mà
      không lỗi nào nổ.
   ⛔ Sửa ở CSS chứ đừng đi sửa `veHomeThongBao`: hàm ấy còn dùng cho chỗ khác,
      và nó là phần người khác đang giữ. */
.hb-noi > .home-khoi {
  border: 0; border-radius: 0; background: none; box-shadow: none; overflow: visible;
}
.hb-noi .home-khoi-dau {
  padding: 0 0 8px; background: none; border: 0; min-height: 0;
}
.hb-noi .home-khoi-dau > .ico,
.hb-noi .home-tb-tieude { display: none; }
/* Dòng tiêu đề nào KHÔNG còn nút nào bên trong thì giấu hẳn, khỏi chừa dải trống. */
.hb-noi .home-khoi-dau:not(:has(button)) { display: none; }

/* Danh sách việc trong ô "Việc của tôi" — cùng khuôn với các dòng tin khác. */
.hb-ds { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.hb-dong {
  display: flex; flex-direction: column; gap: 2px;
  padding: 7px 8px; border-radius: 7px; cursor: pointer;
  border-left: 2px solid transparent;
}
.hb-dong:hover { background: var(--nen2); }
.hb-dong .ten { font-size: 13px; font-weight: 500; color: var(--chu); }
.hb-dong .phu { font-size: 11.5px; color: var(--mo); }
.hb-dong.qua { border-left-color: var(--do); }
.hb-dong .do { color: var(--do); }

/* ══════════════════════════════════════════════════════════════════════════════
   🧱 LƯỚI BENTO — SẮP LẠI LẦN 2, Boss chốt 18/09/2026 sau khi xem bản đầu
   ──────────────────────────────────────────────────────────────────────────────
   Boss trên màn 2469px: *"cho các block nó nhỏ lại đi, chứ ở màn hình to như tôi
   thì nhìn nó bị bẹp dí"*. Đo ra đúng vậy: 3 cột trên màn ấy cho mỗi ô 810×352,
   tức tỉ lệ 2,3 : 1 — dẹt như một thanh ngang, không còn ra dáng bento.
   Boss chọn: **màn rất rộng thì chia 4 cột** (ô còn ~600×340, gần vuông như ảnh
   mẫu). ⛔ Đừng "chữa" bằng cách hạ chiều cao — ô vẫn rộng nguyên nên tỉ lệ càng
   dẹt hơn; và đừng chặn bề ngang lưới, vì thế là đẻ lại dải trống hai bên mà Boss
   vừa bắt tôi vá.

   Boss xếp lại chỗ đứng:
     · Lớp đến giờ  → sang CỘT CUỐI, cao HAI HÀNG
     · Dự giờ       → về đúng ô cũ của Lớp đến giờ
     · Yêu cầu GV   → về đúng ô cũ của Dự giờ
     · Phụ đạo      → gộp chung ô với Dự giờ, kéo ngang để đổi
     · Ghi chú      → rời khỏi lưới, lên thanh avatar
     · Thông báo    → thấp lại cho vừa chữ bên trong
   ══════════════════════════════════════════════════════════════════════════════ */

/* ⛔⛔ CHIỀU CAO HÀNG NAY LÀ `auto`, KHÔNG CÒN CỐ ĐỊNH. Boss muốn ô Thông báo
   *"bé lại phù hợp với chữ của các block công việc trong nó"*, mà hàng cố định
   352px thì ô ấy có co cũng vẫn chừa một dải trống bằng đúng phần thừa.
   Nay: hàng cao theo nội dung, còn các ô THƯỜNG giữ dáng nhờ `min-height`. Riêng
   ô Thông báo bỏ sàn ấy đi nên nó co được thật.
   ⛔ `min-height` chứ đừng `height`: ô nào nội dung dài hơn sàn thì phải được cao
      thêm, không thì chữ bị cắt. */
.home-bento { grid-auto-rows: auto; }
/* ⛔⛔ TRẦN CHIỀU CAO — Boss chốt 18/09/2026 (lượt 5): *"thu hẹp các block lại cho
   tôi, block nào dài quá thì dùng scroll xuống để xem thông tin"*.
   Vì sao lưới bị kéo dài ra: ô "Lớp đến giờ" ghim cao HAI HÀNG, mà nội dung của nó
   (19 lớp) lại cao hơn hai hàng — lưới bèn nới cả hai hàng ấy ra cho vừa, kéo theo
   MỌI ô cùng hàng cao lên gần 550px dù chúng chẳng có gì để bày.
   Nay mỗi ô có trần; nội dung dài hơn trần thì `.hb-noi` tự cuộn (nó đã
   `overflow:auto` sẵn từ đầu).
   ⛔ `max-height` chứ đừng `height`: ô ít chữ vẫn được phép thấp hơn trần, không thì
      ô rỗng lại chừa một mảng trắng đúng bằng phần thừa.
   ⛔ Hai ô KHÔNG có trần, cố ý: Thông báo công việc và Đang online phải co sát theo
      chữ — chính Boss đã bắt sửa ở lượt 2. */
.hb-o { min-height: 300px; max-height: 360px; }
.hb-tb, .hb-online { max-height: none; }

/* Bốn cột từ 1700px — chỗ bắt đầu thấy bẹp trên màn của Boss. */
@media (min-width: 1700px) {
  .home-bento { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (min-width: 1000px) {
  /* ⛔ `-2 / -1` là CỘT CUỐI, đếm ngược từ mép phải — nhờ thế một dòng này đúng cho
     cả lưới 3 cột lẫn 4 cột. Ghi `grid-column: 3` thì sang lưới 4 cột nó rơi vào
     giữa, mà màn hẹp vẫn đúng nên rất dễ tưởng đã xong. */
  /* Cao hai hàng = 2 trần + khe giữa hai hàng. Ghi thẳng con số thì sửa `gap` là
     sai ngay, nên tính bằng `calc` theo đúng hai số đã khai ở trên. */
  .hb-lop { grid-column: -2 / -1; grid-row: 1 / 3; max-height: calc(360px * 2 + 20px); }
  /* Thông báo công việc: rộng hai cột, và BỎ SÀN chiều cao để co theo chữ. */
  .hb-tb { grid-column: span 2; min-height: 0; }
  .hb-online { grid-column: 1 / -1; }
}
/* Ba cột: hàng 3 chỉ còn mình ô Thông báo, cho nó ăn trọn cho khỏi hở. */
@media (min-width: 1000px) and (max-width: 1699.98px) {
  .hb-tb { grid-column: 1 / -1; }
}

/* ── Ô GỘP: kéo ngang để đổi mục (Dự giờ ⇄ Phụ đạo) ──────────────────────── */
.hb-gop .hb-keo {
  flex: 1 1 auto; min-height: 0;
  display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; scrollbar-width: none;
}
.hb-gop .hb-keo::-webkit-scrollbar { display: none; }
.hb-trang {
  flex: 0 0 100%; min-width: 0;
  display: flex; flex-direction: column;
  scroll-snap-align: start;
}
.hb-trang-dau {
  display: flex; align-items: center; gap: 6px;
  padding: 0 16px 6px;
  font-size: 12px; font-weight: 600; color: var(--mo);
}
.hb-trang-dau i { width: 14px; height: 14px; margin-right: 0; }
.hb-trang-nut { padding: 0 14px 10px; }
.hb-trang-nut button {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 13px; font-weight: 500;
  padding: 6px 10px; border: 0; border-radius: 7px;
  background: transparent; color: var(--chu); cursor: pointer;
}
.hb-trang-nut button:hover { background: var(--nen2); }
.hb-trang-nut svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; }
/* Hai chấm ở đáy — dấu hiệu DUY NHẤT cho biết còn mục thứ hai bên cạnh.
   ⛔ Đừng bỏ đi cho gọn: bỏ là thành tính năng có mà không ai biết để dùng. */
.hb-cham {
  display: flex; justify-content: center; gap: 5px; padding: 0 0 10px;
}
.hb-cham span {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--vien); transition: background .2s ease, width .2s ease;
}
.hb-cham span.dang { width: 14px; border-radius: 3px; background: var(--mo); }
/* Ô gộp không nhích thân khi rê — nút đã nằm sẵn trong từng trang. */
.hb-gop:hover .hb-keo { transform: none; }

/* ── Thanh avatar THẤP XUỐNG (Boss chốt) ─────────────────────────────────── */
/* ⛔ Hạ `padding`, ĐỪNG đặt `height` cố định: bên trong là ba cụm chữ có thể xuống
   dòng (lời chào · tên · chức vụ), ghim chiều cao là chữ bị cắt ở tài khoản có tên
   dài. Đo trước khi sửa: cao 105px → sau còn ~76px. */
@media (min-width: 821px) {
  .home-hero { padding: 11px 20px; gap: 14px; }
  .home-hero-av { width: 48px; height: 48px; }
  .home-hero-chao h2 { font-size: 19px; }
  /* ⛔⛔ NÚT GHI CHÚ NAY CÓ CẢ TRÊN MÁY TÍNH — Boss chốt *"cái ô ghi chú cho vào
     thanh avatar"*. Luật cũ `.home-hero-note { display:none }` ở khối máy tính
     giấu nó đi, nên phải mở lại ở đây — và luật này đứng SAU nên thắng. */
  .home-hero-note {
    display: flex; align-items: center; justify-content: center; gap: 2px;
    flex: none; margin-left: auto; width: 36px; height: 36px; padding: 0;
    border: 1px solid rgba(255,255,255,.34); border-radius: 50%;
    background: rgba(255,255,255,.16); color: #fff; cursor: pointer;
    transition: background .2s ease, transform .2s ease;
  }
  .home-hero-note:hover { background: rgba(255,255,255,.3); }
  .home-hero-note .hn-giay { width: 16px; height: 16px; flex: none; fill: none;
    stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
  .home-hero-note .hn-mui { width: 11px; height: 11px; flex: none; fill: none;
    stroke: currentColor; stroke-width: 2; transition: transform .25s ease; }
  body.home-note-mo .home-hero-note .hn-mui { transform: rotate(180deg); }
  /* ⛔ 18/09/2026 (lượt 4) — Boss: *"chỗ thứ ngày tháng ngay bên cạnh avatar bạn
     sửa cho nó dịch sang góc bên phải như trên điện thoại"*.
     Nên KHỐI NGÀY giữ `margin-left:auto` (nó tự đẩy mình sang phải), còn NÚT GHI CHÚ
     bỏ `auto` đi để nó bám ngay sau khối ngày — thành ra thứ tự sát mép phải là
     [thứ/ngày] [nút ghi chú], đúng ảnh Boss chọn.
     ⛔ CHỈ MỘT trong hai thứ được có `margin-left:auto`. Để cả hai thì cái đầu ăn
        hết khoảng trống, cái sau dính luôn vào nó — đó là lý do trước đây khối ngày
        phải nhường (`margin-left:0`) và ngày bị kẹt sát bên avatar. */
  .home-hero-ngay { margin-left: auto; }
  .home-hero-note { margin-left: 0; }
}

/* ── Khối ghi chú gập, ngay dưới thanh avatar ────────────────────────────── */
/* ⛔ Gập bằng `grid-template-rows: 0fr → 1fr`, ĐỪNG dùng `height: 0 → auto`:
   `auto` không chạy hiệu ứng được, nó nhảy một phát. Cách này là cách duy nhất
   cho một khối CAO BAO NHIÊU TUỲ NỘI DUNG mà vẫn trượt mượt.
   ⛔ `min-height: 0` ở ruột là bắt buộc, thiếu nó thì lúc đóng vẫn hở một dải. */
.home-note-gap {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .28s cubic-bezier(.22,.7,.3,1);
}
body.home-note-mo .home-note-gap { grid-template-rows: 1fr; }
.home-note-trong {
  min-height: 0; overflow: hidden;
  border: 1px solid var(--vien); border-radius: 12px;
  background: var(--the);
  box-shadow: 0 0 0 1px rgba(0,0,0,.03), 0 2px 4px rgba(0,0,0,.05);
}
body.toi .home-note-trong {
  box-shadow: 0 0 0 1px rgba(255,255,255,.10);
}
/* Lúc đóng thì bỏ cả viền, không thì còn một vạch mảnh nằm chình ình giữa trang. */
body:not(.home-note-mo) .home-note-trong { border-color: transparent; box-shadow: none; }
.home-note-gap .home-note-tb { padding: 10px 12px 0; }
.home-note-gap .home-note-o { padding: 8px 14px 4px; min-height: 96px; }
.home-note-gap .home-note-tt { padding: 0 14px 10px; }
@media (prefers-reduced-motion: reduce) {
  .home-note-gap { transition: none; }
}

/* ⛔⛔ Ô BENTO KHÔNG ĐỘI TRẦN 5 DÒNG CỦA BĂNG VUỐT ĐIỆN THOẠI.
   `.htin-o-than` ghim `max-height: 5 dòng ≈ 199px` — đúng cho băng vuốt trên điện
   thoại, nhưng trong ô "Lớp đến giờ" cao 696px thì nó cắt ngang dòng thứ tư rồi bỏ
   lại gần 500px trắng bên dưới. Nhìn ra đúng như ô bị hỏng.
   Trần gỡ ở đây, còn việc cuộn để `.hb-noi` lo — ô nào nội dung dài hơn thì cuộn
   trong thân ô, đúng một chỗ cuộn chứ không phải hai cái lồng nhau.
   ⛔ Bộ chọn phải có `.hb-noi` đứng trước (0,2,0) mới thắng được luật gốc (0,1,0);
      viết `.htin-o-than` trơn thì hai luật ngang cơ, và luật gốc nằm ở file kia. */
/* ⛔⛔ PHẢI TRỪ `.home-gio-cuon` RA. Băng vuốt trên điện thoại (`#homeGio`) MANG
      LUÔN CLASS `hb-noi` — viết `.hb-noi .htin-o-than` trơn là gỡ mất trần 5 dòng
      của chính cái băng ấy, và bài `thu-trang-chu-va-menu-avatar` đỏ thêm 9 phép.
      Trần 5 dòng vẫn đúng cho băng vuốt: ở đó nhiều thẻ xếp ngang nhau, thẻ nào cao
      lên là kéo dài cả trang. Trong ô bento thì ngược lại — ô đã cao sẵn 696px. */
.hb-noi:not(.home-gio-cuon) .htin-o-than { max-height: none; overflow: visible; padding: 0; }

/* Ô "Đang online" chỉ là một dải avatar — cho nó co sát, đừng giữ sàn 340px.
   Trên điện thoại nó đang chiếm nguyên một màn trống trơn. */
.hb-online { min-height: 0; }
.hb-online .hb-noi { padding-bottom: 8px; }

/* Ô "Thông báo công việc": hai nút lọc (việc của tôi / việc cả cơ sở) nay NGỒI ĐÚNG
   HÀNG TÊN Ô, góc phải — thay vì lơ lửng thành một hàng riêng bên dưới.
   ⛔ Ghim tuyệt đối so với cả ô (`.hb-o` đã `position: relative` sẵn cho nút "Xem →"),
      nên lúc rê chuột — tên ô mờ đi, thân ô trượt lên — hai nút vẫn đứng yên chỗ cũ,
      bấm được suốt. Nếu để chúng trôi theo `.hb-noi` thì rê vào là chúng nhảy lên
      chồng lên chữ.
   ⛔ Chừa `padding-right` ở hàng tên, không thì tên ô dài gặp hai nút là đè nhau. */
.hb-tb .hb-dau { padding-right: 92px; }
.hb-tb .hb-noi .home-khoi-dau {
  position: absolute; top: 10px; right: 14px; z-index: 2;
  padding: 0; margin: 0; min-height: 0; background: none; border: 0;
}

/* ══════════════════════════════════════════════════════════════════════════════
   🧱 VIỀN RÕ + NỀN TRANG XÁM NHẠT — Boss chốt 18/09/2026
   ──────────────────────────────────────────────────────────────────────────────
   Boss: *"thiết kế sao cho rõ nét các block viền hơn"* và *"cách các block ra 1 xíu
   thật nhỏ"*. Bản trước chỉ có ba lớp bóng, không có viền thật — trên màn sáng, ô
   trắng nằm trên nền #F6F5F3 gần như không phân biệt được mép.
   Nay: nền vùng trang chủ xuống một bậc xám, ô giữ trắng và có viền 1px thật.
   ⛔ Nền chỉ đổi Ở TRANG CHỦ (`body:has(.home-bento)`), không đổi cả app — các màn
      công cụ khác vẫn nền cũ, vì ô/bảng ở đó được dựng theo nền ấy. */
/* ⛔ 21/09/2026 — KHAI TRÊN `body.man-cong-cu`, KHÔNG trên `:root`. File công cụ
   không được mọc thêm `:root` (bài thu-css-khong-de-len-nen-chung, Boss chốt
   08/09). Cả hai chỗ dùng biến này đều nằm dưới `body.man-cong-cu`, nên màu y hệt.
   `body.toi` cùng độ nặng (0,1,1) và đứng SAU nên nền tối vẫn thắng. */
body.man-cong-cu { --home-nen: #EFEDE8; }
body.toi { --home-nen: #181C1F; }
/* ⛔⛔ PHẢI ĐỦ CƠ MỚI ĐÈ ĐƯỢC. Luật `body.man-cong-cu .noi-dung.nd-co-cuon`
   (đặc hiệu 0,3,0) đã ghim nền `var(--the)` — tức TRẮNG ĐẶC. Bản đầu tôi viết
   `body:has(.home-bento) .noi-dung` chỉ được 0,2,1 nên thua, và thua LẶNG LẼ:
   trang vẫn hiện bình thường, chỉ là nền không đổi. Đo mới thấy (nền trang và
   nền ô cùng ra rgb(255,255,255)).
   Nay kèm `.man-cong-cu` và cả `.nd-co-cuon` để hơn hẳn một bậc. */
body.man-cong-cu:has(.home-bento) .noi-dung,
body.man-cong-cu:has(.home-bento) .noi-dung.nd-co-cuon { background: var(--home-nen); }

.home-bento { gap: 20px; }
.hb-o {
  border: 1px solid var(--vien);
  /* Bóng nhẹ hơn hẳn bản trước: nay viền lo việc tách ô khỏi nền, bóng chỉ còn
     nhiệm vụ nâng ô lên một chút. Để nguyên ba lớp bóng cũ cộng thêm viền là ô
     trông nặng, đúng kiểu "web hiệu ứng" mà Boss đã chê. */
  box-shadow: 0 1px 2px rgba(0,0,0,.05);
}
body.toi .hb-o {
  border-color: rgba(255,255,255,.13);
  box-shadow: 0 1px 2px rgba(0,0,0,.35);
}
/* Khối ghi chú gập đi theo cùng một kiểu viền, không thì nó lạc lõng. */
.home-note-trong { box-shadow: 0 1px 2px rgba(0,0,0,.05); }

/* ══════════════════════════════════════════════════════════════════════════════
   👥 DẢI NGƯỜI DÙNG: HIỆN HẾT, QUÁ MÀN MỚI "+N" — Boss chốt 18/09/2026
   ──────────────────────────────────────────────────────────────────────────────
   Trước: dải cuộn ngang, đông người thì phải kéo mới thấy hết. Boss muốn theo
   mẫu avatar-group của 21st.dev: bày hết ra, chỉ khi không đủ chỗ mới gom phần
   dư vào một cái vòng "+N".
   ⛔ Bỏ luôn cuộn ngang ở đây: nay không còn gì để cuộn, mà để `overflow-x:auto`
      thì chính nó nuốt cú lăn chuột — đúng kiểu "kéo màn bị xức" Boss vừa kêu. */
.ol-khung {
  overflow-x: visible; overflow-y: visible;
  cursor: default; touch-action: auto;
}
/* Vòng "+N": cùng cỡ cùng viền với avatar để đứng chung hàng cho đều. */
.ol-them i {
  font-size: 11px; font-weight: 600; letter-spacing: -.2px;
  color: var(--chu); background: var(--nen2);
}

/* ══════════════════════════════════════════════════════════════════════════════
   🔎 THANH TÌM KIẾM TỔNG THỂ — Boss chốt 18/09/2026
   Mẫu: 21st.dev `@kokonutd/action-search-bar` (kiểu Raycast).
   ──────────────────────────────────────────────────────────────────────────────
   Mẫu gốc là React + framer-motion; kho này không có React nên phần nhìn dựng
   bằng CSS thuần. Giữ đúng bốn thứ làm nên dáng của mẫu:
     ① ô nhập một dòng, bo tròn nhẹ, biểu tượng kính lúp nằm TRONG ô;
     ② bảng kết quả bung ra ngay dưới, mỗi dòng hiện LẦN LƯỢT chứ không hiện cùng lúc;
     ③ mỗi dòng: biểu tượng · tên đậm · mô tả mờ · loại nằm sát mép phải;
     ④ chân bảng nhắc phím tắt.
   ══════════════════════════════════════════════════════════════════════════════ */
.tim-tong { position: relative; z-index: 30; }

.tim-hop {
  position: relative;
  display: flex; align-items: center; gap: 9px;
  padding: 0 12px;
  height: 42px;
  border: 1px solid var(--vien); border-radius: 11px;
  background: var(--the);
  box-shadow: 0 1px 2px rgba(0,0,0,.05);
  transition: border-color .18s ease, box-shadow .18s ease;
}
/* Viền sáng lên khi con trỏ đang ở trong ô — dấu hiệu duy nhất cho biết gõ là ăn. */
.tim-hop:focus-within {
  border-color: var(--xanh);
  box-shadow: 0 0 0 3px rgba(14,124,134,.13);
}
.tim-kinh {
  width: 17px; height: 17px; flex: none;
  fill: none; stroke: var(--mo); stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.tim-o {
  flex: 1 1 auto; min-width: 0;
  border: 0; outline: 0; background: none;
  font: inherit; font-size: 14px; color: var(--chu);
}
.tim-o::placeholder { color: var(--mo); }
/* Nhắc phím tắt. ⛔ Ẩn trên điện thoại: ở đó không có bàn phím vật lý, bày ra
   một cái phím tắt không bấm được là đúng thứ Boss đã chê một lần. */
.tim-phim {
  flex: none; font: inherit; font-size: 11px; font-weight: 500;
  color: var(--mo); background: var(--nen2);
  border: 1px solid var(--vien); border-radius: 6px;
  padding: 2px 6px; letter-spacing: .2px;
}
@media (max-width: 820px) { .tim-phim { display: none; } }

/* ── Bảng kết quả ─────────────────────────────────────────────────────────── */
/* ⛔ ĐÈ LÊN lưới ô, đừng đẩy lưới xuống. Đẩy thì mỗi phím gõ là cả trang nhảy
   một cái — vừa khó nhìn vừa làm người ta mất chỗ đang đọc. */
.tim-bang {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 40;
  max-height: min(56vh, 460px); overflow: auto; overscroll-behavior: contain;
  border: 1px solid var(--vien); border-radius: 12px;
  background: var(--the);
  box-shadow: 0 10px 30px rgba(0,0,0,.13), 0 2px 6px rgba(0,0,0,.06);
  animation: timBangVao .22s cubic-bezier(.22,.7,.3,1);
}
body.toi .tim-bang { box-shadow: 0 10px 30px rgba(0,0,0,.5); }
@keyframes timBangVao { from { opacity: 0; transform: translateY(-6px); } }

.tim-ds { padding: 5px; }
/* Bốn cột: biểu tượng · tên · mô tả (co giãn) · loại. Mô tả là cột DUY NHẤT được
   phép co, nên tên và loại không bao giờ bị cắt. */
.tim-d {
  display: grid; align-items: center;
  grid-template-columns: 22px auto minmax(0, 1fr) auto;
  gap: 9px;
  padding: 8px 9px;
  border-radius: 8px;
  cursor: pointer;
  animation: timDongVao .24s ease backwards;
  animation-delay: calc(var(--i, 0) * 32ms);
}
@keyframes timDongVao { from { opacity: 0; transform: translateY(7px); } }
.tim-d:hover, .tim-d.dang { background: var(--nen2); }
.tim-d-ico { display: flex; align-items: center; justify-content: center; }
.tim-svg {
  width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--mo);
}
.tim-d.dang .tim-svg, .tim-d:hover .tim-svg { color: var(--xanh-dam); }
.tim-d-ten { font-size: 13.5px; font-weight: 600; color: var(--chu); white-space: nowrap; }
.tim-d-mt {
  font-size: 12px; color: var(--mo);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Loại nằm sát mép phải, chữ nhỏ — y như cột "Command / Application" của mẫu. */
.tim-d-loai { font-size: 11px; color: var(--mo); white-space: nowrap; }

.tim-trong { padding: 16px; text-align: center; font-size: 13px; color: var(--mo); }
.tim-chan {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 8px 12px;
  border-top: 1px solid var(--vien);
  font-size: 11px; color: var(--mo);
}
@media (max-width: 820px) { .tim-chan { display: none; } }

/* ── Lớp thứ hai: chọn một học sinh rồi chọn việc ──────────────────────────── */
/* Boss chốt: bấm vào một em thì hiện *"nhiều lựa chọn ở các công cụ khác nhau có
   tên và icon rõ ràng"*. Hàng đầu này cho biết đang đứng ở em nào và có nút lùi. */
.tim-hs-dau {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--vien);
  background: var(--nen2);
  border-radius: 12px 12px 0 0;
}
.tim-lui {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--vien); border-radius: 7px;
  background: var(--the); color: var(--chu); cursor: pointer;
}
.tim-lui:hover { background: var(--nen2); }
.tim-lui svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.tim-hs-ten { font-size: 13.5px; font-weight: 600; color: var(--chu); }
.tim-hs-phu {
  font-size: 12px; color: var(--mo);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

@media (prefers-reduced-motion: reduce) {
  .tim-bang, .tim-d { animation: none; }
}

/* ── Ô GỘP: hai tab bấm được (thay hai chấm) — Boss chốt 18/09/2026 ───────── */
/* Chấm cũ chỉ là hình vẽ, bấm không ăn; mà trên máy tính chuột lại không kéo ngang
   được — nên mục Phụ đạo coi như không tới được. Tab thì vừa nói rõ CÓ HAI MỤC
   vừa bấm được ngay. */
.hb-tab {
  display: flex; gap: 4px; flex: none;
  padding: 0 14px 8px;
  transition: transform .3s ease .11s;
}
.hb-tab button {
  display: inline-flex; align-items: center; gap: 5px;
  font: inherit; font-size: 12.5px; font-weight: 500;
  padding: 5px 10px; border: 1px solid transparent; border-radius: 999px;
  background: none; color: var(--mo); cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.hb-tab button i { width: 14px; height: 14px; margin-right: 0; background: currentColor; }
.hb-tab button:hover { background: var(--nen2); color: var(--chu); }
.hb-tab button.dang {
  background: var(--nen2); border-color: var(--vien);
  color: var(--chu); font-weight: 600;
}
.hb-tab button:focus-visible { outline: 2px solid var(--xanh); outline-offset: 1px; }
/* ⛔⛔ KHÔNG TRƯỢT GÌ CẢ Ở Ô GỘP — Boss bắt lỗi 18/09/2026 (lượt 5):
      *"Block phụ đạo và dự giờ bị lỗi khi lia chuột vào"*, ảnh chụp ra chữ
      "Phụ đạo đạo" chồng lên nhau.
   Nguyên do: luật ẩn tên ô lúc rê chuột chỉ áp cho `.hb-o.hb-co-cta` — mà ô gộp
   KHÔNG mang class ấy (nút của nó nằm sẵn trong từng trang, không có nút trượt lên).
   Nên tên ô "Dự giờ · Phụ đạo" đứng nguyên, trong khi hàng tab tôi cho trượt lên
   34px đè thẳng vào nó. Hai dòng chữ chồng nhau đúng ở quãng giữa.
   Cách chữa đúng là BỎ CÚ TRƯỢT, chứ không phải đi ẩn tên ô: ô này vốn không có gì
   trượt lên cả, thêm chuyển động vào chỉ để "cho giống ô khác" là tự tạo ra lỗi. */
@media (hover: hover) {
  .hb-o.hb-gop:hover .hb-tab,
  .hb-o.hb-gop:hover .hb-noi { transform: none; }
}

/* ── Kết quả tìm chia NHÓM — Boss chốt 18/09/2026 (lượt 4) ─────────────────── */
.tim-nhom {
  padding: 9px 10px 4px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--mo);
}
.tim-nhom:first-child { padding-top: 5px; }
/* Dòng "còn N nữa": KHÔNG bấm được, cố ý. Nó là lời nhắc gõ rõ hơn; cho nó bấm
   được thì phải đẻ ra một màn "kết quả đầy đủ" — việc Boss chưa giao. */
.tim-them {
  padding: 5px 10px 9px;
  font-size: 11.5px; color: var(--mo); font-style: italic;
}

/* ══════════════════════════════════════════════════════════════════════════════
   HÀNG HỌC SINH VỪA NHẢY TỚI — tô kem rồi nhạt dần
   ──────────────────────────────────────────────────────────────────────────────
   Boss chốt: *"highlight màu kem nhạt thật dễ nhìn"*, giữ ~3 giây rồi tan.
   ⛔ PHẢI TÔ CẢ `td`, không chỉ tô `tr`. Ô trong bảng điểm danh có nền riêng
      (màu theo tình trạng điểm danh), nền ấy nằm TRÊN nền của hàng nên tô mỗi
      `tr` thì gần như không thấy gì.
   ⛔ VỆT VIỀN TRÁI là thứ giúp tìm ra hàng khi bảng đang cuộn ngang: màu nền nhạt
      dễ chìm giữa một bảng đầy màu, còn vệt đậm bên trái thì không. */
.hs-toi-day, .hs-toi-day > td, .hs-toi-day > th {
  background: #FFF4CE !important;
  transition: background .5s ease, box-shadow .5s ease;
}
.hs-toi-day {
  box-shadow: inset 3px 0 0 #E8A33D;
  border-radius: 4px;
  animation: hsToiVao .45s cubic-bezier(.22,.7,.3,1);
}
@keyframes hsToiVao {
  0%   { background: #FFE49B; }
  100% { background: #FFF4CE; }
}
/* Tới lúc tan: giữ nguyên cấu trúc, chỉ trả nền về trong suốt. */
.hs-toi-day.tan, .hs-toi-day.tan > td, .hs-toi-day.tan > th {
  background: transparent !important;
}
.hs-toi-day.tan { box-shadow: none; }
body.toi .hs-toi-day, body.toi .hs-toi-day > td, body.toi .hs-toi-day > th {
  background: #4A3D1C !important;
}
body.toi .hs-toi-day { box-shadow: inset 3px 0 0 #D9A441; }
body.toi .hs-toi-day.tan, body.toi .hs-toi-day.tan > td, body.toi .hs-toi-day.tan > th {
  background: transparent !important;
}
@media (prefers-reduced-motion: reduce) {
  .hs-toi-day { animation: none; }
}

/* ── Vệt mờ ở đáy ô: "còn nữa ở dưới" — Boss chốt 18/09/2026 (lượt 5) ─────── */
/* ⛔ `pointer-events:none` là bắt buộc: vệt phủ ngang qua vùng cuộn và qua cả nút
   "Xem →", thiếu dòng này là nó nuốt cú bấm ở dải đáy ô.
   ⛔ Chừa 1px mỗi bên để không đè lên viền ô — đè thì góc ô trông như bị khuyết. */
.hb-o, .hb-trang { --hb-day: 1px; }
/* Ô gộp có hàng nút nằm dưới vùng cuộn, nên vệt phải dừng TRÊN hàng nút ấy. */
.hb-gop .hb-trang { --hb-day: 40px; position: relative; }
.hb-o.hb-con-nua::after,
.hb-trang.hb-con-nua::after {
  content: ""; position: absolute;
  left: 1px; right: 1px; bottom: var(--hb-day); height: 34px;
  pointer-events: none; z-index: 1;
  border-radius: 0 0 11px 11px;
  background: linear-gradient(180deg, rgba(255,255,255,0), var(--the) 86%);
}
body.toi .hb-o.hb-con-nua::after,
body.toi .hb-trang.hb-con-nua::after {
  background: linear-gradient(180deg, rgba(0,0,0,0), var(--the) 86%);
}

/* ═══════════════════════════════════════════════════════════════════════════
   KHỐI XEM CỦA CÁC MÀN LỊCH + LƯỚI KÉO SANG HAI BÊN — Boss chốt 20/09/2026
   ---------------------------------------------------------------------------
   Đi cùng ganKhoiXem() và ganKeoNgang() ở cuối js/tinh-nang.js.
   ⛔ BO GÓC DÙNG var(--r-lg) = 0px — Boss chốt 02/09 mọi panel là góc vuông.
      Đừng tự đặt border-radius:8px cho "mềm mại", nó lệch khỏi cả app.
   ⛔ Màu lấy từ biến, không tô cứng — để nền tối tự ăn theo.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Khối xem — nổi cạnh ô, KHÔNG có lớp nền mờ phủ màn (nó chỉ để LIẾC, bấm ra
   ngoài là tắt). z-index 70 là tầng của .lgv-hop-nen; khối này phải nằm DƯỚI
   hộp ấy, vì giữ lâu trên điện thoại sẽ mở hộp đè lên. */
.kx-khoi {
  position: fixed; z-index: 66; width: min(320px, calc(100vw - 16px));
  background: var(--the); color: var(--chu);
  border: 1px solid var(--vien); border-radius: var(--r-lg);
  box-shadow: var(--bong-2); padding: 11px 13px 10px;
  font-size: 13px; line-height: 1.45; overflow: auto;
  opacity: 0; transform: translateY(-3px);
  transition: opacity .12s ease, transform .12s ease;
  /* Khối chỉ để đọc — đừng nuốt cú rê chuột đang đi qua nó lúc chưa hiện hẳn. */
  overscroll-behavior: contain;
}
/* ⭐ GỢI Ý NGẮN (thay hộp chữ đen của trình duyệt) — Boss 19/09/2026.
   Khối xem vốn rộng 320px cho một buổi học đầy thông tin; tên một cái nút chỉ có
   vài chữ, để nguyên khổ ấy thì một dải trắng mênh mông quanh hai từ.
   ⛔ `:has()` chứ đừng thêm lớp vào `.kx-khoi`: khối ấy do `kxMo` dựng và chỉ nhận
      phần RUỘT, không có đường gắn lớp từ bên ngoài. */
.kx-khoi:has(.kx-goiy) {
  width: auto; max-width: min(300px, calc(100vw - 16px));
  padding: 6px 9px; font-size: 12.5px; line-height: 1.4;
}
.kx-goiy { display: block; white-space: pre-line; }
.kx-khoi.hien { opacity: 1; transform: none; }
.kx-khoi[hidden] { display: none; }

.kx-ten { font-size: 15px; font-weight: 700; margin: 0 0 2px; letter-spacing: normal; }
.kx-phu { font-size: 12px; color: var(--mo); margin-bottom: 8px; }
.kx-dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; margin: 0; }
.kx-dl dt { color: var(--mo); font-size: 12px; }
.kx-dl dd { margin: 0; font-size: 12.5px; }

/* Vạch ngăn phần "buổi này" với phần "cô ấy dạy những lớp nào" — hai loại tin
   khác hẳn nhau, dính liền thì mắt đọc thành một khối chữ. */
.kx-chia {
  margin: 9px -13px 8px; border: 0; border-top: 1px solid var(--vien-nhe);
}
.kx-dem { font-size: 12.5px; margin-bottom: 4px; }
.kx-dem b { font-variant-numeric: tabular-nums; }
/* Boss chốt: lớp nhiều thì HIỆN HẾT, không cắt. Nên cho khối tự cao và cuộn
   trong, chứ không gộp thành "+3 lớp nữa". */
.kx-lop-ds { display: flex; flex-wrap: wrap; gap: 4px; }
.kx-lop-ds span {
  font-size: 12px; padding: 1px 7px; border: 1px solid var(--vien);
  border-radius: var(--r-md); background: var(--nen2); white-space: nowrap;
}
.kx-nghile {
  margin: 0 0 7px; padding: 5px 8px; font-size: 12.5px; font-weight: 600;
  color: var(--nhan-chu); background: var(--nhan-nen);
  border: 1px solid var(--nhan-vien); border-radius: var(--r-md);
}
.kx-goi { margin-top: 8px; font-size: 11.5px; color: var(--mo); }

/* Lưới đang bị kéo: cấm bôi chữ, và đổi con trỏ cho biết đang cầm được. */
.dang-keo-ngang {
  cursor: grabbing; user-select: none; -webkit-user-select: none;
  touch-action: pan-y;         /* để ngón tay vẫn cuộn DỌC trang được */
}
/* ⛔ touch-action phải đặt cho CẢ lúc chưa kéo, không thì trình duyệt cuộn ngang
   theo quán tính và cú kéo của mình không bao giờ nhận đủ pointermove. */
[data-keo-ngang="1"] { touch-action: pan-y; }

@media (prefers-reduced-motion: reduce) {
  .kx-khoi { transition: none; }
  [data-keo-ngang="1"] { transition: none !important; }
}

/* ── Nền tối ─────────────────────────────────────────────────────────────── */
body.toi .kx-khoi { box-shadow: 0 6px 22px rgba(0,0,0,.45); }
body.toi .kx-lop-ds span { background: var(--nen2); border-color: var(--vien); }

/* Lớp NẰM TRONG TUẦN đang trỏ — tô đậm hơn để phân biệt với lớp của
   những tuần khác trong tháng. Boss chốt hiện cả hai con số, nên danh sách
   này là của CẢ THÁNG; không đánh dấu thì hai con số kia thành vô nghĩa. */
.kx-lop-ds span.tuan-nay {
  background: var(--xanh-nhat); border-color: var(--xanh); color: var(--xanh-dam);
  font-weight: 600;
}
body.toi .kx-lop-ds span.tuan-nay { background: rgba(20,160,160,.16); }

/* ══════════════════════════════════════════════════════════════════════════════
   🧾 DÒNG MỤC TRONG CÁC Ô TRANG CHỦ — Boss chốt 30/09/2026 (20 câu bấm nút)
   ──────────────────────────────────────────────────────────────────────────────
   Boss: *"thiết kế các block ở trong block sao cho nó ko cứng nhắc và đẹp hiện đại.
   Chứ tôi thấy nó đang bị xấu quá và hơi cứng nhắc ở trong block"*.
   Bản cũ: mỗi mục là một hộp xám nền `--nen2` có VẠCH MÀU dọc bên trái (cam/xanh/
   teal) — mục 10 trong "mười thứ lộ ra là máy làm" (`thiet-ke/BANG-MAU-VA-CHU.md`).
   Nay (Boss chọn "Dòng gọn kẻ mảnh" cho TẤT CẢ ô): không hộp, không vạch; các dòng
   ngăn nhau bằng một nét kẻ mảnh, rê chuột thì cả dòng sáng nhẹ và hiện mũi tên.
   Nhãn trạng thái là viên nền nhạt theo NGHĨA (Boss chọn): teal = cần để ý ·
   đỏ = quá hạn · xám = đã có người lo.
   ⛔ Dùng lớp MỚI (`tc-*`), không sửa luật `.htin-d` cũ: luật cũ còn nằm rải ở
      css/lop.css, sửa từng dòng là đụng file nhiều kênh cùng gõ. Mã JS nay
      không đẻ ra `.htin-d` nữa nên luật cũ tự thôi khớp.
   ⛔ Biến màu khai trên `.home-bento`, KHÔNG trên `:root` — file này không được mọc
      thêm `:root` (bài thu-css-khong-de-len-nen-chung).
   ⛔ Chỉ nét 600 là đậm nhất, không in hoa cả dòng, bo 4px cho nút / 999px cho viên
      nhãn (bảng số đã chốt §4). Không emoji.
   ══════════════════════════════════════════════════════════════════════════════ */
.home-bento {
  --tc-ke: rgba(31, 29, 26, .09);          /* nét kẻ giữa hai dòng */
  --tc-re: #F3F1ED;                         /* nền dòng lúc rê chuột */
  --tc-re-dam: #E9E6E0;                     /* nền nút nhỏ lúc rê chuột */
  --tc-do-nen: #FBEAE7;                     /* viên "Quá hạn" */
}
body.toi .home-bento {
  --tc-ke: rgba(255, 255, 255, .09);
  --tc-re: rgba(255, 255, 255, .05);
  --tc-re-dam: rgba(255, 255, 255, .10);
  --tc-do-nen: rgba(231, 76, 60, .18);
}

/* Danh sách. Kéo rộng ra hai bên 8px để nền rê chuột trùm tới gần mép ô mà chữ
   vẫn thẳng hàng với tên ô. ⛔ Không làm ở băng vuốt điện thoại (`.home-gio-cuon`):
   thân thẻ ở đó tự cuộn, kéo rộng ra là mọc thanh cuộn ngang. */
.tc-ds { display: flex; flex-direction: column; }
.hb-noi:not(.home-gio-cuon) .tc-ds,
.hb-noi:not(.home-gio-cuon) .htin-o-than { margin-inline: -8px; }
/* Băng vuốt điện thoại tính trần "khoảng 5 dòng" (Boss 10/09) theo `--htin-cao-dong`
   — dòng mới hai tầng chữ cao ~54px chứ không còn 33px. Dòng mới ngăn nhau bằng nét
   kẻ chứ không bằng khe, nên công thức trần bỏ luôn vế khe `5px × 4` của bản cũ:
   5 dòng + lề trong 14px (bài thu-trang-chu-va-menu-avatar đo ra số dòng thật).
   Máy tính không dính: ở đó `.hb-noi:not(.home-gio-cuon) .htin-o-than` bỏ trần. */
.home-bento .htin-o-than {
  gap: 0; --htin-cao-dong: 54px;
  max-height: calc(var(--htin-cao-dong) * var(--htin-so-dong, 5) + 14px);
}

/* Tiêu đề nhóm: "Hôm nay · 3". Chữ thường, nhỏ, xám — chỉ để chia, không để hút mắt. */
.tc-nhom {
  padding: 12px 8px 4px;
  font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--mo);
}
.tc-nhom:first-child { padding-top: 2px; }
.tc-nhom span { font-weight: 400; }

/* ── Một dòng ─────────────────────────────────────────────────────────────── */
.tc-dong {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 8px; border-radius: 6px;
  transition: background-color .12s ease;
}
/* Nét kẻ mảnh giữa hai dòng liền nhau. Kẻ bằng bóng trong chứ không bằng viền, để
   dòng không cao thêm 1px và nền rê chuột phủ kín lên nét. */
.tc-ds > :is(.tc-dong, .tc-viec) + :is(.tc-dong, .tc-viec),
.htin-o-than > .tc-dong + .tc-dong { box-shadow: inset 0 1px 0 var(--tc-ke); }
.tc-dong.mo-duoc { cursor: pointer; }
.tc-dong.mo-duoc:hover { background: var(--tc-re); }
.tc-dong.mo-duoc:focus-visible { outline: 2px solid var(--xanh); outline-offset: -2px; }

.tc-chu { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tc-ten {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--chu);
}
/* Tên một dòng, dài thì cắt GỌN ở mép — mọi dòng thẳng hàng nhau, chữ đầy đủ nằm ở
   công cụ. ⛔ KHÔNG dấu "…" (Boss 21/09 "bỏ hết dấu ba chấm", bài thu-bo-dau-ba-cham). */
.tc-ten-chu { min-width: 0; overflow: hidden; white-space: nowrap; }
.tc-them { flex: none; font-size: 11.5px; font-weight: 500; color: var(--mo); white-space: nowrap; }
.tc-toi {
  flex: none; font-size: 10.5px; font-weight: 600; line-height: 16px;
  padding: 0 6px; border-radius: 4px;
  color: var(--xanh-dam); background: var(--xanh-nhat);
}
/* Nền tối: teal đậm chỉ còn ~3:1 — dùng đúng cặp màu của viên nhãn teal nền tối
   (bài thu-nen-toi-chu-sang-21-09 ⑥ bắt đúng chỗ này). */
body.toi .tc-toi { color: #5AD0C6; background: rgba(20, 160, 160, .18); }
.tc-ten .nv-thi-nhan { flex: none; }
/* Dòng phụ xuống tối đa HAI dòng, không cắt cụt một dòng: tên người, ngày, cơ sở dài
   bao nhiêu là tuỳ — cắt một dòng là giấu đúng thứ cần đọc (luật 21/08 vẫn đúng).
   ⛔ Trần `2lh`, KHÔNG `-webkit-line-clamp`: kẹp dòng luôn tự vẽ "…" (khối ㊲ cuối
      css/lop.css). */
.tc-phu {
  font-size: 12px; line-height: 1.4; color: var(--mo);
  max-height: 2lh; overflow: hidden; overflow-wrap: anywhere;
}

/* ── Viên nhãn trạng thái ─────────────────────────────────────────────────── */
.tc-chip {
  flex: none; max-width: 150px;
  overflow: hidden; white-space: nowrap;
  font-size: 11px; font-weight: 600; line-height: 20px;
  padding: 0 9px; border-radius: 999px;
}
.tc-chip.teal { color: var(--xanh-dam); background: var(--xanh-nhat); }
.tc-chip.do   { color: var(--do);       background: var(--tc-do-nen); }
.tc-chip.xam  { color: var(--mo);       background: var(--nen2); }
body.toi .tc-chip.teal { color: #5AD0C6; background: rgba(20, 160, 160, .18); }
body.toi .tc-chip.do   { color: #F1948A; }
body.toi .tc-chip.xam  { background: rgba(255, 255, 255, .07); }

/* Mũi tên cuối dòng: luôn chiếm chỗ (dòng không nhảy), chỉ hiện khi rê / khi chọn
   bằng bàn phím — nói "bấm được" đúng lúc cần, không rải mũi tên khắp ô. */
.tc-mui {
  flex: none; width: 14px; height: 14px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  color: var(--mo); opacity: 0; transform: translateX(-3px);
  transition: opacity .12s ease, transform .12s ease;
}
.tc-dong.mo-duoc:hover .tc-mui,
.tc-dong.mo-duoc:focus-visible .tc-mui { opacity: .75; transform: none; }
/* Máy cảm ứng không có rê chuột: mũi tên hiện sẵn, mờ, để biết dòng bấm được. */
@media (hover: none) { .tc-mui { opacity: .45; transform: none; } }

/* ── Ô "Thông báo công việc": hàng tab cơ sở + bung đầu mục ──────────────── */
/* Hàng tab dính ở đầu vùng cuộn: cuộn xuống giữa danh sách vẫn đổi cơ sở được.
   ⛔ KHÔNG đặt z-index: có z-index là dải tab nổi LÊN TRÊN lớp phủ sạm lúc rê chuột
      (`.hb-phu`, nằm sau trong DOM) → thành một vệt trắng giữa ô đang sạm. Để mặc
      định thì dải tab vẫn đè lên các dòng (dòng không định vị), mà lớp phủ trùm đều. */
.tc-cs {
  position: sticky; top: 0;
  display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none;
  padding: 0 0 10px; background: var(--the);
}
.tc-cs::-webkit-scrollbar { display: none; }
/* Cao 30px: đáy chung cho nút bấm được ở Trang chủ (bài thu-home-thong-bao-viec).
   Điện thoại lên 32px ở cuối khối này. */
.tc-cs-nut {
  flex: none; height: 30px; padding: 0 12px;
  font: inherit; font-size: 12.5px; font-weight: 500; white-space: nowrap;
  color: var(--chu); background: var(--the);
  border: 1px solid var(--vien); border-radius: 999px; cursor: pointer;
}
.tc-cs-nut:hover { background: var(--tc-re); }
.tc-cs-nut.chon { color: var(--xanh-dam); background: var(--xanh-nhat); border-color: var(--xanh); font-weight: 600; cursor: default; }
.tc-cs-nut:focus-visible { outline: 2px solid var(--xanh); outline-offset: 1px; }
body.toi .tc-cs-nut.chon { color: #5AD0C6; background: rgba(20, 160, 160, .18); }

.tc-bung-nut {
  flex: none; width: 30px; height: 30px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 4px; background: transparent; color: var(--mo); cursor: pointer;
}
.tc-bung-nut:hover { background: var(--tc-re-dam); color: var(--chu); }
.tc-bung-nut:focus-visible { outline: 2px solid var(--xanh); outline-offset: -2px; }
.tc-bung-nut svg {
  width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; transition: transform .15s ease;
}
.tc-bung-nut[aria-expanded="true"] svg { transform: rotate(180deg); }
/* Dòng việc có thêm nút bung ở cuối: khe hẹp lại 8px cho đỡ chật. */
.tc-viec .tc-dong { gap: 8px; }

.tc-bung { padding: 0 8px 12px; }
.tc-bung[hidden] { display: none; }
.tc-ct { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.tc-ct label {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 12.5px; line-height: 1.45; color: var(--chu); cursor: pointer;
}
.tc-ct input { flex: none; width: 15px; height: 15px; margin: 2px 0 0; accent-color: var(--xanh); cursor: pointer; }
.tc-ct input:disabled, .tc-ct input:disabled + span { cursor: default; }
.tc-ct li.xong span { color: var(--mo); text-decoration: line-through; }
.tc-bung-trong { margin: 0; font-size: 12px; color: var(--mo); }
.tc-bung-chan { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.tc-xong {
  height: 30px; padding: 0 12px;
  font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--xanh-dam); background: transparent;
  border: 1px solid var(--xanh); border-radius: var(--r-md); cursor: pointer;
}
.tc-xong:hover { background: var(--xanh-nhat); }
.tc-xong:disabled { opacity: .5; cursor: default; }
body.toi .tc-xong { color: #5AD0C6; }
body.toi .tc-xong:hover { background: rgba(20, 160, 160, .18); }
.tc-khoa { font-size: 12px; color: var(--mo); }

/* Ô "Thông báo công việc" nay có TRẦN như mọi ô (hiện hết việc nên có thể rất dài)
   — dài thì cuộn trong ô, vệt mờ đáy báo còn việc bên dưới (`hbNoiTay`).
   Hai nút gạt cũ ở góc phải tên ô đã bỏ, trả lại lề phải cho tên ô. */
.hb-tb { max-height: 360px; }
.hb-tb .hb-dau { padding-right: 16px; }

/* ⛔ Ô "Thông báo công việc" chỉ có với người giao việc được (Boss 30/09: trợ giảng,
   giáo viên không có ô này). Lưới 4 cột thiếu ô ấy thì hàng 2 hở hai cột giữa —
   cho ô Yêu cầu GV trải ba cột lấp chỗ. Lưới 3 cột thì ô ấy vốn nằm trọn một hàng
   riêng nên không hở gì. */
@media (min-width: 1700px) {
  .home-bento:not(:has(.hb-tb)) .hb-yc { grid-column: span 3; }
}
/* Màn vừa (2 cột): ô Việc của tôi đứng một mình một hàng — cho nó trải hết bề ngang,
   khỏi hở nửa hàng bên phải. */
@media (min-width: 700px) and (max-width: 999.98px) {
  .hb-viec { grid-column: 1 / -1; }
}
@media (max-width: 699.98px) {
  .tc-cs-nut { height: 32px; }
  .tc-bung-nut { width: 32px; height: 32px; }
}
@media (prefers-reduced-motion: reduce) {
  .tc-dong, .tc-mui, .tc-bung-nut svg { transition: none !important; }
}
