/* ═══════════════════════════════════════════════════════════════════════════
   app.css — TOÀN BỘ CSS CỦA ỨNG DỤNG HNYTTN
   Không có tệp CSS thứ hai. Mọi màn hình dùng chung bảng lớp dưới đây.

   BỐI CẢNH QUYẾT ĐỊNH THẨM MỸ
   Đây là phần mềm nghiệp vụ cho Văn phòng Hội: ba người ngồi cả ngày, nhìn
   200 dòng một lúc, nhập bằng phím Tab, và in sổ công văn ra giấy để lưu.
   Chuẩn là phần mềm quản trị công nghiệp — dày, phẳng, tương phản rõ.
   KHÔNG gradient trang trí, KHÔNG bo góc 24px, KHÔNG khoảng trắng phóng đại.
   Mỗi pixel đệm thừa là một dòng dữ liệu bị đẩy khỏi màn hình.

   LUẬT SỐ MỘT: KHÔNG HEX NÀO ĐƯỢC VIẾT NGOÀI KHỐI :root.
   Mọi màu đi qua biến. Lý do không phải thẩm mỹ mà là nền tối: chế độ tối
   được làm bằng cách định nghĩa LẠI TOÀN BỘ biến trong một khối duy nhất.
   Một mã màu viết thẳng vào .bang td là một chỗ không bao giờ đổi theo nền,
   và sẽ thành chữ đen trên nền đen mà không ai phát hiện cho tới khi in ra.

   MỤC LỤC
     1. Biến — nền sáng          9.  Chip trạng thái & thanh tiến độ
     2. Biến — nền tối           10. Nút
     3. Nền tảng & chữ           11. Biểu mẫu
     4. Bố cục vỏ ứng dụng       12. Hộp thoại & thông báo nổi
     5. Menu bên                 13. Trạng thái rỗng / đang tải / lỗi
     6. Đầu màn hình & thẻ       14. Phân trang & phụ trợ
     7. Lưới & ô số liệu         15. Đáp ứng màn hình hẹp
     8. Bảng dữ liệu             16. In giấy & giảm hoạt ảnh

     — bổ sung đợt 2 —
     17. Mười lớp từng chết (kéo thả kanban, dải bước, dòng thời gian,
         thanh soạn công văn, mã QR đen-trắng)
     18. Sửa tương phản đã đo
     19. Bộ công cụ mới: bỏ qua menu · dải tiến trình · thẻ · ngăn kéo ·
         vùng thả tệp · nhóm ô gập · cột chọn & dòng tổng · bảng lệnh ·
         ảnh đại diện · khung cắt ảnh · trình xem tệp
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Biến — nền sáng ────────────────────────────────────────────────────
   Bốn tầng nền (--nen < --the/--noi) cố ý rất gần nhau. Phần mềm nghiệp vụ
   phân tầng bằng VIỀN chứ không bằng đổ bóng: bóng đậm làm mỏi mắt sau 8 giờ
   và biến mất hoàn toàn khi in.

   Thang giãn cách là bội của 4px. Không có giá trị lẻ giữa chừng — hễ cần
   "6px cho vừa" thì thật ra là bố cục sai chứ không phải thang sai.

   Hai biến ngữ nghĩa NGOÀI danh sách hợp đồng: --trung-tinh và --cho.
   Hợp đồng khai 4 màu ngữ nghĩa (tot/canh/loi/tin) nhưng chip có 6 màu.
   'dang' (đang xử lý) dùng lại --tin (xanh dương), còn 'cho' (chờ) phải khác
   'canh' (cảnh báo) — lẫn hai màu này thì "Chờ ký" trông như một sự cố. */
:root {
  color-scheme: light;

  /* Nền */
  --nen:  #f6f7f6;
  --the:  #ffffff;
  --chim: #eef1ef;
  --noi:  #ffffff;

  /* Chữ */
  --chu:     #141d19;
  --chu2:    #56605b;
  /* --chu3 KHÔNG phải "chữ mờ cho vui". Nó mang nhãn cột bảng (12px hoa nhỏ),
     nhãn ô số liệu và chữ gợi ý — thứ Văn phòng đọc cả ngày. Sắc nhạt hơn
     #66716c sẽ tụt xuống dưới 4.5:1 trên nền --the; đo lại mỗi khi đổi. */
  --chu3:    #66716c;
  --chu-dao: #ffffff;

  /* Viền */
  --vien:     #e2e7e4;
  --vien-dam: #c8d0cb;

  /* Thương hiệu — xanh y tế, lấy từ sắc con dấu của Hội */
  --chinh:      #0b6e4f;
  --chinh-dam:  #085440;
  --chinh-nhat: #e5f1ec;
  --chinh-chu:  #ffffff;

  /* Ngữ nghĩa. Bản đậm dùng cho CHỮ trên nền -nhat; cặp nào cũng >= 4.5:1. */
  --tot:  #106b42;  --tot-nhat:  #e4f2ea;
  --canh: #97430a;  --canh-nhat: #fcece1;
  --loi:  #a8251a;  --loi-nhat:  #fdeae7;
  --tin:  #1b5490;  --tin-nhat:  #e6eff9;
  --cho:  #85580a;  --cho-nhat:  #fcf1dd;
  --trung-tinh: #4a544f;  --trung-tinh-nhat: #ebeeec;

  /* Đổ bóng — chỉ dùng cho lớp thật sự nổi lên trên (hộp thoại, menu thả).
     Bóng viết bằng rgba của màu mực, không bằng đen thuần: đen thuần trên
     nền hơi ngả lục làm viền trông bẩn. */
  --bong:     0 1px 2px rgb(20 29 25 / 6%);
  --bong-noi: 0 8px 24px -6px rgb(20 29 25 / 18%), 0 2px 6px rgb(20 29 25 / 8%);
  --lop-phu:  rgb(20 29 25 / 45%);   /* nền mờ sau hộp thoại và ngăn kéo menu */

  /* Bo góc — nhỏ. Phần mềm bảng biểu bo 12px trở lên bắt đầu trông như đồ chơi. */
  --bo-nho: 3px;
  --bo:     5px;
  --bo-lon: 8px;

  /* Giãn cách */
  --k1: 4px;  --k2: 8px;  --k3: 12px;
  --k4: 16px; --k5: 24px; --k6: 32px;

  /* Thang cỡ chữ. Gốc 14px. Bảy bậc, không hơn — mỗi bậc thêm là một quyết
     định nữa phải lặp lại đúng ở 15 màn hình viết song song. */
  --c1: 11px; --c2: 12px; --c3: 13px; --c4: 14px;
  --c5: 16px; --c6: 20px; --c7: 24px;

  /* Kích thước bố cục */
  --menu-rong:     248px;
  --menu-thu:      56px;
  --cao-dong:      40px;   /* dòng bảng — mật độ nghiệp vụ, không phải 56px */
  --cao-o:         32px;   /* ô nhập */
  --cao-thanh-tren: 48px;
  --nhanh:  120ms cubic-bezier(.2, 0, .2, 1);
}

/* ── 2. Biến — nền tối ─────────────────────────────────────────────────────
   ĐỊNH NGHĨA LẠI TOÀN BỘ, không sửa lẻ tẻ từng lớp bên dưới. Nếu có lúc nào
   phải viết `[data-theme="toi"] .bang td {…}` thì nghĩa là một biến còn
   thiếu — thêm biến, đừng thêm ngoại lệ.

   Chỉ biến MÀU và ĐỔ BÓNG được định nghĩa lại. Thang giãn cách, bo góc và
   cỡ chữ cố tình KHÔNG đổi theo nền: bố cục nhảy khi người dùng đổi chế độ
   sáng/tối là một lỗi, không phải một tính năng.

   Màu thương hiệu PHẢI sáng lên: xanh y tế nguyên bản trên nền gần đen chỉ
   đạt ~2:1 — chữ trắng trên NÚT xanh vẫn đọc được, nhưng CHỮ xanh trên nền
   tối thì không. Nên ở nền tối --chinh nhận sắc xanh nhạt hơn để làm màu
   nhấn, còn độ đậm cho nút chuyển sang --chinh-dam.

   ═══ VÌ SAO LÀ [data-theme="toi"] CHỨ KHÔNG PHẢI @media ═══
   Người dùng phải TỰ CHỌN được nền, không chỉ theo cài đặt máy: Văn phòng
   ngồi phòng sáng dùng máy cấu hình sẵn nền tối, và ba người dùng chung một
   máy có ba ý thích khác nhau.
   Cách làm CSS-thuần cho việc đó cần hai khối màu giống hệt nhau — một trong
   @media, một trong [data-theme] — và hai bảng màu phải sửa song song là
   đúng cái bẫy mà tệp này viết ở đầu: bản thứ hai sẽ bị quên.
   Nên chỉ có MỘT khối, và <head> của index.html có đoạn mã đồng bộ đặt
   data-theme='sang'|'toi' trước khi trang được vẽ (đọc localStorage, rơi về
   prefers-color-scheme khi người dùng chọn "theo hệ thống"). app.js đặt lại
   giá trị đó mỗi khi người dùng đổi, và nghe matchMedia để "theo hệ thống"
   vẫn đổi ngay giữa buổi làm việc. */
:root[data-theme="toi"] {
  color-scheme: dark;

  --nen:  #0d1311;
  --the:  #141b18;
  --chim: #1a2320;
  --noi:  #1d2723;

  --chu:     #e7ece9;
  --chu2:    #a1aca7;
  --chu3:    #88938d;
  --chu-dao: #0d1311;

  --vien:     #24302b;
  --vien-dam: #35443c;

  --chinh:      #2ea87c;
  --chinh-dam:  #52c398;
  --chinh-nhat: #112a20;
  --chinh-chu:  #04150e;

  --tot:  #53c393;  --tot-nhat:  #0e2a1f;
  --canh: #e59f60;  --canh-nhat: #31200e;
  --loi:  #ef8a7e;  --loi-nhat:  #331a17;
  --tin:  #7cb4ec;  --tin-nhat:  #13233a;
  --cho:  #e4b45f;  --cho-nhat:  #2e2411;
  --trung-tinh: #b0bbb5;  --trung-tinh-nhat: #222b27;

  --bong:     0 1px 2px rgb(0 0 0 / 40%);
  --bong-noi: 0 10px 28px -6px rgb(0 0 0 / 60%), 0 2px 6px rgb(0 0 0 / 40%);
  --lop-phu:  rgb(0 0 0 / 62%);
}

/* ── 3. Nền tảng & chữ ─────────────────────────────────────────────────────
   Be Vietnam Pro được nạp bằng <link> trong index.html (tệp của người khác).
   Ở đây chỉ khai font-family và dây dự phòng — nếu máy của Hội mất mạng thì
   system-ui phải gánh, và bố cục không được xô lệch vì thế. */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--nen);
  color: var(--chu);
  font-family: 'Be Vietnam Pro', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: var(--c4);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* Thân trang KHÔNG BAO GIỜ cuộn ngang. Bảng rộng cuộn trong .khung của nó. */
  overflow-x: hidden;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.3; }
h1 { font-size: var(--c7); }
h2 { font-size: var(--c6); }
h3 { font-size: var(--c5); }
h4 { font-size: var(--c4); }
p  { margin: 0 0 var(--k3); }
a  { color: var(--chinh); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Mọi con số phải thẳng cột. Không có dòng này thì cột tiền nhấp nhô và mắt
   không so sánh được hai số liền nhau — lỗi đọc số hay gặp nhất ở sổ quỹ. */
.so, .tien, .ma-vb, .bang td, .bang th, .o-so-gt, input, .thong-ke b {
  font-variant-numeric: tabular-nums;
}
.tien, .so { text-align: right; }
.ma-vb { font-variant-ligatures: none; letter-spacing: .01em; }

/* Tiêu điểm bàn phím. Văn phòng nhập liệu bằng Tab chứ không bằng chuột —
   mất vòng tiêu điểm là mất khả năng dùng. Viền vẽ BÊN NGOÀI (outline) nên
   không làm xô bố cục như border. */
:focus-visible {
  outline: 2px solid var(--chinh);
  outline-offset: 1px;
  border-radius: var(--bo-nho);
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--chinh-nhat); color: var(--chu); }

/* Thanh cuộn mảnh trong các khung dữ liệu — thanh cuộn mặc định 15px của
   Windows ăn mất gần một cột. */
.khung, .ben-cuon, .hop-than, .chon-ds {
  scrollbar-width: thin;
  scrollbar-color: var(--vien-dam) transparent;
}

/* ── 4. Bố cục vỏ ứng dụng ─────────────────────────────────────────────────
   Lưới hai cột cố định 248px. Không dùng flex: với flex, menu co lại khi nội
   dung bên phải có một bảng rộng, và tên màn hình bị cắt giữa chừng. */
.ung-dung {
  display: grid;
  grid-template-columns: var(--menu-rong) 1fr;
  min-height: 100dvh;
}
.ung-dung.thu-menu { grid-template-columns: var(--menu-thu) 1fr; }

/* PHẢI viết `.ung-dung > .chinh`, không được viết trần `.chinh`.
   `.chinh` còn là bổ nghĩa của nút chính (.nut.chinh). Viết trần thì mọi nút
   chính thừa hưởng flex-direction:column của vùng nội dung, và một nút có
   biểu tượng + chữ sẽ xếp chữ xuống dưới biểu tượng. */
.ung-dung > .chinh {
  min-width: 0;          /* bắt buộc: không có nó thì con rộng làm phình cả lưới */
  display: flex;
  flex-direction: column;
  background: var(--nen);
}

.than {
  flex: 1;
  min-width: 0;
  padding: var(--k4) var(--k5) var(--k6);
}

/* Thanh trên chỉ hiện ở màn hình hẹp (nút mở ngăn kéo). Xem §15. */
.thanh-tren {
  display: none;
  align-items: center;
  gap: var(--k2);
  height: var(--cao-thanh-tren);
  padding: 0 var(--k3);
  background: var(--the);
  border-bottom: 1px solid var(--vien);
  position: sticky;
  top: 0;
  z-index: 30;
}

/* ── 5. Menu bên ───────────────────────────────────────────────────────────
   Cột trái: thương hiệu trên, danh sách phân hệ ở giữa, người dùng dưới cùng. */
.ben {
  display: flex;
  flex-direction: column;
  background: var(--the);
  border-right: 1px solid var(--vien);
  position: sticky;
  top: 0;
  height: 100dvh;
  z-index: 40;
}
.ben-dau {
  display: flex;
  align-items: center;
  gap: var(--k2);
  height: var(--cao-thanh-tren);
  padding: 0 var(--k3);
  border-bottom: 1px solid var(--vien);
  flex: 0 0 auto;
}
.ben-dau .dau-hieu {
  width: 26px; height: 26px; flex: 0 0 auto;
  display: grid; place-items: center;
  border-radius: var(--bo);
  background: var(--chinh);
  color: var(--chinh-chu);
  font-size: var(--c2); font-weight: 700;
}
.ben-dau .ten {
  font-size: var(--c3); font-weight: 600; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ben-dau .ten small { display: block; color: var(--chu3); font-weight: 400; font-size: var(--c1); }

.ben-cuon { flex: 1; overflow-y: auto; padding: var(--k2) var(--k2) var(--k4); }

.ben-nhom {
  padding: var(--k3) var(--k2) var(--k1);
  font-size: var(--c1); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--chu3);
  white-space: nowrap; overflow: hidden;
}

.muc {
  display: flex; align-items: center; gap: var(--k2);
  padding: 0 var(--k2);
  height: 32px;
  border-radius: var(--bo);
  color: var(--chu2);
  font-size: var(--c3);
  cursor: pointer;
  user-select: none;
  white-space: nowrap; overflow: hidden;
  border: none; background: none; width: 100%; text-align: left;
  font-family: inherit;
}
.muc:hover { background: var(--chim); color: var(--chu); text-decoration: none; }
.muc.hien { background: var(--chinh-nhat); color: var(--chinh); font-weight: 600; }
.muc .bt { flex: 0 0 20px; display: grid; place-items: center; opacity: .85; }
.muc .nhan-muc { overflow: hidden; text-overflow: ellipsis; }
.muc .dem {
  margin-left: auto; flex: 0 0 auto;
  font-size: var(--c1); font-weight: 600;
  background: var(--chim); color: var(--chu2);
  border-radius: 999px; padding: 0 6px; min-width: 18px; text-align: center;
}
.muc.hien .dem { background: var(--chinh); color: var(--chinh-chu); }

.ben-chan {
  flex: 0 0 auto;
  border-top: 1px solid var(--vien);
  padding: var(--k2);
  display: flex; align-items: center; gap: var(--k2);
}
.anh-dai-dien {
  width: 28px; height: 28px; flex: 0 0 auto;
  border-radius: 999px;
  background: var(--chinh-nhat); color: var(--chinh);
  display: grid; place-items: center;
  font-size: var(--c2); font-weight: 700;
}
.ben-chan .ten-nd { font-size: var(--c3); font-weight: 600; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ben-chan .vai { font-size: var(--c1); color: var(--chu3); }

/* Thu gọn còn 56px — chỉ biểu tượng. Chữ bị ẩn bằng display:none chứ không
   bằng width:0: chữ rộng 0 vẫn tính vào chiều rộng tối thiểu của flex và làm
   biểu tượng lệch khỏi tâm. */
.thu-menu .ben-nhom,
.thu-menu .muc .nhan-muc,
.thu-menu .muc .dem,
.thu-menu .ben-dau .ten,
.thu-menu .ben-chan .thong-tin-nd { display: none; }
.thu-menu .muc { justify-content: center; padding: 0; }
.thu-menu .ben-dau { justify-content: center; padding: 0; }
.thu-menu .ben-chan { justify-content: center; }

/* Lớp phủ tối sau ngăn kéo — chỉ tồn tại ở màn hình hẹp.
   TÊN PHẢI LÀ .lop-phu, KHÔNG ĐƯỢC LÀ .phu. Đã có lúc lớp này tên .phu và
   trùng với .phu của dòng phụ dưới tiêu đề màn hình (dau()) — hậu quả là dòng
   "3 hội viên · kỳ thu 2026" biến thành một tấm màn mờ phủ kín toàn ứng dụng
   ở MỌI bề rộng, làm cả giao diện xám đi mà không ai chỉ ra được vì sao.
   Đây là lý do lớp dùng chung phải có tên riêng, không dùng lại tên tiện ích. */
.lop-phu {
  position: fixed; inset: 0;
  background: var(--lop-phu);
  z-index: 35;
  border: none; padding: 0; margin: 0;
  animation: hien var(--nhanh);
}

/* ── 6. Đầu màn hình & thẻ ─────────────────────────────────────────────────
   dau(tieuDe, phu, ...hanhDong): tiêu đề trái, nút hành động phải. Nút luôn
   dồn phải kể cả khi tiêu đề dài — nên dùng margin-left:auto chứ không
   space-between (space-between đẩy nút ra xa khi chỉ có một nút). */
.dau {
  display: flex; align-items: flex-start; gap: var(--k3);
  margin-bottom: var(--k4);
  flex-wrap: wrap;
}
.dau .tieu-de { font-size: var(--c6); font-weight: 600; line-height: 1.25; }
.dau .phu { font-size: var(--c3); color: var(--chu2); margin-top: 2px; }
.dau .hanh-dong { margin-left: auto; display: flex; gap: var(--k2); flex-wrap: wrap; align-items: center; }

.the {
  background: var(--the);
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  box-shadow: var(--bong);
}
.the + .the { margin-top: var(--k4); }
.the-dau {
  display: flex; align-items: center; gap: var(--k2);
  padding: var(--k3) var(--k4);
  border-bottom: 1px solid var(--vien);
  font-size: var(--c4); font-weight: 600;
}
.the-dau .hanh-dong { margin-left: auto; display: flex; gap: var(--k2); }
.the-than { padding: var(--k4); }
.the-chan {
  padding: var(--k3) var(--k4);
  border-top: 1px solid var(--vien);
  background: var(--chim);
  border-radius: 0 0 var(--bo) var(--bo);
  display: flex; gap: var(--k2); align-items: center;
}
/* Bảng nằm trong thẻ thì không cần đệm — viền bảng đã là viền thẻ. */
.the > .khung:first-child { border-radius: var(--bo) var(--bo) 0 0; }
.the > .khung:last-child  { border-radius: 0 0 var(--bo) var(--bo); }
.the > .khung:only-child  { border-radius: var(--bo); }

.hang { display: flex; align-items: center; gap: var(--k2); flex-wrap: wrap; }
.hang.doc { flex-direction: column; align-items: stretch; }
.hang.phai { justify-content: flex-end; }
.hang.giua { justify-content: center; }
.day { margin-left: auto; }

/* ── 7. Lưới & ô số liệu ───────────────────────────────────────────────────
   luoi() tự xuống dòng theo chiều rộng thật, không theo điểm ngắt cố định:
   cùng một lưới phải đẹp cả khi menu mở lẫn khi menu thu. */
.luoi {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--k4);
}
.luoi.chat { gap: var(--k3); }
.luoi.hai  { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }

.o-so {
  background: var(--the);
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  padding: var(--k3) var(--k4);
  box-shadow: var(--bong);
  min-width: 0;
}
.o-so-nhan {
  font-size: var(--c2); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--chu3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.o-so-gt {
  font-size: var(--c7); font-weight: 600; line-height: 1.2;
  margin-top: 2px;
}
.o-so-phu { font-size: var(--c2); color: var(--chu2); margin-top: 2px; }
.o-so.bam { cursor: pointer; }
.o-so.bam:hover { border-color: var(--vien-dam); }

/* ── 8. Bảng dữ liệu ───────────────────────────────────────────────────────
   BẪY QUAN TRỌNG — vì sao .khung dùng `overflow: auto` chứ không phải
   `overflow-x: auto`:
   Theo CSS, khai overflow một trục khác `visible` thì trục còn lại tự thành
   `auto`. Nghĩa là `overflow-x:auto` VẪN biến .khung thành hộp cuộn theo
   chiều dọc — và khi đó `position: sticky` của <thead> dính vào .khung chứ
   không dính vào trang. Nếu .khung cao vô hạn thì đầu bảng "dính" ở một chỗ
   không bao giờ khuất, tức là không dính gì cả.
   Cách chữa duy nhất mà không cần JS: cho .khung một chiều cao trần. Bảng tự
   cuộn cả hai chiều trong hộp của nó, đầu bảng dính vào mép trên hộp, và
   thân trang không bao giờ cuộn ngang. Màn hình nào cần bảng cao tự do thì
   thêm .cao-tu-do (và chấp nhận mất đầu bảng dính). */
.khung {
  overflow: auto;
  max-height: var(--cao-khung, calc(100dvh - 15rem));
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  background: var(--the);
  overscroll-behavior: contain;
}
.khung.cao-tu-do { max-height: none; overflow: visible; }
.the > .khung { border: none; }

.bang {
  width: 100%;
  border-collapse: separate;   /* 'collapse' làm viền của thead dính biến mất khi cuộn */
  border-spacing: 0;
  font-size: var(--c3);
}
.bang th, .bang td {
  padding: 0 var(--k3);
  height: var(--cao-dong);
  text-align: left;
  white-space: nowrap;         /* cho phép bảng rộng hơn khung rồi cuộn ngang */
  border-bottom: 1px solid var(--vien);
  vertical-align: middle;
}
.bang thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--the);
  height: 34px;
  font-size: var(--c2); font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--chu3);
  border-bottom: 1px solid var(--vien-dam);
  user-select: none;
}
.bang tbody tr:last-child td { border-bottom: none; }
.bang tbody tr:hover td { background: var(--chim); }
.bang tbody tr.bam { cursor: pointer; }
.bang tbody tr.chon td { background: var(--chinh-nhat); }
.bang td.phu  { color: var(--chu2); }
.bang td.tran { white-space: normal; min-width: 220px; }   /* cột mô tả dài */
.bang .canh-phai, .bang th.canh-phai { text-align: right; }
.bang .canh-giua, .bang th.canh-giua { text-align: center; }

/* Cột sắp xếp được: mũi tên chỉ hiện khi đang sắp theo cột đó, hoặc khi rê
   chuột lên — hiện mũi tên ở mọi cột làm đầu bảng nhiễu. */
.bang th.xep { cursor: pointer; }
.bang th.xep:hover { color: var(--chu); }
.bang th .mui { opacity: 0; margin-left: 4px; font-size: var(--c1); }
.bang th.xep:hover .mui { opacity: .5; }
.bang th.dang-xep { color: var(--chinh); }
.bang th.dang-xep .mui { opacity: 1; }

/* Cột dính bên trái (thường là cột tên) — giữ được ngữ cảnh khi cuộn ngang. */
.bang .dinh-trai { position: sticky; left: 0; z-index: 1; background: var(--the); }
.bang thead .dinh-trai { z-index: 3; }
.bang tbody tr:hover .dinh-trai { background: var(--chim); }

.bang-chan {
  display: flex; align-items: center; gap: var(--k3);
  padding: var(--k2) var(--k3);
  border-top: 1px solid var(--vien);
  font-size: var(--c2); color: var(--chu2);
}

/* ── 9. Chip trạng thái & thanh tiến độ ────────────────────────────────────
   Sáu màu, cố định. Màn hình KHÔNG BAO GIỜ tự chế màu hay nhãn trạng thái —
   chipTT() tra từ bộ khung. Mỗi cặp nền/chữ đều >= 4.5:1 ở cả hai chế độ. */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  height: 20px; padding: 0 8px;
  border-radius: 999px;
  font-size: var(--c2); font-weight: 600; line-height: 1;
  white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.chip::before {
  content: ''; flex: 0 0 auto;
  width: 5px; height: 5px; border-radius: 999px;
  background: currentColor;
}
.chip.khong-cham::before { display: none; }
.chip.trung_tinh { background: var(--trung-tinh-nhat); color: var(--trung-tinh); }
.chip.cho        { background: var(--cho-nhat);        color: var(--cho); }
.chip.dang       { background: var(--tin-nhat);        color: var(--tin); }
.chip.tot        { background: var(--tot-nhat);        color: var(--tot); }
.chip.canh       { background: var(--canh-nhat);       color: var(--canh); }
.chip.loi        { background: var(--loi-nhat);        color: var(--loi); }

.thanh {
  height: 6px; border-radius: 999px;
  background: var(--chim);
  overflow: hidden;
  min-width: 60px;
}
.thanh > i {
  display: block; height: 100%;
  background: var(--chinh);
  border-radius: 999px;
  transition: width var(--nhanh);
}
.thanh.canh > i { background: var(--canh); }
.thanh.loi  > i { background: var(--loi); }

/* ── 10. Nút ───────────────────────────────────────────────────────────────
   Cao 32px để thẳng hàng với ô nhập. Nút chính chỉ MỘT trên mỗi vùng — hai
   nút xanh cạnh nhau thì không còn nút nào là chính. */
.nut {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--cao-o); padding: 0 var(--k3);
  border: 1px solid var(--vien-dam);
  border-radius: var(--bo);
  background: var(--the);
  color: var(--chu);
  font-family: inherit; font-size: var(--c3); font-weight: 500;
  cursor: pointer; white-space: nowrap; user-select: none;
  transition: background var(--nhanh), border-color var(--nhanh);
}
.nut:hover { background: var(--chim); }
.nut:active { background: var(--vien); }
.nut[disabled], .nut.tat { opacity: .5; cursor: not-allowed; pointer-events: none; }

.nut.chinh {
  background: var(--chinh); border-color: var(--chinh); color: var(--chinh-chu);
}
.nut.chinh:hover  { background: var(--chinh-dam); border-color: var(--chinh-dam); }
.nut.chinh:active { background: var(--chinh-dam); }

.nut.nguy {
  background: var(--the); border-color: var(--vien-dam); color: var(--loi);
}
.nut.nguy:hover { background: var(--loi-nhat); border-color: var(--loi); }

.nut.phang { border-color: transparent; background: none; color: var(--chu2); }
.nut.phang:hover { background: var(--chim); color: var(--chu); }

.nut.nho { height: 26px; padding: 0 8px; font-size: var(--c2); }
.nut.bt  { width: var(--cao-o); padding: 0; }
.nut.bt.nho { width: 26px; }
.nut.rong { width: 100%; }

.nhom-nut { display: inline-flex; }
.nhom-nut .nut { border-radius: 0; margin-left: -1px; }
.nhom-nut .nut:first-child { border-radius: var(--bo) 0 0 var(--bo); margin-left: 0; }
.nhom-nut .nut:last-child  { border-radius: 0 var(--bo) var(--bo) 0; }
.nhom-nut .nut.hien { background: var(--chinh-nhat); color: var(--chinh); border-color: var(--chinh); z-index: 1; }

/* ── 11. Biểu mẫu ──────────────────────────────────────────────────────────
   Nhãn ở TRÊN ô nhập, không ở bên trái: nhãn tiếng Việt dài ngắn chênh nhau
   nhiều ("Họ tên" vs "Số chứng chỉ hành nghề"), đặt bên trái thì hoặc cột
   nhãn rộng phí hoặc chữ bị xuống dòng lô nhô. */
.form { display: grid; gap: var(--k3); }
.form-luoi {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--k3);
}
/* align-content: start là BẮT BUỘC, không phải để cho đẹp.
   .truong là lưới con nằm trong lưới .form-luoi. Mặc định của align-content
   trong lưới là "stretch", nên khi một ô cùng hàng có thêm dòng gợi ý, cả
   hàng cao lên và phần dư được CHIA ĐỀU cho các dòng của .truong bên cạnh —
   ô nhập phình từ 32px lên 43px, và hai hàng liền nhau cao khác nhau tuỳ ô
   nào có gợi ý. Với biểu mẫu hội viên 20 trường thì lưới trông xộc xệch mà
   không ai chỉ ra được luật CSS nào gây ra. */
.truong { display: grid; gap: 4px; min-width: 0; align-content: start; }
.truong.rong-2 { grid-column: 1 / -1; }
.truong > label {
  font-size: var(--c2); font-weight: 600; color: var(--chu2);
}
.truong > label .sao { color: var(--loi); margin-left: 2px; }
.truong .goi-y { font-size: var(--c2); color: var(--chu3); }
.truong .loi-truong { font-size: var(--c2); color: var(--loi); font-weight: 500; }

.o, input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=time], input[type=search], select, textarea {
  width: 100%;
  min-height: var(--cao-o);
  padding: 5px var(--k2);
  border: 1px solid var(--vien-dam);
  border-radius: var(--bo);
  background: var(--the);
  color: var(--chu);
  font-family: inherit; font-size: var(--c4);
  line-height: 1.4;
}
textarea { min-height: 84px; resize: vertical; line-height: 1.5; }
select { appearance: none; padding-right: var(--k5); cursor: pointer;
  /* Mũi tên vẽ bằng gradient để không phải nhúng ảnh nền có mã màu. */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--chu3) 50%),
    linear-gradient(135deg, var(--chu3) 50%, transparent 50%);
  background-position: calc(100% - 15px) 55%, calc(100% - 10px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.o:hover, input:hover, select:hover, textarea:hover { border-color: var(--chu3); }
.o:disabled, input:disabled, select:disabled, textarea:disabled {
  background: var(--chim); color: var(--chu3); cursor: not-allowed;
}
input::placeholder, textarea::placeholder { color: var(--chu3); }
.truong.hong .o, .truong.hong input, .truong.hong select, .truong.hong textarea {
  border-color: var(--loi);
}

/* Ô tiền/số: chữ phải, cột thẳng hàng ngay cả khi đang gõ. */
.o.tien, input.tien, .o.so-nhap, input.so-nhap { text-align: right; font-variant-numeric: tabular-nums; }

/* Ô có đơn vị hoặc biểu tượng đứng cạnh */
.o-ghep { display: flex; align-items: stretch; }
.o-ghep > .o, .o-ghep > input { border-radius: var(--bo) 0 0 var(--bo); }
.o-ghep > .duoi-to {
  display: grid; place-items: center;
  padding: 0 var(--k2);
  border: 1px solid var(--vien-dam); border-left: none;
  border-radius: 0 var(--bo) var(--bo) 0;
  background: var(--chim); color: var(--chu2);
  font-size: var(--c3); white-space: nowrap;
}

/* Công tắc bool — to bằng ngón tay nhưng không chiếm chiều cao thêm. */
.cong-tac { display: inline-flex; align-items: center; gap: var(--k2); cursor: pointer; user-select: none; }
.cong-tac input { position: absolute; opacity: 0; width: 0; height: 0; }
.cong-tac .lan {
  width: 34px; height: 20px; flex: 0 0 auto;
  border-radius: 999px; background: var(--vien-dam);
  position: relative; transition: background var(--nhanh);
}
.cong-tac .lan::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 999px;
  background: var(--the); box-shadow: var(--bong);
  transition: transform var(--nhanh);
}
.cong-tac input:checked + .lan { background: var(--chinh); }
.cong-tac input:checked + .lan::after { transform: translateX(14px); }
.cong-tac input:focus-visible + .lan { outline: 2px solid var(--chinh); outline-offset: 2px; }

/* Ô chọn bản ghi (khoá ngoại) — ô nhập + danh sách thả xuống có tìm kiếm. */
.chon-bg { position: relative; }
.chon-ds {
  position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% + 2px);
  max-height: 260px; overflow-y: auto;
  background: var(--noi);
  border: 1px solid var(--vien-dam);
  border-radius: var(--bo);
  box-shadow: var(--bong-noi);
  padding: var(--k1);
  animation: truot-xuong var(--nhanh);
}
.chon-ds .dong-chon {
  padding: 6px var(--k2);
  border-radius: var(--bo-nho);
  font-size: var(--c3);
  cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chon-ds .dong-chon:hover, .chon-ds .dong-chon.hien { background: var(--chim); }
.chon-ds .dong-chon .phu { color: var(--chu3); font-size: var(--c2); }
.chon-ds .trong-chon { padding: var(--k2); color: var(--chu3); font-size: var(--c2); }

/* Nhiều lựa chọn — mỗi lựa chọn là một thẻ gỡ được. */
.the-chon {
  display: inline-flex; align-items: center; gap: 4px;
  height: 22px; padding: 0 4px 0 8px;
  border-radius: var(--bo-nho);
  background: var(--chinh-nhat); color: var(--chinh);
  font-size: var(--c2); font-weight: 500;
}
.the-chon button {
  border: none; background: none; cursor: pointer; color: inherit;
  font-size: var(--c3); line-height: 1; padding: 2px;
}

/* Vùng thả tệp */
.vung-tep {
  border: 1px dashed var(--vien-dam);
  border-radius: var(--bo);
  padding: var(--k4);
  text-align: center;
  color: var(--chu2); font-size: var(--c3);
  cursor: pointer;
}
.vung-tep:hover, .vung-tep.keo { border-color: var(--chinh); background: var(--chinh-nhat); }

.form-chan {
  display: flex; gap: var(--k2); align-items: center;
  padding-top: var(--k3);
  border-top: 1px solid var(--vien);
  margin-top: var(--k1);
}

/* Thanh lọc trên đầu bảng */
.thanh-loc {
  display: flex; flex-wrap: wrap; gap: var(--k2); align-items: center;
  margin-bottom: var(--k3);
}
.thanh-loc .o-tim { max-width: 280px; }
.thanh-loc select, .thanh-loc .o { width: auto; min-width: 150px; }

/* ── 12. Hộp thoại & thông báo nổi ─────────────────────────────────────────
   Hoạt ảnh chỉ để phản hồi thao tác, <= 150ms. Không có hiệu ứng "nảy". */
.nen-hop {
  position: fixed; inset: 0; z-index: 100;
  background: var(--lop-phu);
  display: grid; place-items: center;
  padding: var(--k4);
  animation: hien var(--nhanh);
}
.hop {
  width: min(560px, 100%);
  max-height: calc(100dvh - 2 * var(--k4));
  display: flex; flex-direction: column;
  background: var(--the);
  border: 1px solid var(--vien);
  border-radius: var(--bo-lon);
  box-shadow: var(--bong-noi);
  animation: len var(--nhanh);
}
.hop.rong  { width: min(880px, 100%); }
.hop.hep   { width: min(400px, 100%); }
.hop-dau {
  display: flex; align-items: center; gap: var(--k2);
  padding: var(--k3) var(--k4);
  border-bottom: 1px solid var(--vien);
  font-size: var(--c5); font-weight: 600;
  flex: 0 0 auto;
}
.hop-dau .dong { margin-left: auto; }
.hop-than { padding: var(--k4); overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.hop-chan {
  display: flex; gap: var(--k2); justify-content: flex-end; align-items: center;
  padding: var(--k3) var(--k4);
  border-top: 1px solid var(--vien);
  flex: 0 0 auto;
}
/* Khoá cuộn nền khi hộp thoại mở — chung.js gắn lớp này vào <body>. */
body.khoa-cuon { overflow: hidden; }

.khay-bao {
  position: fixed; top: var(--k3); right: var(--k3); z-index: 200;
  display: flex; flex-direction: column; gap: var(--k2);
  pointer-events: none;
  max-width: min(380px, calc(100vw - 2 * var(--k3)));
}
.bao {
  display: flex; align-items: flex-start; gap: var(--k2);
  padding: var(--k2) var(--k3);
  background: var(--noi);
  border: 1px solid var(--vien-dam);
  border-left: 3px solid var(--chu3);
  border-radius: var(--bo);
  box-shadow: var(--bong-noi);
  font-size: var(--c3);
  pointer-events: auto;
  animation: truot-trai var(--nhanh);
}
.bao.di { animation: tat var(--nhanh) forwards; }
.bao.tot { border-left-color: var(--tot); }
.bao.loi { border-left-color: var(--loi); }
.bao.tin { border-left-color: var(--tin); }
.bao.canh { border-left-color: var(--canh); }
.bao .dong { margin-left: auto; border: none; background: none; cursor: pointer;
  color: var(--chu3); font-size: var(--c4); line-height: 1; padding: 2px; }

/* ── 13. Trạng thái rỗng / đang tải / lỗi ──────────────────────────────────
   Ba trạng thái này bị bỏ quên nhiều nhất, và là ba trạng thái Văn phòng gặp
   nhiều nhất trong tuần đầu — lúc chưa có dữ liệu nào. */
.trong {
  display: grid; place-items: center; gap: var(--k2);
  padding: var(--k6) var(--k4);
  text-align: center;
  color: var(--chu2);
}
.trong .bt-trong {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: var(--bo);
  background: var(--chim); color: var(--chu3);
}
.trong .tieu-de-trong { font-size: var(--c4); font-weight: 600; color: var(--chu); }
.trong .goi-y-trong { font-size: var(--c3); max-width: 42ch; }

.bao-loi {
  display: flex; align-items: flex-start; gap: var(--k2);
  padding: var(--k2) var(--k3);
  background: var(--loi-nhat);
  border: 1px solid var(--loi);
  border-radius: var(--bo);
  color: var(--loi);
  font-size: var(--c3); font-weight: 500;
  margin-bottom: var(--k3);
}
.bao-loi.canh { background: var(--canh-nhat); border-color: var(--canh); color: var(--canh); }
.bao-loi.tin  { background: var(--tin-nhat);  border-color: var(--tin);  color: var(--tin); }

/* Khung xương chờ. Không dùng spinner: spinner nói "đang chờ", khung xương
   nói "sắp có một bảng ở đây" — mắt đỡ giật khi dữ liệu về. */
.xuong {
  background: var(--chim);
  border-radius: var(--bo-nho);
  height: 12px;
  animation: tho 1.2s ease-in-out infinite;
}
.dang-tai { display: grid; gap: var(--k2); padding: var(--k3); }
.dang-tai .xuong:nth-child(2n) { opacity: .7; }

.quay {
  width: 14px; height: 14px; flex: 0 0 auto;
  border: 2px solid var(--vien-dam);
  border-top-color: var(--chinh);
  border-radius: 999px;
  animation: xoay .6s linear infinite;
}

/* ── 14. Phân trang & phụ trợ ──────────────────────────────────────────────*/
.phan-trang {
  display: flex; align-items: center; gap: var(--k2);
  padding: var(--k3) 0 0;
  font-size: var(--c3); color: var(--chu2);
  flex-wrap: wrap;
}
.phan-trang .so-trang { margin-left: auto; display: flex; gap: 4px; align-items: center; }

/* .phu là tiện ích "chữ phụ" dùng ở mọi nơi (dòng dưới tiêu đề, ô bảng mờ,
   dòng phụ trong danh sách chọn). Khai một luật gốc để màn hình nào gắn .phu
   trần cũng ra chữ mờ — chứ không ra một hành vi bất ngờ nào khác. */
.phu { color: var(--chu2); }
.nhan-phu { font-size: var(--c2); color: var(--chu3); }
.manh { color: var(--chu2); }
.dam { font-weight: 600; }
.cat-1dong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an { display: none !important; }
.chi-doc-man { color: var(--chu3); font-style: italic; }

/* Danh sách mô tả cho màn hình chi tiết: nhãn trái, giá trị phải. */
.mo-ta { display: grid; grid-template-columns: minmax(140px, 200px) 1fr; gap: var(--k2) var(--k3); font-size: var(--c3); }
.mo-ta dt { color: var(--chu3); font-weight: 500; }
.mo-ta dd { margin: 0; color: var(--chu); }

/* Nội dung soạn thảo đã làm sạch (noiDungHtml). Bọc trong .noi-dung để bài
   viết không kéo theo kiểu chữ của bảng biểu xung quanh. */
.noi-dung { font-size: var(--c4); line-height: 1.65; color: var(--chu); max-width: 74ch; }
.noi-dung h1, .noi-dung h2, .noi-dung h3, .noi-dung h4 { margin: var(--k4) 0 var(--k2); }
.noi-dung p { margin: 0 0 var(--k3); }
.noi-dung ul, .noi-dung ol { margin: 0 0 var(--k3); padding-left: var(--k5); }
.noi-dung li { margin-bottom: var(--k1); }
.noi-dung img { max-width: 100%; height: auto; border-radius: var(--bo); }
.noi-dung blockquote {
  margin: 0 0 var(--k3); padding: var(--k2) var(--k3);
  border-left: 3px solid var(--chinh);
  background: var(--chim); color: var(--chu2);
}
.noi-dung table { width: 100%; border-collapse: collapse; margin-bottom: var(--k3); font-size: var(--c3); }
.noi-dung th, .noi-dung td { border: 1px solid var(--vien); padding: 6px var(--k2); text-align: left; }
.noi-dung th { background: var(--chim); font-weight: 600; }

/* ══════════════════════════════════════════════════════════════════════════
   17. MƯỜI LỚP TỪNG CHẾT
   Mười lớp dưới đây đã được các tệp man-*.js phát ra từ đầu nhưng app.css
   chưa có luật nào — nghĩa là mười chỗ trên màn hình trông như "chưa làm
   xong" mà không ai tra ra vì sao. Nặng nhất: kéo thả trên bảng kanban công
   việc HOÀN TOÀN KHÔNG CÓ PHẢN HỒI THỊ GIÁC — thẻ không mờ đi, cột đích
   không sáng lên, người dùng thả xuống rồi mới biết mình vừa làm gì.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 17.1 Dải bước hồ sơ (man-ho-so.js › .dai-buoc) ────────────────────────
   Bảy bước của Điều 7. Các chip đã có màu riêng; việc của lớp này là nối
   chúng thành một DẢI có chiều, để mắt đọc ra "đang ở bước 4/7" chứ không
   phải bảy nhãn rời rạc. */
.dai-buoc { align-items: center; row-gap: var(--k1); }
/* Mũi nối giữa hai chip. Dùng ::after của chip SAU chứ không thêm phần tử —
   man-ho-so.js dựng DOM, CSS không được đòi nó thêm thẻ. */
.dai-buoc > .chip:not(:first-child) { position: relative; margin-left: 10px; }
.dai-buoc > .chip:not(:first-child)::after {
  content: '›';
  position: absolute; left: -11px; top: 50%; transform: translateY(-50%);
  color: var(--chu3); font-weight: 400; font-size: var(--c3);
}
/* Bước đang đứng: viền ngoài để nổi hẳn khỏi các bước đã qua. */
.dai-buoc > .chip.dang { outline: 1px solid var(--tin); outline-offset: 1px; }

/* ── 17.2 Cột kanban hồ sơ (man-ho-so.js › .cot-buoc) ──────────────────────*/
.cot-buoc {
  background: var(--chim);
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  padding: var(--k2);
  /* Cột dài hơn màn hình thì cuộn TRONG cột, không kéo dài cả bảng kanban —
     sáu cột cao bằng nhau thì mới so sánh được số hồ sơ ở mỗi bước. */
  max-height: calc(100dvh - 18rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.cot-buoc > .the { margin-bottom: var(--k2); }
.cot-buoc > .the:last-child { margin-bottom: 0; }
.cot-buoc .the + .the { margin-top: 0; }   /* đã có margin-bottom, đừng cộng dồn */

/* ── 17.3 Dòng thời gian (chung.js › dongThoiGian, man-hoi-vien.js) ────────
   Phải chạy đúng với CẢ HAI cách dựng: <ol><li class="muc-tg"> của chung.js
   và <div class="dong-thoi-gian"><div class="muc-tg hang"> của man-hoi-vien.
   Vì bản trong man-hoi-vien đặt `padding` bằng style nội tuyến (thắng mọi
   luật ở đây), cái chấm mốc phải định vị TUYỆT ĐỐI từ lề trái của khung,
   không dựa vào padding của từng mục. */
.dong-thoi-gian {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0 0 0 var(--k5);
}
.dong-thoi-gian::before {
  content: '';
  position: absolute; left: 5px; top: 10px; bottom: 10px;
  width: 2px; background: var(--vien);
}
.muc-tg { position: relative; }
.muc-tg::before {
  content: '';
  position: absolute; left: calc(-1 * var(--k5) + 1px); top: 13px;
  width: 10px; height: 10px; border-radius: 999px;
  background: var(--the);
  border: 2px solid var(--vien-dam);
}
/* Màu mốc theo sáu màu chip — cùng bảng màu với chipTT, không phát minh thêm. */
.muc-tg.tot::before        { border-color: var(--tot); }
.muc-tg.canh::before       { border-color: var(--canh); }
.muc-tg.loi::before        { border-color: var(--loi); }
.muc-tg.dang::before       { border-color: var(--tin); }
.muc-tg.cho::before        { border-color: var(--cho); }
.muc-tg.trung_tinh::before { border-color: var(--trung-tinh); }

.dong-thoi-gian > li.muc-tg {
  display: flex; align-items: flex-start; gap: var(--k3);
  padding: var(--k2) 0;
}
.muc-tg + .muc-tg { border-top: 1px solid var(--vien); }
.tg-luc {
  flex: 0 0 auto; min-width: 92px;
  font-size: var(--c2); color: var(--chu3);
  font-variant-numeric: tabular-nums;
}
.tg-luc .nhan-phu { display: block; }
.tg-noi { min-width: 0; flex: 1 1 auto; }
.tg-noi > a { font-weight: 600; }

/* ── 17.4 Kéo thả kanban công việc (man-cong-viec.js) ──────────────────────
   .keo-duoc  thẻ có thể kéo
   .dang-keo  thẻ đang được kéo đi
   .cho-tha   cột đang là đích thả
   Đây là ba lớp quan trọng nhất trong mục 17: thiếu chúng, thao tác kéo thả
   của cả phân hệ Công việc không có một tín hiệu nào. */
.keo-duoc { cursor: grab; }
.keo-duoc:active { cursor: grabbing; }
.keo-duoc:hover { border-color: var(--vien-dam); box-shadow: var(--bong-noi); }

.dang-keo {
  opacity: .4;
  /* Viền nét đứt trong lúc kéo: bản thân con trỏ đã mang ảnh thẻ, nên chỗ cũ
     cần trông như MỘT Ô TRỐNG CÒN GIỮ CHỖ, không phải một thẻ bình thường. */
  border-style: dashed;
  cursor: grabbing;
}

/* .cho-tha đặt trên cả cột (một .the). Dùng outline chứ không border: border
   làm cột rộng thêm 2px và cả hàng kanban xô ngang mỗi lần rê qua. */
.cho-tha {
  outline: 2px dashed var(--chinh);
  outline-offset: -2px;
  background: var(--chinh-nhat);
}
.cho-tha .the-dau { border-bottom-color: var(--chinh); }

/* ── 17.5 Khối soạn công văn (man-van-ban.js › .khoi-soan/.thanh-soan) ─────*/
.khoi-soan {
  border: 1px solid var(--vien-dam);
  border-radius: var(--bo);
  background: var(--the);
  overflow: hidden;
}
.khoi-soan .vung-soan {
  border: none;                     /* viền đã nằm ở .khoi-soan */
  border-radius: 0;
}
.khoi-soan .vung-soan:focus-visible { outline-offset: -2px; }
.thanh-soan {
  gap: var(--k1);
  padding: var(--k1) var(--k2);
  background: var(--chim);
  border-bottom: 1px solid var(--vien);
  /* Thanh công cụ dính lại khi cuộn trong ô soạn dài: công văn 3 trang mà
     phải cuộn ngược lên đầu mới bấm được nút Đậm là không dùng được. */
  position: sticky; top: 0; z-index: 2;
  margin-bottom: 0 !important;      /* thắng style nội tuyến marginBottom cũ */
}
.thanh-soan .nut.nho { min-width: 28px; }

/* ── 17.6 Mã QR: ĐEN TRÊN TRẮNG, KỂ CẢ Ở NỀN TỐI ──────────────────────────
   Đây là ngoại lệ DUY NHẤT của luật "mọi màu đi qua biến", và nó có lý do
   vật lý chứ không phải thẩm mỹ:
     · máy quét đọc mã ĐẢO MÀU rất thất thường — có máy được, có máy không,
       và hội viên đứng ở quầy lễ tân không hiểu vì sao mã của mình "hỏng";
     · thẻ hội viên còn được IN RA GIẤY, mà giấy thì luôn trắng.
   Hai lớp này ghim màu tuyệt đối, thắng thuộc tính fill mà man-cong-hoi-vien
   đặt sẵn (var(--chu-dao)/var(--chu)) — vốn sẽ tự đảo màu ở nền tối. */
.ma-qr .o-nen { fill: #ffffff; }
.ma-qr .o-toi { fill: #000000; }

/* ══════════════════════════════════════════════════════════════════════════
   18. SỬA TƯƠNG PHẢN ĐÃ ĐO
   .nhan-phu là chữ mờ dành cho NỀN TRANG. Đặt nó lên một nền đặc thì nó giữ
   nguyên màu --chu3 và gần như biến mất: số mục của nhóm danh mục đang chọn
   (nút .nut.rong.chinh) đo được 1,06:1 ở nền tối và 1,23:1 ở nền sáng —
   ngưỡng là 4,5:1. Con số biến mất đúng ở nhóm người dùng đang xem.
   ══════════════════════════════════════════════════════════════════════════ */
.nut.chinh .nhan-phu { color: var(--chinh-chu); }
.nut.nguy  .nhan-phu { color: var(--loi); }
.muc.hien  .nhan-phu { color: var(--chinh); }
.chip .nhan-phu      { color: inherit; }

/* ══════════════════════════════════════════════════════════════════════════
   19. BỘ CÔNG CỤ MỚI (§A phụ lục đợt 2)
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 19.1 Đường bỏ qua menu ────────────────────────────────────────────────
   Vô hình cho tới khi nhận tiêu điểm bàn phím. KHÔNG dùng display:none —
   phần tử display:none không nhận được tiêu điểm, tức là liên kết không bao
   giờ hiện ra và tính năng coi như không tồn tại. */
.bo-qua {
  position: fixed; top: var(--k2); left: var(--k2); z-index: 300;
  transform: translateY(-200%);
  padding: var(--k2) var(--k3);
  background: var(--chinh); color: var(--chinh-chu);
  border-radius: var(--bo);
  box-shadow: var(--bong-noi);
  font-size: var(--c3); font-weight: 600;
  transition: transform var(--nhanh);
}
.bo-qua:focus { transform: none; text-decoration: none; }

/* ── 19.1b Nhịp đổi nền ────────────────────────────────────────────────────
   app.js gắn .doi-nen vào <html> trong đúng một khung hình khi đổi nền
   sáng/tối. Vì sao cần: `.nut { transition: background 120ms }` lấy màu từ
   biến --chinh; khi cả bảng màu đổi cùng lúc, trình duyệt KHÔNG khởi động
   lại hoạt ảnh cho kiểu thay đổi đó và nút giữ nguyên màu cũ — đã đo: nút
   chính vẫn là xanh đậm của nền sáng giữa một giao diện đã tối hẳn. */
html.doi-nen, html.doi-nen *, html.doi-nen *::before, html.doi-nen *::after {
  transition: none !important;
}

/* ── 19.2 Dải tiến trình ───────────────────────────────────────────────────*/
.tien-trinh {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  z-index: 250;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--nhanh);
  overflow: hidden;
}
.tien-trinh.chay { opacity: 1; }
.tien-trinh > i {
  display: block; height: 100%; width: 40%;
  background: var(--chinh);
  /* Chạy vô định thay vì hiện phần trăm: fetch không báo tiến độ tải xuống,
     nên một thanh "62%" ở đây sẽ là con số bịa. */
  animation: chay-ngang 1.1s ease-in-out infinite;
}
@keyframes chay-ngang {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* ── 19.3 Thẻ (tabs) ───────────────────────────────────────────────────────*/
.nhom-the {
  display: flex; gap: var(--k1);
  border-bottom: 1px solid var(--vien);
  margin-bottom: var(--k3);
  overflow-x: auto;
  scrollbar-width: thin;
}
.the-tab {
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 var(--k3);
  border: none; background: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--chu2);
  font-family: inherit; font-size: var(--c3); font-weight: 500;
  white-space: nowrap; cursor: pointer;
}
.the-tab:hover { color: var(--chu); background: var(--chim); }
.the-tab.hien {
  color: var(--chinh); font-weight: 600;
  border-bottom-color: var(--chinh);
}
.dem-tab {
  font-size: var(--c1); font-weight: 600;
  background: var(--chim); color: var(--chu2);
  border-radius: 999px; padding: 0 6px; min-width: 18px; text-align: center;
}
.the-tab.hien .dem-tab { background: var(--chinh-nhat); color: var(--chinh); }
.the-tab-than:focus-visible { outline-offset: 4px; }

/* ── 19.4 Ngăn kéo ─────────────────────────────────────────────────────────*/
.nen-keo {
  position: fixed; inset: 0; z-index: 100;
  background: var(--lop-phu);
  animation: hien var(--nhanh);
}
.ngan-keo {
  position: absolute; top: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column;
  background: var(--the);
  border-left: 1px solid var(--vien);
  box-shadow: var(--bong-noi);
  animation: truot-vao var(--nhanh);
}
.ngan-keo.di { animation: truot-ra var(--nhanh) forwards; }
.keo-than { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--k4); }
.ngan-keo > .hop-dau { flex: 0 0 auto; }
.ngan-keo > .hop-chan { flex: 0 0 auto; background: var(--chim); }
@keyframes truot-vao { from { transform: translateX(100%); } }
@keyframes truot-ra  { to   { transform: translateX(100%); } }

/* ── 19.5 Vùng thả tệp & danh sách tệp ─────────────────────────────────────*/
.vung-tep:focus-visible { outline-offset: 2px; }
.ds-tep { display: grid; gap: var(--k1); margin-top: var(--k2); }
.dong-tep {
  display: flex; align-items: center; gap: var(--k2); flex-wrap: wrap;
  padding: 6px var(--k2);
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  background: var(--the);
  font-size: var(--c3);
}
.dong-tep.hong { border-color: var(--loi); background: var(--loi-nhat); }
.dong-tep .ten-tep { flex: 1 1 160px; min-width: 0; }
.dong-tep .thanh { flex: 1 1 100%; height: 4px; }
.dong-tep .loi-truong { flex: 1 1 100%; }

/* ── 19.6 Nhóm ô gập được trong biểu mẫu ───────────────────────────────────*/
.form-than { display: grid; gap: var(--k3); }
details.nhom-o {
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  background: var(--the);
}
details.nhom-o > summary {
  display: flex; align-items: center; gap: var(--k2);
  padding: var(--k2) var(--k3);
  font-size: var(--c3); font-weight: 600;
  cursor: pointer; user-select: none;
  list-style: none;                 /* bỏ tam giác mặc định của Firefox */
  border-radius: var(--bo);
}
details.nhom-o > summary::-webkit-details-marker { display: none; }
details.nhom-o > summary::before {
  content: '›';
  color: var(--chu3); font-weight: 400;
  transition: transform var(--nhanh);
}
details.nhom-o[open] > summary::before { transform: rotate(90deg); }
details.nhom-o[open] > summary { border-bottom: 1px solid var(--vien); border-radius: var(--bo) var(--bo) 0 0; }
details.nhom-o > summary:hover { background: var(--chim); }
details.nhom-o > .form-luoi { padding: var(--k3); }

/* ── 19.7 Bảng: cột chọn, dòng tổng, tay kéo bề rộng ───────────────────────*/
.bang th.o-chon, .bang td.o-chon { width: 34px; padding: 0 0 0 var(--k2); }
.bang td.o-chon input, .bang th.o-chon input { cursor: pointer; margin: 0; }

.bang tfoot .dong-tong td {
  position: sticky; bottom: 0; z-index: 2;
  background: var(--chim);
  border-top: 1px solid var(--vien-dam);
  border-bottom: none;
  font-weight: 600;
}

/* Tay kéo đổi bề rộng cột. Rộng 8px nhưng chỉ vẽ một vạch 1px: vùng bấm phải
   to hơn vạch nhìn thấy, nếu không thì phải nhắm rất chính xác mới túm được. */
.keo-cot {
  position: absolute; top: 0; right: -4px; bottom: 0;
  width: 8px; cursor: col-resize;
  z-index: 3;
}
.keo-cot::after {
  content: ''; position: absolute; top: 6px; bottom: 6px; left: 3px;
  width: 1px; background: transparent;
}
.bang th:hover .keo-cot::after { background: var(--vien-dam); }
/* .keo-cot định vị tuyệt đối theo ô đầu bảng — chạy được vì `.bang thead th`
   ở §8 đã có position:sticky, vốn cũng là một khối chứa. */
body.dang-keo-cot { cursor: col-resize; user-select: none; }

.ds-cot { display: grid; gap: var(--k2); }

/* ── 19.8 Chọn khoảng ngày ─────────────────────────────────────────────────*/
.khoang-ngay input[type=date] { width: auto; min-width: 140px; }

/* ── 19.9 Bảng lệnh (Ctrl+K) ───────────────────────────────────────────────*/
.bang-lenh { display: grid; gap: var(--k2); }
.bang-lenh > .o { height: 40px; font-size: var(--c5); }
.bang-lenh-ds {
  max-height: min(52dvh, 420px);
  overflow-y: auto;
  scrollbar-width: thin;
  margin: 0 calc(-1 * var(--k2));
  padding: 0 var(--k2);
}
.bang-lenh-ds .dong-chon {
  padding: 6px var(--k2);
  border-radius: var(--bo-nho);
  cursor: pointer;
  white-space: normal;
}
.bang-lenh-ds .dong-chon.hien { background: var(--chinh-nhat); }

/* Tiêu đề nhóm trong mọi trình đơn thả — thay cho style nội tuyến rải rác. */
.dau-tha {
  padding: 6px var(--k2) 2px;
  font-size: var(--c2); font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--chu3);
}

/* ── 19.10 Ảnh đại diện ────────────────────────────────────────────────────
   Tám màu m0…m7 KHÔNG phải tám màu mới: chúng dùng lại đúng sáu cặp màu chip
   cộng màu thương hiệu và màu chữ phụ — những cặp đã đo đạt 4,5:1 ở cả hai
   nền. Thêm tám cặp hex mới là thêm tám thứ phải đo lại mỗi lần đổi bảng màu. */
.anh-dai-dien {
  position: relative;
  overflow: hidden;
  flex: 0 0 auto;
  border: none; padding: 0;
  font-weight: 700;
  line-height: 1;
}
.anh-dai-dien img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.anh-dai-dien.bam { cursor: pointer; }
.anh-dai-dien.bam:hover { filter: brightness(.92); }
.anh-dai-dien .chu-dau { user-select: none; }
.anh-dai-dien.m0 { background: var(--chinh-nhat);      color: var(--chinh); }
.anh-dai-dien.m1 { background: var(--tot-nhat);        color: var(--tot); }
.anh-dai-dien.m2 { background: var(--tin-nhat);        color: var(--tin); }
.anh-dai-dien.m3 { background: var(--canh-nhat);       color: var(--canh); }
.anh-dai-dien.m4 { background: var(--loi-nhat);        color: var(--loi); }
.anh-dai-dien.m5 { background: var(--cho-nhat);        color: var(--cho); }
.anh-dai-dien.m6 { background: var(--trung-tinh-nhat); color: var(--trung-tinh); }
.anh-dai-dien.m7 { background: var(--chim);            color: var(--chu2); }

/* ── 19.11 Khung cắt ảnh ───────────────────────────────────────────────────*/
.cat-anh-hop { display: grid; gap: var(--k3); justify-items: center; }
.cat-khung {
  position: relative;
  overflow: hidden;
  border-radius: var(--bo);
  background: var(--chim);
  border: 1px solid var(--vien-dam);
  cursor: grab;
  /* touch-action:none là BẮT BUỘC cho Pointer Events trên cảm ứng: không có
     nó thì trình duyệt nuốt cử chỉ để cuộn trang, và pointermove ngừng bắn
     ngay giữa lúc người dùng đang kéo ảnh. */
  touch-action: none;
  user-select: none;
}
.cat-khung.cat-keo { cursor: grabbing; }
.cat-anh {
  position: absolute; top: 50%; left: 50%;
  max-width: none;                  /* thắng luật img{max-width:100%} chung */
  pointer-events: none;             /* kéo là việc của khung, không của ảnh */
}
/* Vòng tròn hướng dẫn: cho thấy phần ảnh sẽ được giữ lại. Vẽ bằng box-shadow
   toả rộng nên không cần thêm một phần tử phủ nào. */
.cat-khung::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: 999px;
  box-shadow: 0 0 0 9999px var(--lop-phu);
  pointer-events: none;
}
.cat-truot { flex: 1 1 auto; }

/* ── 19.12 Trình xem tệp ───────────────────────────────────────────────────*/
.xem-tep {
  position: fixed; inset: 0; z-index: 90;
  display: flex; flex-direction: column;
  background: var(--nen);
  animation: hien var(--nhanh);
}
.xt-thanh {
  display: flex; align-items: center; gap: var(--k3);
  flex: 0 0 auto;
  height: var(--cao-thanh-tren);
  padding: 0 var(--k3);
  background: var(--the);
  border-bottom: 1px solid var(--vien);
}
.xt-nhan { min-width: 0; }
.xt-ten { font-size: var(--c4); font-weight: 600; line-height: 1.2; }
.xt-than {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  overflow: auto;
  padding: var(--k3);
}
.xt-khung { width: 100%; height: 100%; border: none; background: var(--the); }
.xt-anh-khung {
  flex: 1 1 auto; width: 100%;
  display: grid; place-items: center;
  overflow: hidden;
  touch-action: none;
}
.xt-anh-khung.keo-duoc-anh { cursor: grab; }
.xt-anh-khung.dang-keo-anh { cursor: grabbing; }
.xt-anh {
  max-width: 100%; max-height: 100%;
  transition: transform var(--nhanh);
  will-change: transform;
  user-select: none;
}
.xt-anh-khung.dang-keo-anh .xt-anh { transition: none; }  /* kéo phải bám tay */
.xt-cong-cu {
  display: flex; align-items: center; gap: var(--k2);
  flex: 0 0 auto;
  margin-top: var(--k2);
  padding: var(--k1) var(--k2);
  background: var(--noi);
  border: 1px solid var(--vien);
  border-radius: 999px;
  box-shadow: var(--bong-noi);
}
.xt-chu {
  width: 100%; max-width: 90ch; margin: 0 auto;
  padding: var(--k4);
  background: var(--the);
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: var(--c3);
  white-space: pre-wrap; word-break: break-word;
  overflow: auto;
}
.xt-vp {
  width: 100%; max-width: 82ch; margin: 0 auto;
  padding: var(--k5);
  background: var(--the);
  border: 1px solid var(--vien);
  border-radius: var(--bo);
  box-shadow: var(--bong);
}
.xt-loi { width: min(520px, 100%); }
/* Mũi tên chuyển tệp: nổi hai bên, to bằng ngón tay. */
.xt-mui {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px;
  font-size: var(--c7);
  background: var(--noi);
  border: 1px solid var(--vien);
  box-shadow: var(--bong-noi);
  border-radius: 999px;
  z-index: 2;
}
.xt-mui.trai { left: var(--k3); }
.xt-mui.phai { right: var(--k3); }

/* ── 19.13 Thông báo nổi có nút hành động ──────────────────────────────────*/
.bao .bao-chu { flex: 1 1 auto; min-width: 0; }
.bao .nut.nho { flex: 0 0 auto; }

/* Hoạt ảnh — tất cả <= 150ms, chỉ để phản hồi thao tác. */
@keyframes hien { from { opacity: 0; } }
@keyframes tat  { to { opacity: 0; transform: translateX(8px); } }
@keyframes len  { from { opacity: 0; transform: translateY(6px) scale(.99); } }
@keyframes truot-trai  { from { opacity: 0; transform: translateX(12px); } }
@keyframes truot-xuong { from { opacity: 0; transform: translateY(-4px); } }
@keyframes xoay { to { transform: rotate(360deg); } }
@keyframes tho  { 50% { opacity: .45; } }

/* ── 15. Đáp ứng màn hình hẹp ──────────────────────────────────────────────
   >=1100px : lưới 248px + nội dung (mặc định)
   900-1100 : vẫn hai cột nhưng menu thu, đệm hẹp lại
   <900px   : menu thành ngăn kéo trượt, có lớp phủ tối, đóng khi bấm ra ngoài */
@media (max-width: 1099px) {
  .than { padding: var(--k3) var(--k4) var(--k5); }
  .luoi { gap: var(--k3); }
}

@media (max-width: 899px) {
  .ung-dung, .ung-dung.thu-menu { grid-template-columns: 1fr; }
  .thanh-tren { display: flex; }

  .ben {
    position: fixed; top: 0; bottom: 0; left: 0;
    width: min(var(--menu-rong), 84vw);
    transform: translateX(-100%);
    transition: transform var(--nhanh);
    box-shadow: var(--bong-noi);
  }
  .ben.mo { transform: none; }
  /* Ở ngăn kéo, trạng thái "thu" không có nghĩa — luôn hiện đủ chữ. */
  .thu-menu .ben-nhom, .thu-menu .muc .nhan-muc, .thu-menu .muc .dem,
  .thu-menu .ben-dau .ten, .thu-menu .ben-chan .thong-tin-nd { display: revert; }
  .thu-menu .muc { justify-content: flex-start; padding: 0 var(--k2); }
  .thu-menu .ben-dau { justify-content: flex-start; padding: 0 var(--k3); }

  .than { padding: var(--k3); }
  .dau .hanh-dong { margin-left: 0; width: 100%; }
  .khung { max-height: var(--cao-khung, calc(100dvh - 13rem)); }
  .form-luoi { grid-template-columns: 1fr; }
  .mo-ta { grid-template-columns: 1fr; gap: 2px var(--k2); }
  .mo-ta dd { margin-bottom: var(--k2); }
  .khay-bao { left: var(--k3); right: var(--k3); max-width: none; }
  .hop { width: 100%; }
}

/* ── 16. In giấy & giảm hoạt ảnh ───────────────────────────────────────────
   Văn phòng Hội in sổ công văn và danh sách hội viên ra giấy để lưu và ký.
   Khi in: bỏ menu, bỏ mọi nút, bỏ trần chiều cao của .khung (nếu không thì
   chỉ in ra đúng phần đang nhìn thấy — lỗi in hay gặp nhất với bảng cuộn),
   và cấm cắt một dòng làm đôi giữa hai trang. */
@media print {
  @page { margin: 14mm 12mm; }

  body { background: var(--the); font-size: 11pt; }

  /* .phu (dòng phụ dưới tiêu đề) KHÔNG nằm trong danh sách ẩn — trên sổ in,
     "Danh sách hội viên · kỳ thu 2026" chính là thứ xác định tờ giấy đó là gì. */
  .ben, .thanh-tren, .lop-phu, .nen-hop, .khay-bao,
  .nut, .nhom-nut, .phan-trang, .thanh-loc, .dau .hanh-dong,
  .the-chan, .form-chan, .bang th .mui, .quay,
  /* Lớp nổi của đợt 2. .xem-tep là NGOẠI LỆ có chủ ý — xem luật ngay dưới. */
  .bo-qua, .tien-trinh, .nen-keo, .keo-cot, .xt-thanh, .xt-mui, .xt-cong-cu {
    display: none !important;
  }

  /* In TỪ TRONG trình xem tệp: người dùng bấm "In" khi đang xem một công văn
     thì phải ra tờ công văn đó, không phải màn hình nằm dưới nó. Nên trình
     xem KHÔNG bị ẩn — nó trải phẳng ra thành nội dung trang giấy, còn phần
     ứng dụng bên dưới thì ẩn đi. */
  .xem-tep {
    position: static !important;
    background: none;
  }
  /* Trình xem nằm thẳng dưới <body>, còn ứng dụng nằm trong #app — hai nhánh
     khác nhau, nên không có bộ chọn anh-em nào nối được. :has() là cách duy
     nhất không cần JS. Trình duyệt quá cũ không hiểu :has() thì in ra cả hai
     phần: thừa giấy, nhưng không mất nội dung — hỏng nhẹ, chấp nhận được. */
  body:has(.xem-tep) #app { display: none !important; }
  .xt-than { display: block; overflow: visible; padding: 0; }
  .xt-anh { max-width: 100%; max-height: none; transform: none !important; }
  .xt-vp, .xt-chu { border: none; box-shadow: none; padding: 0; max-width: none; }
  .xt-khung { height: 100vh; }

  .ung-dung, .ung-dung.thu-menu { display: block; }
  .than { padding: 0; }

  /* Bảng phải tràn hết trang giấy, không cuộn, không cắt dòng giữa chừng. */
  .khung {
    overflow: visible !important;
    max-height: none !important;
    border: none;
    border-radius: 0;
  }
  .the { border: none; box-shadow: none; }
  .the-dau { padding: 0 0 4pt; border-bottom: 1pt solid var(--vien-dam); }
  .the-than { padding: 0; }

  .bang { font-size: 10pt; width: 100%; }
  .bang th, .bang td {
    height: auto; padding: 3pt 4pt;
    white-space: normal;            /* trên giấy không có chỗ để cuộn ngang */
    border-bottom: .5pt solid var(--vien-dam);
  }
  /* Lặp lại đầu bảng ở mỗi trang giấy — sổ công văn dài 6 trang mà mất tiêu
     đề cột từ trang 2 là không dùng được để đối chiếu. */
  .bang thead { display: table-header-group; }
  .bang tfoot { display: table-footer-group; }
  .bang tr, .o-so, .the { break-inside: avoid; page-break-inside: avoid; }
  .bang .dinh-trai { position: static; }

  /* Chip in ra giấy đen trắng: giữ viền để còn phân biệt được trạng thái. */
  .chip {
    border: .5pt solid var(--vien-dam);
    background: none !important;
    color: var(--chu) !important;
  }
  .chip::before { display: none; }

  a { color: var(--chu); text-decoration: none; }
  .dau { margin-bottom: 8pt; }
  .dau .tieu-de { font-size: 14pt; }
}

/* Người dùng tắt hoạt ảnh ở hệ điều hành thì tắt thật, không giảm nửa vời. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
