/* ============================================================================
 * X-IRIS — BẢNG MÀU DÙNG CHUNG cho các màn "THÊM MỚI / CHỈNH SỬA / XEM CHI TIẾT"
 * (Nhập hàng, Xuất hàng, Phiếu vận hành, Ghi chỉ số đồng hồ, Thông số vận hành...).
 *
 * 2026-08-22: trước đây MỖI file .tpl tự khai một bộ hex riêng (--nh-ink, --nh-card,
 * --nh-accent, --nh-wink...) giống hệt nhau nhưng COPY-PASTE độc lập — sửa 1 màu phải
 * sửa lặp lại ở từng file, dễ sót (đã xảy ra thật: sửa nhap_hang xong, xuat_hang vẫn cũ).
 * File này khai MỘT LẦN DUY NHẤT; mỗi .tpl chỉ còn `--nh-ink:var(--xf-ink)` thay vì
 * `--nh-ink:#0f172a` — tức KHÔNG đổi tên biến cục bộ của từng file (đỡ phải sửa lại hàng
 * trăm chỗ dùng var(--nh-*) trong CSS/HTML của nó), chỉ đổi NGUỒN GIÁ TRỊ. Sau này đổi
 * màu chỉ sửa Ở ĐÂY — mọi màn tự động theo.
 *
 * CÔNG THỨC (chốt qua nhiều vòng phản hồi thật của user, xem lịch sử sửa nhap_hang_add/
 * view.tpl cùng ngày để biết LÝ DO từng giá trị — không phải chọn ngẫu nhiên):
 *   - Tiêu đề khối (badge số + tên khối + viền trái)  = --xf-wink (vàng cam, "màu hệ
 *     thống đang dùng" cho trạng thái — KHÔNG PHẢI màu widget Tổng quan, cái đó là code
 *     chết không hiển thị).
 *   - Nút chính / link / tiêu đề bảng / viền ô khi focus = --xf-accent (xanh dương thật,
 *     KHÔNG PHẢI teal cũ #017e84 — teal lệch tông với vàng cam, xanh dương mới là cặp bổ
 *     túc). Bản tối KHÔNG dùng var(--x-cyan) (#70ecff, quá chói cạnh vàng cam).
 *   - Nút chính (.btn.pri) ở bản TỐI: nền dùng NGUYÊN --xf-accent-btn-dark (đậm hơn
 *     --xf-accent) + chữ TRẮNG — không lật chữ sang tối (thử rồi, user thấy chói/khó đọc).
 *   - Nền thẻ = ĐẶC HOÀN TOÀN, không dùng --x-card (bán trong suốt của hệ thống — để lộ
 *     gradient nhiều lớp phía dưới, đọc như sọc/loang, user đã báo 2 lần).
 *   - Nền "ô khoá"/zone/tiêu đề bảng = PHỦ ĐEN MỜ TƯƠNG ĐỐI (rgba), không phải hex cứng —
 *     đảm bảo LUÔN tối hơn thẻ bất kể --xf-card đổi thành màu gì sau này.
 *   - 26/08/2026: NGOẠI LỆ có chủ đích — user chốt đổi --xf-card BẢN TỐI sang phủ đen mờ
 *     #00000047 (~28% đặc), đã cảnh báo trước là gần trùng alpha với --xf-zone (rgba(0,0,0,.28))
 *     nên "ô khoá"/zone gần như không còn tối hơn thẻ được nữa, user vẫn chốt đổi. Bản SÁNG
 *     giữ nguyên #fff đặc — ngoại lệ này CHỈ áp dụng bản tối.
 * ========================================================================== */
:root {
  --xf-ink:#0f172a; --xf-mut:#3f4d63; --xf-faint:#57667c;
  --xf-card:#fff; --xf-line:#c7d0dd; --xf-zone:rgba(15,23,42,.06); --xf-line2:#dbe2ea;
  --xf-hover:#f8fafc;
  --xf-okink:#047857; --xf-okbg:#ecfdf5; --xf-okline:#a7f3d0;
  --xf-wink:#b45309; --xf-wbg:#fffbeb; --xf-wline:#fde68a;
  --xf-erink:#dc2626; --xf-erbg:#fef2f2; --xf-erline:#fecaca;
  --xf-shadow:0 1px 3px rgba(15,23,42,.05);
  --xf-accent:#0369a1; --xf-accent-btn-dark:#0369a1; --xf-cam:#c2410c;
  --xf-field:#e9eef6; --xf-field-brd:#97a9c0; --xf-field-ring:rgba(3,105,161,.30);
}
html[data-xtheme="dark"] {
  --xf-ink:var(--x-ink); --xf-mut:var(--x-mut); --xf-faint:var(--x-faint);
  --xf-card:#00000047; --xf-line:rgba(53,224,240,0.22); --xf-zone:rgba(0,0,0,.28); --xf-line2:rgba(53,224,240,0.15);
  --xf-hover:#1c2d47;
  --xf-okink:var(--x-green); --xf-okbg:rgba(64,247,177,.12); --xf-okline:rgba(64,247,177,.34);
  --xf-wink:var(--x-amber); --xf-wbg:rgba(255,201,77,.12); --xf-wline:rgba(255,201,77,.34);
  --xf-erink:var(--x-red); --xf-erbg:rgba(255,107,107,.12); --xf-erline:rgba(255,107,107,.34);
  --xf-shadow:0 4px 20px rgba(0,0,0,0.25);
  /* --xf-accent (chữ/viền/link) SÁNG hơn --xf-accent-btn-dark (nền nút đặc) có chủ đích:
     accent dùng làm CHỮ trên nền tối cần đủ sáng để đọc; nút LÀ nền nên cần đủ tối để chữ
     trắng lên rõ — 2 vai trò khác nhau, gộp làm 1 là gốc của bug "chữ chìm" đã xảy ra. */
  --xf-accent:#38bdf8; --xf-accent-btn-dark:#0369a1; --xf-cam:#ffb27a;
/* Ô nhập bản TỐI phải SÁNG HƠN nền thẻ, không phải tối hơn. Thẻ ở bản tối là
   --xf-card:#00000047 (đen 28%) chồng lên nền navy, ra khoảng #081019 — ô nhập mà cũng
   tông đó thì biến mất. Đã qua ba nấc #0d1c2e -> #13273d -> #17324f vẫn bị chủ dự án
   báo "chế độ tối trong tối quá luôn á"; #1e4066 mới đủ tách khỏi nền. Bản SÁNG thì
   ngược lại: ô TỐI hơn thẻ trắng (#e9eef6), và chủ dự án đã duyệt tông đó. */
/* Tông ô nhập bản TỐI: XÁM–XANH TRUNG TÍNH, không phải xanh đậm.
   #1e4066 (xanh bão hoà) đủ nổi nhưng chủ dự án bác: "màu này nhìn xấu quá" — đúng,
   nó giống một ô ĐANG ĐƯỢC CHỌN hơn là một ô để gõ, và đứng cạnh nút xanh của trang
   thì hai thứ đánh nhau. #1d2836 giữ nguyên độ sáng cần thiết để tách khỏi nền thẻ
   nhưng gần như không màu, nên ô nhập lùi về sau, nhường màu cho nút và trạng thái. */
  --xf-field:#1d2836; --xf-field-brd:#44566c; --xf-field-ring:rgba(122,219,255,.38);
}

/* ============================================================================
 * LOADING DÙNG CHUNG — 29/09/2026
 * Nền đen trong suốt, cụm chuyển động nhiều lớp và thanh tiến trình. Overlay luôn
 * phủ toàn viewport, kể cả sidebar; cụm giữa không dùng hộp nền để giao diện nhẹ hơn.
 * ========================================================================== */
:root {
  --xf-loading-phu: rgba(0, 0, 0, .68);
  --xf-loading-cyan: #38bdf8;
  --xf-loading-blue: #2563eb;
  --xf-loading-green: #2dd4bf;
}
html[data-xtheme="dark"] { --xf-loading-phu: rgba(0, 0, 0, .76); }
.xf-loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--xf-loading-phu);
  -webkit-backdrop-filter: blur(3px) saturate(.78);
  backdrop-filter: blur(3px) saturate(.78);
  touch-action: none;
  overscroll-behavior: contain;
  animation: xfLoadingOverlayIn .18s ease-out both;
}
.xf-loading-overlay, .xf-loading-overlay * { box-sizing: border-box; }
.xf-loading-overlay.xf-loading-out {
  pointer-events: none;
  animation: xfLoadingOverlayOut .18s ease-in both;
}
.xf-loading-panel {
  width: auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: #f2fbff;
  animation: xfLoadingPanelIn .28s cubic-bezier(.2, .8, .2, 1) both;
}
.xf-loading-stage {
  position: relative;
  width: 104px;
  height: 104px;
  display: grid;
  place-items: center;
  flex: 0 0 104px;
}
.xf-loading-stage::before {
  content: "";
  position: absolute;
  inset: 18px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(56,189,248,.16), rgba(37,99,235,.04) 54%, transparent 72%);
  filter: blur(4px);
  animation: xfLoadingAura 1.7s ease-in-out infinite;
}
.xf-loading-ring {
  position: absolute;
  border-radius: 50%;
}
.xf-loading-ring-a {
  inset: 0;
  background: conic-gradient(from 30deg, transparent 0 14%, var(--xf-loading-cyan) 28%, var(--xf-loading-blue) 58%, transparent 74% 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  filter: drop-shadow(0 0 7px rgba(56, 189, 248, .5));
  animation: xfLoadingSpin 1.05s linear infinite;
}
.xf-loading-ring-b {
  inset: 14px;
  border: 1px solid rgba(148, 210, 232, .25);
  border-top-color: var(--xf-loading-green);
  border-left-color: rgba(45, 212, 191, .72);
  animation: xfLoadingSpinBack 1.7s cubic-bezier(.55, .2, .35, .8) infinite;
}
.xf-loading-orbit {
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  animation: xfLoadingOrbit 2.35s linear infinite;
}
.xf-loading-orbit i {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #7dd3fc;
  box-shadow: 0 0 12px rgba(56,189,248,.95), 0 0 3px #fff;
}
.xf-loading-orbit i:nth-child(1) { top: -2px; left: calc(50% - 3px); }
.xf-loading-orbit i:nth-child(2) { right: 5px; bottom: 17px; width: 5px; height: 5px; background:#5eead4; }
.xf-loading-orbit i:nth-child(3) { left: 8px; bottom: 14px; width: 4px; height: 4px; opacity:.72; }
.xf-loading-core {
  position: relative;
  z-index: 1;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(125, 211, 252, .3);
  border-radius: 50%;
  background: rgba(14, 165, 233, .12);
  box-shadow: 0 0 0 7px rgba(56, 189, 248, .05), 0 0 22px rgba(37, 99, 235, .34);
  animation: xfLoadingCore 1.45s ease-in-out infinite;
}
.xf-loading-bars {
  width: 25px;
  height: 23px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
}
.xf-loading-bars i {
  width: 4px;
  height: 17px;
  border-radius: 3px;
  background: linear-gradient(180deg, #99f6e4, #38bdf8);
  box-shadow: 0 0 8px rgba(56, 189, 248, .72);
  transform-origin: center bottom;
  animation: xfLoadingBar .82s ease-in-out infinite;
}
.xf-loading-bars i:nth-child(2) { animation-delay: -.55s; }
.xf-loading-bars i:nth-child(3) { animation-delay: -.28s; }
.xf-loading-label {
  color: #e7f7ff;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0;
  white-space: nowrap;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .62);
}
.xf-loading-track {
  position: relative;
  width: 148px;
  height: 4px;
  overflow: hidden;
  border-radius: 3px;
  background: rgba(148, 163, 184, .2);
}
.xf-loading-track span {
  position: absolute;
  inset: 0 auto 0 0;
  width: 48%;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, var(--xf-loading-cyan), var(--xf-loading-green));
  box-shadow: 0 0 9px rgba(56, 189, 248, .6);
  animation: xfLoadingTrack 1.25s ease-in-out infinite;
}
@keyframes xfLoadingOverlayIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes xfLoadingOverlayOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes xfLoadingPanelIn { from { opacity: 0; transform: translateY(6px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes xfLoadingSpin { to { transform: rotate(360deg); } }
@keyframes xfLoadingSpinBack { 50% { transform: rotate(-150deg) scale(.94); } 100% { transform: rotate(-360deg) scale(1); } }
@keyframes xfLoadingOrbit { to { transform: rotate(360deg); } }
@keyframes xfLoadingAura { 50% { transform: scale(1.18); opacity:.6; } }
@keyframes xfLoadingCore { 50% { box-shadow: 0 0 0 10px rgba(56, 189, 248, .02), 0 0 28px rgba(45, 212, 191, .38); } }
@keyframes xfLoadingBar {
  0%, 100% { transform: translateY(3px) scaleY(.42); opacity: .52; }
  50% { transform: translateY(-2px) scaleY(1); opacity: 1; }
}
@keyframes xfLoadingBarSoft {
  0%, 100% { transform: translateY(1px) scaleY(.62); opacity: .68; }
  50% { transform: translateY(-1px) scaleY(.94); opacity: 1; }
}
@keyframes xfLoadingTrack { 0% { transform: translateX(-110%); } 55%, 100% { transform: translateX(220%); } }
@media (prefers-reduced-motion: reduce) {
  .xf-loading-overlay, .xf-loading-panel, .xf-loading-stage::before, .xf-loading-ring-a, .xf-loading-ring-b, .xf-loading-orbit,
  .xf-loading-core, .xf-loading-bars i, .xf-loading-track span { animation: none; }
  /* Vòng quay, ba thanh nhịp và thanh tiến trình đều là tín hiệu trạng thái chức năng.
     Giữ chuyển động chậm/nhẹ để điện thoại bật "Giảm chuyển động" vẫn thấy loader đang chạy. */
  .xf-loading-ring-a { animation: xfLoadingSpin 1.6s linear infinite; }
  .xf-loading-ring-b { transform: rotate(-28deg); }
  .xf-loading-bars i { animation: xfLoadingBarSoft 1.2s ease-in-out infinite; }
  .xf-loading-bars i:nth-child(2) { animation-delay: -.8s; }
  .xf-loading-bars i:nth-child(3) { animation-delay: -.4s; }
  .xf-loading-track span { left: 0; animation: xfLoadingTrack 1.8s ease-in-out infinite; }
}

/* ============================================================================
 * 11/09/2026 — NỀN ĐẶC CHO HỘP NỔI (select2). CÙNG MỘT CÁI BẪY với overlay ở trên.
 *
 * Có một luật dùng chung đang tô nền danh sách xổ của select2 bằng
 *   html[data-xtheme="dark"] .select2-dropdown{background:var(--xf-card)!important}
 * mà --xf-card BẢN TỐI từ 26/08 là #00000047 (đen ~28% alpha, xem ghi chú đầu file).
 * Nền thẻ nằm PHẲNG trên trang thì mờ vẫn đẹp; nhưng danh sách xổ NỔI ĐÈ lên nội dung,
 * nền mờ làm thẻ KPI / nút / bảng phía sau hiện xuyên qua — người dùng đọc ra như "lỗi
 * giao diện". Đã đo trên trang thật 11/09: dropdown z-index 2000000 (nằm trên cùng,
 * KHÔNG phải lỗi z-index) nhưng background computed ra rgba(0,0,0,0.28).
 *
 * Sửa ở GỐC thay vì vá từng màn (đã đếm: 36 file .tpl dùng select2). Dùng token riêng,
 * cố định, KHÔNG phụ thuộc --xf-card đổi thế nào về sau — đúng cách đã làm với overlay.
 *
 * ⚠ Phải thắng một luật có !important ở specificity (0,2,1). Nên selector dưới đây cố ý
 * thêm .select2-container--open để lên (0,3,1): specificity được so TRƯỚC thứ tự nguồn,
 * nhờ vậy thắng bất kể luật kia được nạp sau hay trước.
 * ========================================================================== */
:root { --xf-pop:#fff; }
html[data-xtheme="dark"] { --xf-pop:#12233a; }
.select2-container--open .select2-dropdown{background:var(--xf-pop)!important}
html[data-xtheme="dark"] .select2-container--open .select2-dropdown{background:var(--xf-pop)!important}
/* Kết quả đang chọn/đang rê cũng phải đặc, nếu không vẫn lộ nội dung phía sau qua dòng đó. */
html[data-xtheme="dark"] .select2-container--open .select2-results__option--selected,
html[data-xtheme="dark"] .select2-container--open .select2-results__option[aria-selected="true"]{background:#1b3a5c!important}
/* 25/08: user báo bản position:fixed đè lên CẢ sidebar — .xf-loading-scoped gắn khi có
   container riêng (vd #tqRoot), chỉ phủ ĐÚNG khu vực nội dung của màn đó.
   ⚠⚠ 19/09/2026 — ĐÃ NGỪNG DÙNG. Chủ dự án đảo lại yêu cầu: loading phải phủ FULL MÀN, kể cả
   sidebar. js/xiris_loading.js nay bỏ qua tham số container nên class này KHÔNG còn được gắn
   vào đâu nữa. GIỮ LẠI khai báo (không xoá) để nếu có ngày quay về kiểu cũ thì chỉ cần bật
   lại nhánh scoped bên JS, khỏi dựng lại kiểu dáng. */
.xf-loading-overlay.xf-loading-scoped{position:absolute;z-index:50}
/* 26/08: overlay .scoped cao theo TOÀN BỘ nội dung (có thể vài nghìn px ở Tổng quan) mà
   .xf-spin lại canh giữa theo CHIỀU CAO ĐÓ (align-items:center của cha) -> icon rơi vào
   giữa trang, đứng gần đầu trang (nơi có ô chọn dự án) sẽ không thấy gì. Ghim icon theo
   VIEWPORT hiện tại (không theo chiều cao overlay) để luôn thấy ngay chỗ đang đứng. */
.xf-loading-overlay.xf-loading-scoped .xf-loading-panel{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}

/* 26/08: jquery-ui.min.css khai cứng .ui-widget{font-family:Arial,Helvetica,sans-serif} cho
   TOÀN BỘ widget jQuery UI (datepicker...) — bảng lịch bấm lên hiện chữ Arial, lệch hẳn font hệ
   thống trang đang dùng. .ui-datepicker được jQuery UI gắn thẳng ra <body> nên inherit ở đây là
   lấy đúng font hệ thống thật (kế thừa từ <body>), không tự chọn một font cụ thể nào khác. */
.ui-datepicker{font-family:inherit}


/* ============================================================================================
 * 28/08 (user): "mấy icon ở chế độ tối mà cứ để màu đen" — icon lịch trong <input type=date>,
 * mũi tên <select>, thanh cuộn... là control GỐC của trình duyệt, không phải icon của mình.
 * Mặc định trình duyệt vẽ chúng theo bảng màu SÁNG nên trên nền tối thành đen thui.
 * color-scheme:dark là cách CHUẨN để báo trình duyệt vẽ đúng bộ màu tối -> icon tự sáng lên.
 * ⚠ ĐỪNG kèm thêm filter:invert() cho icon lịch — color-scheme đã lật rồi, invert nữa là đen lại.
 * ============================================================================================ */
html[data-xtheme="dark"] input,
html[data-xtheme="dark"] select,
html[data-xtheme="dark"] textarea,
html[data-xtheme="dark"] .xf-input,
html[data-xtheme="dark"] .xf-select { color-scheme: dark; }
/* 28/08 lần 2 (user): riêng danh sách sổ xuống của <select> (thong_ke_ctn.tpl) vẫn hiện nền
   trắng chữ nhạt — color-scheme đặt trên CHÍNH thẻ <select> không đủ, Chrome vẽ popup danh
   sách theo color-scheme của CẢ TÀI LIỆU (root), không chỉ theo phần tử kích hoạt nó. Đặt thêm
   ở gốc <html> để chắc chắn popup native (select, input date/time...) luôn theo đúng bộ tối. */
html[data-xtheme="dark"] { color-scheme: dark; }
/* 28/08 lần 3 (user, khẩn): color-scheme:dark ở gốc <html> VẪN không đủ — trình duyệt/máy user
   vẫn vẽ danh sách sổ xuống <select> nền trắng chữ nhạt gần như không đọc được. Không dựa vào
   color-scheme nữa; đặt THẲNG màu nền/chữ lên từng <option> — cách này Chrome/Edge/Firefox tôn
   trọng ổn định hơn nhiều so với color-scheme (vốn chỉ là gợi ý, trình duyệt có thể bỏ qua tuỳ
   engine render popup của từng máy). Dùng hex cố định #0d1c2e/#f5fbff — biến --xf-card có kênh
   alpha không đặc thật ở bản tối (xem ghi chú cũ ở .xf-loading-overlay), <option> cần màu ĐẶC. */
html[data-xtheme="dark"] select option,
html[data-xtheme="dark"] select optgroup {
    background-color: #0d1c2e;
    color: #f5fbff;
}

/* ============================================================================
   11/09/2026 (user): LETTERHEAD GREENWORLD CHO BẢN IN PDF
   Khối #xirisPdfHeader nằm ngay đầu <body> (layout/header_only.tpl) nên có mặt ở
   mọi màn. Ngoài màn hình thì ẩn hẳn, chỉ hiện lúc in.

   Dựng bằng HTML/CSS chứ không phải 1 ảnh bitmap: in ra nét ở mọi cỡ giấy, chỉ
   dùng ảnh cho logo và mã QR (2 thứ không vẽ lại bằng CSS được).

   Vì sao position:absolute chứ không phải fixed: absolute chỉ vẽ ở TRANG ĐẦU
   (đúng yêu cầu user), fixed sẽ lặp lại đầu mọi trang giấy.

   Vì sao phải !important + chọn theo #id: mỗi màn khi in đều tự ẩn hết trang rồi
   chỉ bật lại khối gốc của mình, theo 3 kiểu khác nhau:
     - body{visibility:hidden}              (phiếu VH, nhập/xuất, đồng hồ, TSVH, báo cáo ca, TK XLN)
     - body *{visibility:hidden!important}  (thống kê bảo trì)
     - body.tk-printing > *:not(.tkw){display:none!important}  (thống kê)
   Chọn theo #id (độ đặc hiệu 1,0,0) nên thắng cả ba mà không phải sửa 10 file.

   --xf-pdf-head: khoảng cách từ letterhead xuống nội dung (ô "Khoảng cách" ở màn cấu hình).
   Không còn phải chừa lề cứng cho header nữa: lúc in header được dời vào TRONG khối in nên
   nằm trong dòng chảy và tự đẩy nội dung xuống.
   ========================================================================== */
#xirisPdfHeader,
#xirisPdfFooter { display: none; }

@media print {
    :root { --xf-pdf-head: 6mm; }   /* khoảng cách từ letterhead xuống nội dung */

    /* Lúc in, script ở layout/header_only.tpl dời khối này VÀO TRONG khối in của màn, nên ở
       đây chỉ cần bật hiện + nằm trong dòng chảy; lề trái/phải thừa hưởng của khối in. */
    #xirisPdfHeader {
        display: block !important;
        visibility: visible !important;
        position: static;
        width: 100%;
        margin-bottom: var(--xf-pdf-head, 6mm);
        box-sizing: border-box;
        color: #000;
        font-family: Arial, Helvetica, sans-serif;
    }
    #xirisPdfHeader * { visibility: visible !important; }

    #xirisPdfFooter {
        display: block !important;
        visibility: visible !important;
        position: static;
        width: 100%;
        margin-top: var(--xf-pdf-foot, 6mm);
        box-sizing: border-box;
        color: #000;
        font-family: Arial, Helvetica, sans-serif;
    }
    #xirisPdfFooter * { visibility: visible !important; }

    .xf-lh-top {
        display: flex;
        align-items: center;
        gap: 10mm;
        border: 1px solid #d9d9d9;
        padding: 3mm 4mm;
    }

    /* Chế độ "ảnh": user tải nguyên 1 ảnh letterhead lên, đè toàn bộ mẫu HTML. */
    .xf-lh-anh { display: block !important; width: 100%; height: auto; }

    /* --- logo + khẩu hiệu --- */
    .xf-lh-logo { flex: 0 0 auto; text-align: center; }
    .xf-lh-logo img { display: block; height: 17mm; width: auto; }
    .xf-lh-slogan {
        display: block;
        margin-top: 0.6mm;
        border-top: 0.6pt solid #c8a415;
        border-bottom: 0.6pt solid #c8a415;
        padding: 0.4mm 0;
        color: #1a7a3c;
        font-size: 4pt;
        letter-spacing: 0.35pt;
    }

    /* --- tên công ty + liên hệ --- */
    .xf-lh-info { flex: 1 1 auto; min-width: 0; font-family: "Times New Roman", Times, serif; }
    .xf-lh-name { font-size: 19pt; font-weight: 700; line-height: 1.05; letter-spacing: 0.3pt; }
    .xf-lh-corp { font-size: 12pt; font-weight: 700; line-height: 1.15; }
    .xf-lh-line { font-size: 10pt; line-height: 1.3; }
    .xf-lh-mail { color: #1155cc; text-decoration: underline; }

    /* --- 2 tem ISO --- */
    .xf-lh-iso { flex: 0 0 auto; display: flex; flex-direction: column; gap: 2mm; }
    .xf-lh-badge {
        border: 0.9pt solid #2fa34a;
        border-radius: 1.6mm;
        padding: 1.2mm 2.2mm;
        line-height: 1.1;
    }
    .xf-lh-badge-main { display: flex; align-items: center; gap: 1.6mm; font-size: 10pt; color: #333; }
    .xf-lh-badge-main b { color: #2fa34a; font-size: 13pt; font-weight: 700; }
    .xf-lh-pill {
        margin-left: auto;
        background: #2fa34a;
        color: #fff;
        border-radius: 1mm;
        padding: 0.3mm 1.4mm;
        font-size: 5.5pt;
        font-weight: 700;
    }
    .xf-lh-badge-sub { color: #666; font-size: 6pt; letter-spacing: 0.2pt; }

    /* --- mã QR --- */
    .xf-lh-qr { flex: 0 0 auto; height: 16mm; width: auto; display: block; }

    /* --- vạch xanh/vàng dưới khung --- */
    .xf-lh-rule {
        height: 1.4mm;
        margin: 0 0 3mm;
        background: linear-gradient(to right, #c8a415 0 38%, #1a7a3c 38% 100%);
    }

    /* --- triết lý --- */
    .xf-lh-triet-ly {
        text-align: center;
        color: #17607a;
        font-size: 10pt;
        font-weight: 600;
        letter-spacing: 2.6pt;
    }
    .xf-lh-cham-ngon {
        margin-top: 1mm;
        text-align: center;
        color: #17607a;
        font-size: 13pt;
        font-weight: 700;
    }
    .xf-lh-cham-ngon i { color: #2f6ea5; font-style: normal; margin: 0 1.5mm; }

}

/* ===========================================================================
   IN PDF — GIỮ MÀU, DẢI TIÊU ĐỀ CÙNG TÔNG VỚI FILE EXCEL        (11/09/2026)
   user: "pdf cho in có màu như excel đi tất cả các phiếu luôn".

   Hai việc phải làm, thiếu một cái là vẫn ra bản in trắng trơn:
   1. Trình duyệt MẶC ĐỊNH bỏ hết nền/màu khi in cho đỡ tốn mực. Bật lại bằng
      print-color-adjust:exact — trước đây chỉ màn Chi tiết phiếu vận hành tự
      khai riêng nên chỉ mình nó in ra có màu.
   2. Trên màn hình tiêu đề khối để PHẲNG (chuẩn tiêu đề site-wide, không nền
      tint) nên có bật màu cũng chẳng có gì để in. Vì vậy vẽ thêm DẢI XANH cho
      RIÊNG bản in, lấy đúng bảng màu của file Excel (C.brand #017E84, nền hàng
      chẵn #F8FAFC trong hàm exportExcel của các màn phiếu) để bản in PDF và file
      Excel nhìn ra là cùng một bộ chứng từ.

   ⚠ Toàn bộ nằm trong @media print — KHÔNG đụng gì tới giao diện màn hình.
   ⚠ Cố ý KHÔNG dùng `*` cho cả trang mà chỉ bật màu trong các KHUNG IN đã biết:
      mỗi khung đó đã tự ép bảng màu SÁNG trong @media print của màn nó, nên
      bật màu không thể làm bản in ra nền đen khi người dùng đang ở chế độ tối.
      Thêm màn in mới thì thêm khung của nó vào danh sách dưới đây.
   ⚠ Tên khung được LẶP 3 LẦN (.nh-wrap.nh-wrap.nh-wrap) để nâng độ đặc hiệu.
      Không phải làm màu: từng màn có sẵn luật riêng đặc hiệu hơn kèm !important
      (ví dụ `.nh-tb th.lbl{color:...!important}`, hoặc luật kèm
      html[data-xtheme="dark"]), viết một lớp là thua — đã đo: nền đổi được mà
      CHỮ vẫn giữ màu cũ, thành chữ xanh trên nền xanh, đọc không ra.
   =========================================================================== */
@media print {

    /* Khung in của: Nhập/Xuất hàng + Đồng hồ (.nh-wrap), Thông số vận hành
       (.ts-wrap), Chi tiết phiếu vận hành (.pvv), Phiếu bảo trì (#ls_ct),
       Báo cáo ca vận hành (.bcv-wrap), Báo cáo thông số vận hành (.bct). */
    .nh-wrap, .nh-wrap *,
    .ts-wrap, .ts-wrap *,
    .pvv, .pvv *,
    #ls_ct, #ls_ct *,
    .bcv-wrap, .bcv-wrap *,
    .bct, .bct * {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
        color-adjust: exact !important;
    }

    /* --- Dải tiêu đề khối --- */
    .nh-wrap.nh-wrap.nh-wrap .nh-ch,
    .nh-wrap.nh-wrap.nh-wrap .nh-bh,
    .ts-wrap.ts-wrap.ts-wrap .nh-ch,
    .ts-wrap.ts-wrap.ts-wrap .nh-bh,
    .pvv.pvv.pvv .pvv-title,
    #ls_ct#ls_ct#ls_ct .ls-ct-the > h4 {
        background: #017e84 !important;
        border-color: #017e84 !important;
        color: #ffffff !important;
        border-radius: 0 !important;
        padding: 6px 10px !important;
    }
    .nh-wrap.nh-wrap.nh-wrap .nh-ch *,
    .nh-wrap.nh-wrap.nh-wrap .nh-bh *,
    .ts-wrap.ts-wrap.ts-wrap .nh-ch *,
    .ts-wrap.ts-wrap.ts-wrap .nh-bh *,
    .pvv.pvv.pvv .pvv-title *,
    #ls_ct#ls_ct#ls_ct .ls-ct-the > h4 * {
        color: #ffffff !important;
    }

    /* --- Tiêu đề bảng --- */
    .nh-wrap.nh-wrap.nh-wrap table thead th,
    .ts-wrap.ts-wrap.ts-wrap table thead th,
    .pvv.pvv.pvv table thead th,
    #ls_ct#ls_ct#ls_ct table thead th,
    .bcv-wrap.bcv-wrap.bcv-wrap table thead th,
    .bct.bct.bct table thead th {
        background: #017e84 !important;
        background-image: none !important;
        border-color: #017e84 !important;
        color: #ffffff !important;
    }
    .nh-wrap.nh-wrap.nh-wrap table thead th *,
    .ts-wrap.ts-wrap.ts-wrap table thead th *,
    .pvv.pvv.pvv table thead th *,
    #ls_ct#ls_ct#ls_ct table thead th *,
    .bcv-wrap.bcv-wrap.bcv-wrap table thead th *,
    .bct.bct.bct table thead th * {
        color: #ffffff !important;
    }

    /* --- Hàng chẵn tô nhạt, đúng kiểu kẻ sọc của file Excel --- */
    .nh-wrap.nh-wrap.nh-wrap table tbody tr:nth-child(even) > td,
    .ts-wrap.ts-wrap.ts-wrap table tbody tr:nth-child(even) > td,
    #ls_ct#ls_ct#ls_ct table tbody tr:nth-child(even) > td,
    .bcv-wrap.bcv-wrap.bcv-wrap table tbody tr:nth-child(even) > td,
    .bct.bct.bct table tbody tr:nth-child(even) > td {
        background: #f8fafc !important;
    }
}


/* =========================================================================================
   12/09/2026 (user): "header toàn trang ở điện thoại nhiều trang nó không hiện luôn, sao bấm
   sidebar được" — mất thanh ☰ nên không mở được menu trái.

   GỐC RỄ (đo chứ không đoán): khung ứng dụng khoá cứng theo 100vh —
     style.css:7761  .wrap_all_site { height:100vh; overflow:hidden }
     style.css:4872  .content_main  { height:calc(100vh - 57px); overflow:auto }
   Trên điện thoại 100vh là chiều cao viewport LỚN NHẤT (tính cả phần đang bị thanh địa chỉ che),
   luôn CAO HƠN vùng thực sự nhìn thấy. Hệ quả dây chuyền:
     1. tài liệu cao hơn màn hình chừng 60-100px -> TRANG NGOÀI vẫn trượt được;
     2. vuốt một cái là thanh header 57px trôi khỏi màn;
     3. kéo ngược lên KHÔNG được, vì ngón tay đang nằm trên .content_main — nó có thanh cuộn
        RIÊNG (overflow:auto) và nuốt trọn cử chỉ, trang ngoài không bao giờ nhận.
   Thế là header mất hẳn, hết đường bấm ba gạch. Đúng hai triệu chứng user báo: "mất hẳn, trên
   cùng là nội dung luôn" và "lúc đầu có, cuộn xuống là mất".

   dvh = chiều cao viewport ĐANG THẤY, tự co giãn theo thanh địa chỉ -> khung vừa khít màn hình,
   trang ngoài hết chỗ trượt, header không bao giờ bị đẩy đi. Trình duyệt cũ không hiểu dvh thì
   bỏ qua đúng hai dòng này và giữ nguyên 100vh như trước, không hỏng thêm gì.

   ⚠ ĐỪNG "sửa" bằng position:sticky cho .dong_mo_menu: .wrap_all_site có overflow:hidden nên nó
     thành khung cuộn của sticky, mà chính nó lại không cuộn -> sticky IM RE, đổi xong tưởng xong.
   ⚠ Đặt ở ĐÂY chứ không phải style.responsive.css: tệp này nạp qua header_only.tpl kèm ?v= do
     mình tự bump được, nên bản vá tới máy người dùng ngay; CSS theme do NukeViet tự gắn phiên bản,
     không chắc hết bộ nhớ đệm của điện thoại.
   ========================================================================================= */
@media screen and (max-width: 991.98px) {
    .wrap_all_site {
        height: 100dvh;
    }
    .content_main {
        height: calc(100dvh - 57px);
    }
}

/* =========================================================================================
   PHAN TRANG DUNG CHUNG  (18/09/2026 — chu du an: "dung 1 loai phan trang thoi")
   Moi man truoc day tu boc mot lop rieng: .dsnk-pages, .nh-page, .pa-pager... Nay tat ca
   dung `<div class="xf-pager">{PAGES}</div>`, con {PAGES} luon la ket qua nv_generate_page().
   Khai o day vi xiris_form.css duoc nap site-wide, khai mot lan la moi man dung duoc.
   ⚠ Chi tao kieu cho .pagination KHI nam trong .xf-pager — theme con dung lop .pagination
     o cho khac, dat kieu tran se an sang chuc nang khac.
   ========================================================================================= */
.xf-pager {
    display: flex;
    justify-content: center;
    padding: 14px 8px 4px;
}
.xf-pager .pagination {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.xf-pager .pagination > li > a,
.xf-pager .pagination > li > span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    border: 1px solid var(--xf-line);
    border-radius: 8px;
    background: var(--xf-card);
    color: var(--xf-ink);
    font-size: 13px;
    line-height: 1;
    text-decoration: none;
    transition: background .12s, border-color .12s, color .12s;
}
.xf-pager .pagination > li > a:hover,
.xf-pager .pagination > li > a:focus {
    border-color: var(--xf-accent);
    color: var(--xf-accent);
    text-decoration: none;
}
.xf-pager .pagination > .active > a,
.xf-pager .pagination > .active > span,
.xf-pager .pagination > li.active > a,
.xf-pager .pagination > li.active > span {
    /* ⚠⚠ --xf-accent-btn-dark chu KHONG phai --xf-accent. Ban toi --xf-accent = #38bdf8,
       chu trang len do chi ~1,9:1 — khong doc ra so trang nao dang mo. --xf-accent-btn-dark
       la #0369a1 o CA hai ban mau, chu trang len do 5,93:1 (WCAG AA). */
    background: var(--xf-accent-btn-dark);
    border-color: var(--xf-accent-btn-dark);
    color: #fff;
    font-weight: 600;
}
.xf-pager .pagination > .disabled > a,
.xf-pager .pagination > .disabled > span {
    opacity: .45;
    pointer-events: none;
}

/* =========================================================================================
   THANH HEADER O DIEN THOAI — LOP CHAN THU HAI  (18/09/2026)
   12/09 da vá bằng 100dvh (xem khối ngay trên). Chủ dự án báo lại 18/09: "cái header ở giao
   diện điện thoại nó hay bị che". `dvh` chỉ chữa việc vỏ ứng dụng CAO HƠN vùng nhìn thấy;
   nó không chặn được dây chuyền thứ hai:
     .content_main có thanh cuộn riêng → vuốt hết đầu/cuối khối đó thì cử chỉ TRÀN SANG
     trang ngoài (scroll chaining) → trang ngoài nhích lên, thanh header 57px trôi khỏi màn,
     mà kéo ngược lại thì ngón tay vẫn nằm trên .content_main nên không lấy lại được.
   `overscroll-behavior: contain` cắt đúng đường tràn đó: cuộn hết khối là dừng, không
   truyền ra ngoài nữa.
   ⚠ Cố ý KHÔNG dùng `html,body{overflow:hidden}`: màn nào lỡ không nằm trong .content_main
     sẽ mất luôn khả năng cuộn. Luật dưới đây chỉ THÊM, không khoá gì cả.
   ========================================================================================= */
@media (max-width: 991.98px) {
    .content_main {
        overscroll-behavior: contain;
    }
    body {
        overscroll-behavior-y: none;
    }
}

/* =========================================================================================
   THANH HEADER MOBILE - KHONG CHO CUON KHUNG NGOAI  (29/09/2026)
   `overscroll-behavior` chi chan thao tac vuot bien tu ngon tay. Cac man co scrollIntoView(),
   focus() hoac lien ket sau van co the yeu cau trinh duyet cuon ca document, lam vo ung dung
   nhich len va cat mat phan tren cua header. Ghim rieng vo ung dung vao viewport de document
   khong con la mot tang cuon; .content_main van cuon binh thuong ben trong.
   ========================================================================================= */
@media screen and (max-width: 991.98px) {
    .wrap_all_site {
        position: fixed;
        inset: 0;
        width: 100%;
        height: auto;
        min-height: 0;
        overflow: hidden;
    }
    .content_main {
        max-height: calc(100dvh - 57px);
        -webkit-overflow-scrolling: touch;
    }
}

/* =========================================================================================
   BẢNG THÀNH THẺ trên điện thoại  (18/09/2026)
   Gắn class "xf-the" cho <table> là xong. Dưới 820px bảng gập thành từng THẺ: mỗi ô một dòng,
   nhãn cột bên trái — giá trị bên phải, cách nhau MỘT đường kẻ dọc liền mạch.
   Nhãn do js/xiris_bang_the.js chép từ <thead> xuống, dựng thành thẻ thật .xf-nh/.xf-gt.

   ⚠⚠ MỌI LUẬT PHẢI VIẾT "> tbody" / "> thead", KHÔNG viết kiểu hậu duệ (22/09/2026).
     Bảng LỒNG TRONG BẢNG có thật: màn Lịch sử bảo trì bấm một thiết bị thì xổ ra bảng hạng
     mục nằm hẳn bên trong <td> của bảng ngoài. Viết `table.xf-the tbody > tr > td` thì luật
     của bảng ngoài rơi luôn xuống ô của bảng con — bảng con nào CỐ Ý không gập thẻ (ma trận
     mốc tuần) sẽ bị `display:block` xé nát. Dấu ">" trước tbody chặn đúng chỗ đó.
     Mọi bảng đều có <thead>/<tbody> là con trực tiếp (trình duyệt tự chèn tbody nếu thiếu)
     nên đổi sang con trực tiếp KHÔNG đổi hành vi của bảng phẳng. js/xiris_bang_the.js đã
     được vá cùng lúc bằng ":scope >" vì y hệt lý do.

   ⚠⚠ BỐN THỨ PHẢI GỠ, thiếu một cái là thẻ vỡ — đều là bài học từ màn Pha hóa chất 18/09:
     1. min-width của bảng  -> bảng vẫn kéo rộng, thẻ không co lại được
     2. width:1% của cột số -> ô co còn ~28px, số tràn ra đè lên nhãn. Luật kiểu
        `.xx-tb td.num{width:1%}` có độ ưu tiên (0,2,1), phải đè bằng vế mạnh hơn + !important
     3. position:sticky của cột dính -> ô nhảy khỏi thẻ, đè lên ô khác
     4. đệm dọc của <td> -> đường kẻ dọc bị hở 16px giữa hai hàng, nhìn ra nhiều đoạn rời rạc.
        Dời đệm xuống hai thẻ con thì đường kẻ nối liền một mạch.
   ========================================================================================= */
/* ⚠⚠ NHÃN CHỈ ĐƯỢC HIỆN Ở CHẾ ĐỘ THẺ. Phải ẩn ở NGOÀI @media, không thì trên màn rộng
   nhãn hiện ra như chữ thường ngay trong ô: "Mã phiếuPVH-20260813-00052", "Người thực
   hiệnNV Vận Hành 2"... (đã xảy ra 18/09/2026 trên cả 5 màn vừa bật thẻ).
   .xf-gt là <span> nên ở màn rộng nó vẫn nội tuyến, không đổi gì bố cục bảng. */
table.xf-the .xf-nh { display: none; }

/* ⚠⚠ PHẢI GHI "screen and", đừng bỏ đi (22/09/2026).
   Lúc IN, bề ngang mà `max-width` đem ra so là KHỔ GIẤY chứ không phải màn hình: A4 dọc
   ~794px, trừ lề còn ~718px — nhỏ hơn 820 nên khối này khớp ngay giữa bản in. Trong khi
   js/xiris_bang_the.js lại dán nhãn theo matchMedia của MÀN HÌNH, máy tính thì không dán.
   Kết quả: bản in ra một cột ô xếp dọc KHÔNG CÓ NHÃN, không ai đọc được.
   Thẻ vốn là khuôn dựng CHO điện thoại; giấy thì bảng thật mới đúng. */
@media screen and (max-width: 820px) {
    :has(> table.xf-the) { overflow-x: visible; }

    table.xf-the {
        display: block;
        width: 100%;
        min-width: 0 !important;
        max-width: 100%;
        border-collapse: separate;
        border-spacing: 0;
    }
    table.xf-the > thead { display: none; }
    table.xf-the > tbody,
    table.xf-the > tbody > tr,
    table.xf-the > tbody > tr > td { display: block; }
    /* ⚠⚠ PHẢI TRẢ LẠI [hidden]. Luật `display:block` ở trên có độ ưu tiên (0,1,3), mạnh hơn
       luật mặc định `[hidden]{display:none}` (0,1,0) của trình duyệt — nên hàng nào bị JS ẩn
       bằng thuộc tính hidden sẽ VẪN HIỆN trong chế độ thẻ.
       Triệu chứng đã gặp ở màn Giám sát phiếu vận hành 18/09/2026: hàng chi tiết "mở được mà
       không đóng được" — nút đóng vẫn chạy, đặt hidden=true đàng hoàng, nhưng CSS giữ nó hiện.
       Bất cứ bảng nào dùng hidden để đóng/mở hàng đều dính, nên chặn ngay tại bộ dùng chung. */
    table.xf-the > tbody > tr[hidden],
    table.xf-the > tbody > tr > td[hidden],
    table.xf-the [hidden] { display: none !important; }
    /* ⚠⚠ Gỡ CẢ BA: width, min-width và max-width (22/09/2026).
       Bản trước chỉ gỡ `width` vì cái bẫy gặp đầu tiên là `width:1%` của cột số. Màn Đồng
       hồ ghim kiểu khác: `.nh-tb.tt td:first-child{min-width:96px;max-width:96px}` cho khổ
       hẹp — vào chế độ thẻ thì ô tiêu đề của thẻ bị bóp còn 96px, chữ rớt từng dòng. Trong
       thẻ ô nào cũng là một khối chiếm trọn bề ngang, nên mọi ràng buộc bề rộng của bản
       bảng đều vô nghĩa: gỡ sạch một lượt cho khỏi vấp tiếp. */
    table.xf-the > tbody > tr > td,
    table.xf-the > tbody > tr > td[class] {
        width: auto !important;
        min-width: 0 !important;
        max-width: none !important;
    }

    table.xf-the > tbody > tr {
        /* Xếp dọc bằng flex để ô tiêu đề được kéo LÊN ĐẦU thẻ (order:-1). Thứ tự cột trong
           bảng thường bắt đầu bằng STT, nhưng trên thẻ thì mã phiếu / tên mới là thứ người ta
           tìm trước; STT vẫn giữ, chỉ tụt xuống thành một dòng bình thường. */
        /* ⚠ CỠ CHỮ CỦA CẢ THẺ. Bản bảng dùng 13px cho màn rộng — có chuột, màn lớn, ngồi xa
           vẫn đọc được. Điện thoại cầm trên tay thì phải TO HƠN, không phải nhỏ hơn. Đặt ở
           <tr> để mọi ô con thừa hưởng, khỏi đi khai lại từng chỗ. */
        font-size: 14px;
        display: flex;
        flex-direction: column;
        margin-bottom: 10px;
        border: 1px solid var(--xf-line);
        border-radius: 10px;
        overflow: hidden;
        background: #fff;
    }
    html[data-xtheme="dark"] table.xf-the > tbody > tr { background: #0d1b2a; }

    table.xf-the > tbody > tr > td {
        position: static !important;
        box-shadow: none !important;
        background: transparent;
        border-left: 0;
        border-bottom: 0;
        /* ⚠ Gỡ CẢ BỐN PHÍA, không chỉ trái–dưới (22/09/2026). Bản trước chỉ gỡ hai
           cạnh vì mọi bảng gặp lúc đó đều chỉ kẻ đường ngang. Bảng Phiếu vận hành thì
           `.pvv-table td{border:1px solid}` kẻ đủ bốn phía — gập thẻ ra mỗi ô một cái
           khung, trông như bảng lồng trong thẻ. Ô tiêu đề và thanh nút vẫn giữ được
           đường kẻ của mình vì luật riêng của chúng đặc hiệu hơn luật này. */
        border-top: 0;
        border-right: 0;
        padding: 0 12px;
        text-align: right;
        white-space: normal !important;
    }
    table.xf-the > tbody > tr > td[data-nhan] { display: flex; align-items: stretch; }

    table.xf-the .xf-nh {
        display: block;
        flex: 0 0 148px;
        max-width: 44%;
        min-width: 0;
        align-self: center;
        padding: 9px 11px 9px 0;
        /* 12px chu khong phai 10.5px: khuôn thẻ sinh ra CHO điện thoại, để chữ nhỏ hơn cả bản
           bảng trên máy tính là sai từ gốc (chủ dự án 22/09/2026). */
        font-size: 12px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .3px;
        color: var(--xf-mut);
        text-align: left;
        line-height: 1.3;
        overflow-wrap: anywhere;
    }
    table.xf-the .xf-gt {
        flex: 1 1 auto;
        min-width: 0;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: flex-end;
        gap: 0 4px;
        padding: 9px 0 9px 11px;
        border-left: 1px solid var(--xf-line);
        text-align: right;
        line-height: 1.35;
        overflow-wrap: anywhere;
    }

    /* Ô ĐẦU = tiêu đề thẻ: không chia cột, căn trái, nền hơi đậm để tách khỏi khối số. */
    table.xf-the > tbody > tr > td.xf-tieude {
        order: -1;
        /* Tiêu đề thẻ (mã phiếu / tên) là thứ người ta quét mắt tìm trước — cho to hơn hẳn. */
        font-size: 15px;
        padding: 10px 12px;
        text-align: left;
        background: rgba(125,125,125,.08);
        border-bottom: 1px solid var(--xf-line);
    }
    table.xf-the > tbody > tr > td.xf-tieude > .xf-nh { display: none; }
    table.xf-the > tbody > tr > td.xf-tieude > .xf-gt {
        display: block;
        padding: 0;
        border-left: 0;
        text-align: left;
    }

    /* ===== Ô CUỐI KHÔNG CÓ NHÃN = CỤM NÚT -> MỘT THANH NÚT TRẢI TRỌN BỀ NGANG THẺ =====
       Chủ dự án 22/09/2026: *"nút xem cho full … cái nào nhiều nút thì chỉnh width lại nhưng
       phải full hàng đó"*.
       Trước đó nút giữ đúng bề rộng theo chữ nên nằm nép một góc cạnh khoảng trống rộng gần
       bằng cả thẻ — mà trên điện thoại đây lại chính là thứ người ta bấm nhiều nhất, và ngón
       tay thì không nhắm được vào một nút con con.
       Nay: MỘT nút thì ăn trọn hàng, NHIỀU nút thì chia đều nhau nhưng vẫn kín hàng.

       ⚠ Phải trải HAI TẦNG. Có màn đặt nút trực tiếp trong ô (Nhật ký vận hành, Phiếu vận
         hành, Lịch sử pha), có màn bọc cụm nút trong một lớp trung gian: <div class="nh-act">
         ở Nhập/Xuất hàng, <span class="sc-tt-nut"> ở Danh sách sự cố. Chỉ trải tầng ngoài thì
         mấy màn kia vẫn y như cũ, nút nép một góc trong một lớp bọc rộng hết hàng.
       ⚠ CHỈ áp cho ô KHÔNG CÓ NHÃN (`:not([data-nhan])`) — tức cột mà tiêu đề để trống, theo
         quy ước của bộ này thì đó đúng là cột nút. Ô có nhãn vẫn là dòng "nhãn – giá trị"
         bình thường, đừng biến giá trị thành nút. */
    /* ⚠⚠ `:not([colspan])` KHÔNG ĐƯỢC BỎ (22/09/2026). Hàng chi tiết xổ ra thường chỉ có
       MỘT ô <td colspan="n">, tức vừa là :last-child vừa không có nhãn — đúng cả hai điều
       kiện ở đây, nên nó bị coi là cụm nút: ô thành flex, mọi con `flex:1 1 0`.
       Bắt được ở màn Giám sát phiếu vận hành: hộp xem nhanh và nút "Mở phiếu đầy đủ" xếp
       CẠNH NHAU mỗi cái nửa hàng, nội dung phiếu co còn 142px — nhìn y như bị cắt cụt.
       ⚠ Đã thử cách "để nó dính rồi gỡ ngược bằng một khối td[colspan] riêng" — SAI: luật gỡ
         đó (0,3,5) đè luôn CSS của từng màn (0,1,0), giết `display:flex`+`gap` của mấy lớp
         bọc chi tiết (.sc-ct-luoi ở Danh sách sự cố, #mbb_ct_hop ở Pha hóa chất, bảng con ở
         Lịch sử bảo trì) — mà chẳng màn nào yêu cầu. Loại ô gộp ra NGAY TỪ ĐẦU mới đúng: nó
         rơi về luật có sẵn và bộ dùng chung không đụng tới con của nó một chút nào. */
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        padding: 10px 12px;
        text-align: left;
        border-top: 1px solid var(--xf-line);
    }
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) > *,
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) > div > *,
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) > span > * {
        flex: 1 1 0;
        min-width: 0;
    }
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) > div,
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) > span {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
    }
    /* ⚠⚠ NÚT BIỂU TƯỢNG VUÔNG THÌ KHÔNG ĐƯỢC GIÃN. Luật `flex:1 1 0` ở trên cố ý cho
       MỌI con của ô nút, nhưng nút sao chép link (.xiris-copy, xem js/xiris_copy.js) là ô
       vuông 26×26 — bị kéo bằng nửa hàng thì ra một thanh xám dài thượt cạnh nút "Xem chi
       tiết", nhìn như lỗi render. Đã vá riêng cho Danh sách sự cố 18/09/2026; chặn thẳng ở
       đây để màn nào gắn nút chép sau này khỏi vấp lại. */
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) .xiris-copy {
        flex: 0 0 auto;
    }
    /* Nút vốn căn chữ sang trái; kéo rộng hết hàng rồi mà chữ vẫn nép trái thì trông như lỗi.
       Kèm `white-space:normal` cho nhãn dài ("Duyệt phiếu vận hành") xuống dòng thay vì tràn. */
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) a,
    table.xf-the > tbody > tr > td:last-child:not([data-nhan]):not([colspan]) button {
        justify-content: center;
        text-align: center;
        white-space: normal;
    }
    /* Hàng gộp (colspan: hàng TỔNG, hàng rỗng, hàng chi tiết xổ ra) giữ nguyên kiểu khối.
       ⚠⚠ PHẢI CÓ :not([data-nhan]) CHO ĐỦ ĐỘ ĐẶC HIỆU (22/09/2026). Luật này viết từ đầu với
          đúng ý "ô gộp giữ kiểu khối", nhưng nó chỉ (0,2,4) nên THUA luật "ô cuối không nhãn
          = thanh nút" ở ngay trên (0,3,4) — mà ô gộp thì vừa là :last-child vừa không có
          nhãn, dính trọn cả hai vế.
          Hậu quả bắt được ở màn Giám sát phiếu vận hành: hàng chi tiết xổ ra chỉ có một
          <td colspan="6">, nên hộp xem nhanh và nút "Mở phiếu đầy đủ" bị xếp CẠNH NHAU mỗi
          cái nửa hàng — nội dung phiếu co còn 142px, nhìn y như bị cắt cụt.
       ⚠ Gỡ luôn flex của các con: luật thanh nút đặt `flex:1 1 0` cho cả con lẫn cháu. */
    table.xf-the > tbody > tr > td[colspan] { display: block; text-align: left; padding: 10px 12px; }
}
@media screen and (max-width: 820px) {
    /* ===== CÂN ĐỐI LẠI THẺ (18/09/2026) =====
       Chủ dự án: "nút bấm không được, với nhìn không cân đối".
       Ba chỗ chỉnh:
       1. Nút/biểu tượng nằm chung ô với chữ (nút xổ cạnh mã phiếu) phải KHÔNG ĐƯỢC CO —
          mặc định flex cho co, nên khi mã phiếu dài chiếm hết chỗ thì nút bị bóp dẹp lại,
          bấm không trúng.
       2. Cụm mã phiếu + nút xổ để nguyên một khối, không cho ngắt giữa chữ và nút.
       3. Ô KHÔNG CÓ NHÃN mà cũng không phải ô cuối (ví dụ cột ô tick, chỉ chứa dấu "—")
          thu nhỏ lại cho gọn, chứ để nguyên một dòng trống nhìn như lỗi. */
    table.xf-the .xf-gt button,
    table.xf-the .xf-gt .btn,
    table.xf-the .xf-gt [class*="-nut"],
    table.xf-the .xf-gt [class*="-xo"] { flex: 0 0 auto; }

    table.xf-the .xf-gt > span,
    table.xf-the .xf-gt > a { min-width: 0; }

    table.xf-the > tbody > tr > td:not([data-nhan]):not(:last-child) {
        padding: 6px 12px 0;
        text-align: left;
        font-size: 11px;
        opacity: .75;
    }
}
@media screen and (max-width: 820px) {
    /* ===== Ô NHẬP LIỆU TRONG THẺ (18/09/2026) =====
       Bảng lập phiếu (Nhập hàng / Xuất hàng) có <input>, <select> và select2 ngay trong ô.
       Ở chế độ bảng chúng được khai bề rộng cứng theo cột; gập thành thẻ thì bề rộng đó
       thành vô nghĩa — ô nhập bé tí nằm lệch một góc, ngón tay bấm không trúng.
       Cho chúng trải trọn cột giá trị: dễ chạm, và số căn phải nên vẫn dễ đối chiếu.
       ⚠ select2 tính bề rộng lúc khởi tạo theo <select> gốc, nên phải !important mới đè được. */
    table.xf-the .xf-gt input:not([type="checkbox"]):not([type="radio"]),
    table.xf-the .xf-gt select,
    table.xf-the .xf-gt textarea {
        /* flex thay vì width:100% — để đơn vị gộp kèm (".xf-dv") còn chỗ đứng cạnh ô nhập,
           không bị đẩy xuống dòng dưới. */
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
        max-width: 100%;
        text-align: right;
    }
    /* Ô ĐƠN VỊ bị giấu vì đã gộp vào số; đơn vị in nhỏ và mờ, đứng ngay sau con số. */
    table.xf-the > tbody > tr > td.xf-an-dv { display: none; }
    table.xf-the .xf-dv {
        flex: 0 0 auto;
        margin-left: 4px;
        font-size: 11.5px;
        color: var(--xf-mut);
    }
    table.xf-the .xf-gt .select2-container {
        width: 100% !important;
        min-width: 0 !important;
    }
    table.xf-the .xf-gt .select2-container .select2-selection__rendered { text-align: left; }
}

/* =========================================================================================
   Ô NHẬP KHÔNG ĐƯỢC CHÌM VÀO NỀN THẺ  (22/09/2026)
   Chủ dự án: "mấy cái input khó thấy quá, kiểu bị chìm á… mấy input khác cũng chìm mà".
   Gốc bệnh nằm ở chính hai biến màu phía trên tệp này:
     bản SÁNG  --xf-field:#fff    mà --xf-card cũng #fff   -> ô nhập TRÙNG HỆT nền thẻ
     bản TỐI   --xf-field:#0d1c2e nằm trên thẻ navy        -> chênh nhau không đáng kể
   Cả ô chỉ còn được nhận ra nhờ một đường viền nhạt. Đã chỉnh THẲNG TẠI BIẾN (#f4f7fb /
   #13273d) nên mọi màn dùng --xf-field tự khỏi, khỏi đi vá từng trang. Trị số cố ý chỉ lệch
   nhẹ: đủ để mắt tách ô ra khỏi nền, không biến biểu mẫu thành một mảng xám loang lổ.

   ĐÁNH DẤU Ô BẮT BUỘC VÀ BÁO LỖI ĐÚNG LÚC
   Bản trước tô nền hổ phách cho MỌI ô bắt buộc còn trống ngay khi mở trang. Có trả lời được
   câu "sao vào phiếu không biết phải điền", nhưng nhìn như cả biểu mẫu đang báo lỗi — chủ dự
   án hỏi lại "không còn cách nào nhìn chuyên nghiệp hơn hả". Nay tách bạch hai việc:
     · ĐANG YÊU CẦU   -> một vạch nhấn mảnh ở mép trái ô. Lướt mắt là thấy, không mang sắc
       thái cảnh báo.
     · ĐANG SAI/THIẾU -> mới tô hổ phách, và CHỈ SAU KHI người dùng đã đụng vào ô rồi bỏ
       trống, hoặc đã bấm gửi.
   ⚠ Điểm mấu chốt là :user-invalid chứ không phải :invalid. :invalid đúng ngay từ lúc trang
     vừa mở nên mới gây ra màn hình đỏ rực; :user-invalid đợi người dùng thật sự tương tác.
   ========================================================================================= */
/* ⚠ KHÔNG đánh dấu ô bắt buộc bằng vạch màu ở mép ô.
   Đã thử 22/09/2026 (vạch nhấn 3px bên trái) và chủ dự án bác ngay: "nhìn không giống
   input gì hết, trông giống con nít vậy, màu mè quá". Đúng — trên một biểu mẫu nhiều ô,
   mỗi ô một vệt màu thì trang biến thành cầu vồng, mà vệt đó cũng không nói được nó nghĩa
   là gì. Dấu sao đỏ ở NHÃN đã làm đúng việc đó rồi, gọn và ai cũng hiểu.
   Ô nhập chỉ cần ba thứ, không hơn: nền khác nền thẻ, viền rõ, và lõm nhẹ vào trong. */
.xf-form input[type=text], .xf-form input[type=date], .xf-form input[type=number],
.xf-form select, .xf-form textarea,
.nh-wrap input[type=text], .nh-wrap input[type=date], .nh-wrap input[type=number],
.nh-wrap select, .nh-wrap textarea {
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
}
html[data-xtheme="dark"] .xf-form input[type=text],
html[data-xtheme="dark"] .xf-form select,
html[data-xtheme="dark"] .xf-form textarea,
html[data-xtheme="dark"] .nh-wrap input[type=text],
html[data-xtheme="dark"] .nh-wrap select,
html[data-xtheme="dark"] .nh-wrap textarea {
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, .45);
}
/* Thiếu/sai THẬT SỰ mới đổi màu, và chỉ sau khi người dùng đã đụng vào ô hoặc bấm gửi
   (:user-invalid, không phải :invalid). Viền thôi, không tô nền — tô nền cả ô trên một
   biểu mẫu dài nhìn rất nặng. */
.xf-form :user-invalid,
.nh-wrap :user-invalid {
    border-color: #e0774a !important;
}

/* =========================================================================================
   Ô NHẬP TO RÕ RÀNG HƠN  (22/09/2026 — chủ dự án: "cho ô input to ra rõ ràng hơn")
   Các màn đang khai `padding:9px 11px` và không đặt chiều cao, nên ô cao khoảng 37px —
   nhỏ so với cỡ chữ chung của trang, và trên điện thoại thì dưới ngưỡng chạm thoải mái.
   Nâng lên 44px: đây là cỡ tối thiểu quen dùng cho mục tiêu chạm, gõ trên máy cũng dễ nhìn.
   ⚠ Tiền tố `html ` chỉ để NÂNG ĐỘ ƯU TIÊN lên (0,2,2), thắng luật `.nh-wrap input[type=text]`
     (0,2,1) khai trong từng trang — khối <style> của trang nằm sau tệp này nên cùng độ ưu
     tiên là trang thắng. Cách này sạch hơn rải !important khắp nơi.
   ========================================================================================= */
html .xf-form input[type=text],
html .xf-form input[type=date],
html .xf-form input[type=number],
html .xf-form select,
html .nh-wrap input[type=text],
html .nh-wrap input[type=date],
html .nh-wrap input[type=number],
html .nh-wrap select {
    min-height: 44px;
    padding: 11px 13px;
    font-size: 14px;
    line-height: 1.35;
}
html .xf-form textarea,
html .nh-wrap textarea {
    min-height: 92px;
    padding: 11px 13px;
    font-size: 14px;
    line-height: 1.45;
}
/* select2 dựng lại ô chọn bằng thẻ riêng nên phải nâng theo, không thì ô chọn lùn hơn hẳn
   mấy ô gõ đứng cạnh. */
html .xf-form .select2-container--default .select2-selection--single,
html .nh-wrap .select2-container--default .select2-selection--single {
    min-height: 44px;
    padding: 6px 6px 0;
}
html .xf-form .select2-container--default .select2-selection--single .select2-selection__rendered,
html .nh-wrap .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 30px;
    font-size: 14px;
}

/* =========================================================================================
   Ô ĐANG GÕ PHẢI NỔI HẲN LÊN  (22/09/2026)
   Chủ dự án: "focus như này có border đồ lên chứ không phải con trỏ chuột vô là xong".
   Đúng — chỉ có con trỏ nhấp nháy thì trên một biểu mẫu dài không biết mình đang đứng ở ô
   nào, nhất là khi vừa vào trang con trỏ đã tự nhảy vào một ô.
   Ô đang gõ nay đổi màu viền sang màu nhấn, dày lên, kèm quầng sáng quanh ô. Quầng cũng đã
   nâng độ đậm ở hai biến phía trên (16%/22% -> 30%/38%) vì mức cũ gần như không thấy.
   ⚠ Tiền tố `html ` để nâng độ ưu tiên lên (0,2,2) — khối <style> của từng màn nằm SAU tệp
     này và cũng khai :focus, cùng độ ưu tiên thì trang thắng. */
html .xf-form input:focus,
html .xf-form select:focus,
html .xf-form textarea:focus,
html .nh-wrap input:focus,
html .nh-wrap select:focus,
html .nh-wrap textarea:focus {
    outline: none;
    border-color: var(--xf-accent);
    border-width: 2px;
    box-shadow: 0 0 0 3px var(--xf-field-ring);
}
/* select2 không nhận :focus trên thẻ gốc — nó dựng ô riêng và gắn cờ khi mở. */
html .xf-form .select2-container--open .select2-selection--single,
html .nh-wrap .select2-container--open .select2-selection--single {
    border-color: var(--xf-accent) !important;
    box-shadow: 0 0 0 3px var(--xf-field-ring) !important;
}

/* =========================================================================================
   ĐÈ MÀU Ô NHẬP CỦA BẢN TỐI  (22/09/2026)
   Suốt mấy lượt đổi --xf-field mà màn tối không nhúc nhích, hoá ra thủ phạm là
   css/xiris_dark.css dòng 311-316:

       html[data-xtheme="dark"] .form-control,
       html[data-xtheme="dark"] select, html[data-xtheme="dark"] input[type="text"], …
       html[data-xtheme="dark"] textarea { background: #0d1c2e; … }

   Nó ghi THẲNG MÃ MÀU vào phần tử chứ không đi qua biến — nên quét tệp đó bằng từ khoá
   "--xf-field" không ra gì, và độ ưu tiên (0,2,2) của nó lại thắng luật (0,2,1) của từng màn
   vốn mới là chỗ đọc --xf-field.
   ⚠ BÀI HỌC: đừng chỉ quét theo TÊN BIẾN khi truy một màu không chịu đổi — phải quét cả mã
     màu cứng. Cách chắc nhất vẫn là nhìn tab Styles của DevTools: nó chỉ đúng tệp và dòng.

   Dưới đây chép đúng bộ chọn đó rồi trỏ về biến. Tệp này nạp SAU xiris_dark.css nên cùng độ
   ưu tiên là nó thắng, và từ nay bản tối đi theo --xf-field như bản sáng.
   ========================================================================================= */
html[data-xtheme="dark"] .form-control,
html[data-xtheme="dark"] select,
html[data-xtheme="dark"] input[type="text"],
html[data-xtheme="dark"] input[type="number"],
html[data-xtheme="dark"] input[type="password"],
html[data-xtheme="dark"] input[type="date"],
html[data-xtheme="dark"] textarea {
    background: var(--xf-field);
    border-color: var(--xf-field-brd);
}

/* =========================================================================================
   PLACEHOLDER: ĐỌC ĐƯỢC, KHÔNG LÀM CHÌM
   ⚠ 22/09/2026 từng hiểu ngược ý chủ dự án. Anh ấy nói "màu đó làm chìm placeholder"
     — tức NỀN xanh đậm #1e4066 nuốt mất chữ gợi ý — còn mình lại đi hạ độ đậm của
     placeholder xuống nữa, càng khó đọc. Nền nay đã đổi sang xám trung tính #1d2836
     nên chữ gợi ý tự đọc được; đặt mức tương phản vừa đủ, KHÔNG hạ thêm.
   ========================================================================================= */
html[data-xtheme="dark"] input::placeholder,
html[data-xtheme="dark"] textarea::placeholder,
html[data-xtheme="dark"] .form-control::placeholder {
    color: rgba(226, 238, 252, .62);
    opacity: 1;
}
html[data-xtheme="dark"] input::placeholder,
html[data-xtheme="dark"] textarea::placeholder,
html[data-xtheme="dark"] .form-control::placeholder {
    color: rgba(226, 238, 252, .34);
    opacity: 1;
}

/* =========================================================================================
   CÁC MÀN PHIẾU TRONG NHẬT KÝ VẬN HÀNH  (22/09/2026 — chủ dự án: "làm cho mấy phiếu trong
   nhật ký vận hành đi nha")
   Bốn màn phiếu dùng bốn lớp bao khác nhau, nên khuôn ô nhập ở trên (vốn chỉ nhắm .xf-form
   và .nh-wrap) không với tới ba trong số đó:
       .nh-wrap    Ghi chỉ số đồng hồ      (đã có sẵn ở khuôn trên)
       .ts-wrap    Ghi thông số vận hành
       .pva-field  Lập phiếu vận hành
       .sct-f      Lập phiếu sự cố
   ⚠ Hai màn Ghi thông số vận hành và Lập phiếu vận hành đang khai `border:2px solid
     var(--nh-accent)!important` / `var(--brand)!important` — tức MỌI ô nhập đều viền dày màu
     nhấn. Đó đúng là kiểu "màu mè" chủ dự án đã bác ở màn xuất/nhập hàng: viền màu nên dành
     riêng cho ô ĐANG GÕ, dùng cho mọi ô thì mất hết ý nghĩa và trang thành rực rỡ.
     Vì bên đó có !important nên ở đây buộc phải !important mới đè được.
   ⚠ .sct-f còn lấy `var(--d-card)` làm nền ô nhập — tức đúng bằng nền thẻ, chìm y hệt lỗi gốc.
   ========================================================================================= */
html .ts-wrap input[type=text],
html .ts-wrap input[type=number],
html .ts-wrap select,
html .pva-field input[type=text],
html .pva-field input[type=number],
html .pva-field select,
html .sct-f input[type=text],
html .sct-f input[type=number],
html .sct-f select {
    min-height: 44px;
    padding: 11px 13px;
    font-size: 14px;
    line-height: 1.35;
    border: 1.5px solid var(--xf-field-brd) !important;
    border-radius: 9px;
    background: var(--xf-field) !important;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
}
html .ts-wrap textarea,
html .pva-field textarea,
html .sct-f textarea {
    min-height: 92px;
    padding: 11px 13px;
    font-size: 14px;
    line-height: 1.45;
    border: 1.5px solid var(--xf-field-brd) !important;
    border-radius: 9px;
    background: var(--xf-field) !important;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
}
html[data-xtheme="dark"] .ts-wrap input[type=text],
html[data-xtheme="dark"] .ts-wrap select,
html[data-xtheme="dark"] .ts-wrap textarea,
html[data-xtheme="dark"] .pva-field input[type=text],
html[data-xtheme="dark"] .pva-field select,
html[data-xtheme="dark"] .pva-field textarea,
html[data-xtheme="dark"] .sct-f input[type=text],
html[data-xtheme="dark"] .sct-f select,
html[data-xtheme="dark"] .sct-f textarea {
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, .45);
}
/* Viền màu CHỈ dành cho ô đang gõ. */
html .ts-wrap input:focus,
html .ts-wrap select:focus,
html .ts-wrap textarea:focus,
html .pva-field input:focus,
html .pva-field select:focus,
html .pva-field textarea:focus,
html .sct-f input:focus,
html .sct-f select:focus,
html .sct-f textarea:focus {
    outline: none;
    border-color: var(--xf-accent) !important;
    border-width: 2px !important;
    box-shadow: 0 0 0 3px var(--xf-field-ring);
}

/* =========================================================================================
   BỘ LỌC THÀNH TẤM TRƯỢT trên điện thoại  (22/09/2026)
   Gắn class "xf-loc" cho khối lọc (thẻ biểu mẫu, hoặc div với màn lọc bằng AJAX);
   phần chạy nằm ở js/xiris_loc.js.
   ⚠⚠ Mấy luật dưới viết "html .xf-loc" chứ không phải ".xf-loc" trơn: bỏ chữ html là
      còn (0,1,0), BẰNG luật của từng màn (ví dụ `.ls-loc{display:grid}`) mà CSS của màn
      nạp SAU tệp này nên nó thắng — bộ lọc sẽ không bao giờ thu lại.
   Dưới 820px: biểu mẫu lọc thu lại, chỉ còn một thanh [Bộ lọc (n)]; bấm vào thì nó trượt lên
   từ đáy màn hình, có nền mờ phía sau. Màn rộng giữ nguyên bố cục ngang như cũ.
   ========================================================================================= */
@media (max-width: 820px) {
    .xf-loc-thanh { display: flex; gap: 8px; margin: 0 0 12px; }
    .xf-loc-mo {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        min-height: 42px;
        padding: 0 16px;
        border: 1px solid var(--xf-line);
        border-radius: 10px;
        background: var(--xf-card);
        color: var(--xf-ink);
        font: inherit;
        font-weight: 600;
        cursor: pointer;
    }
    .xf-loc-dem {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 20px;
        height: 20px;
        padding: 0 6px;
        border-radius: 999px;
        background: var(--xf-accent);
        color: #fff;
        font-size: 11px;
        font-weight: 700;
    }
    .xf-loc-dem[hidden] { display: none; }

    html .xf-loc { display: none; }
    html .xf-loc.mo {
        /* ⚠ ĐỪNG dùng display:block. Biểu mẫu lọc gốc là flex NGANG có gap; đổi sang block là
           triệt luôn gap, các ô dính sát nhau và nhãn đè lên ô phía trên (chủ dự án 22/09/2026:
           "sao dính nhau quá vậy"). Giữ flex, chỉ xoay trục sang DỌC là vừa xếp đúng một cột
           vừa còn nguyên khoảng cách. */
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 14px;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 10050;
        max-height: 86dvh;
        overflow-y: auto;
        margin: 0;
        border-radius: 16px 16px 0 0;
        /* ⚠ Tam truot phai TU LO padding. Truoc day no an nho padding cua the trang
           (.gsp-card…), nhung co man go class the khoi <form> de xep lai bo cuc —
           luc do tam truot mo ra dinh sat mep man hinh. Khai o day thi man nao
           cung dung. */
        padding: 16px 16px calc(16px + env(safe-area-inset-bottom, 0px));
        box-shadow: 0 -12px 34px rgba(0, 0, 0, .38);
        /* ⚠⚠ NỀN PHẢI ĐẶC — MÃ MÀU CỐ ĐỊNH, KHÔNG DÙNG BIẾN.
           Tấm trượt thừa hưởng nền của thẻ (.gsp-card…), mà nền thẻ là var(--xf-card);
           ở bản tối biến đó là #00000047 — CHỈ ĐẶC 28%. Thế là nhìn xuyên thấu thấy cả
           bảng phía sau, chữ chồng lên chữ.
           Luật này đã chốt từ 26/08/2026 cho mọi thứ nổi lên che nội dung (hộp thoại,
           tấm trượt, tiêu đề dính): dùng HEX cố định, cấm --xf-card / --xf-zone /
           --*-panel, vì cả đám đều có thể là rgba mờ tuỳ theme. */
        background: #ffffff;
    }

    /* Mọi ô trong tấm trượt trải trọn bề ngang — biểu mẫu gốc xếp ngang nên nhiều ô khai
       bề rộng theo nội dung, để nguyên thì trong tấm trượt chúng so le nhau. */
    html .xf-loc.mo > * { width: 100%; min-width: 0; margin: 0; }
    html .xf-loc.mo .select2-container { width: 100% !important; }
    /* loc-chu-bang-nhau (25/09/2026, chu du an): o NGAY dung chu 16px con select2 chi
       12-13px -> nhin nhu hai bo o khac nhau (do tren man Pha hoa chat). Nen/vien/bo goc
       thi da giong nhau san, chi rieng co chu lech.
       ⚠⚠ DO DAC HIEU: man tu khai `.hc-page .select2-container--default
          .select2-selection--single .select2-selection__rendered` = (0,4,0) VA nam trong
          <style> cua trang nen dung SAU tep nay. Viet `html .xf-loc .select2-container
          .select2-selection__rendered` chi duoc (0,3,1) -> THUA. Phai bam theo dung chuoi
          class cua select2 de len (0,4,2).
       ⚠ Khong ha o ngay xuong: duoi 16px Safari iOS tu phong to trang khi cham vao o nhap.
       ⚠ Khong buoc `.mo`: co man de khoi loc hien thang (khong gap thanh tam truot) —
         chu van phai bang nhau. */
    html body .xf-loc .select2-container--default .select2-selection--single
        .select2-selection__rendered,
    html body .xf-loc select { font-size: 16px; }
    html[data-xtheme="dark"] body .xf-loc.mo { background: #0d1b2a; }
    /* Tiêu đề dính ở đầu tấm trượt cũng phải đặc, không thì chữ bên dưới trôi qua
       ngay dưới nó khi cuộn. `background: inherit` là đủ VÌ nền cha nay đã đặc. */
    .xf-loc-nen {
        position: fixed;
        inset: 0;
        z-index: 10049;
        background: rgba(8, 17, 30, .55);
        backdrop-filter: blur(2px);
    }
    html.xf-loc-khoa, html.xf-loc-khoa body { overflow: hidden; }

    .xf-loc-dau {
        position: sticky;
        top: 0;
        z-index: 1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 10px;
        margin: -4px -4px 0;
        padding: 6px 4px 10px;
        border-bottom: 1px solid var(--xf-line);
        background: inherit;
        font-size: 15px;
    }
    .xf-loc-dong {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 34px;
        height: 34px;
        border: 0;
        border-radius: 8px;
        background: transparent;
        color: var(--xf-mut);
        font-size: 16px;
        cursor: pointer;
    }
}

/* -----------------------------------------------------------------------------------------
   PHAN TRANG VE BANG JS — cung mot kieu voi phan tren  (22/09/2026)
   Man nao loc bang AJAX thi khong co {PAGES} cua nv_generate_page ma tu ve <button>. Truoc
   day moi man tu khai lai kich thuoc/mau cho nut cua minh, thanh ra "mot kieu duy nhat" chi
   dung tren giay. Khai o day mot lan, man chi can:
       <div class="ten-rieng xf-pager"> … <button>1</button> … </div>
   roi XOA het luat nut rieng cua no. Bo cuc rieng (can giua hay dan hai dau) van giu duoc,
   vi CSS cua trang nap SAU tep nay nen thang o cung do dac hieu.
   Trang dang xem nhan bang class .on / .nay / .active / [aria-current=page] — ba ten dau la
   ba ten cac man san co, giu ca ba de khoi phai sua JS tung man.
   ----------------------------------------------------------------------------------------- */
.xf-pager button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    border: 1px solid var(--xf-line);
    border-radius: 8px;
    background: var(--xf-card);
    color: var(--xf-ink);
    font: inherit;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    transition: background .12s, border-color .12s, color .12s;
}
.xf-pager button:hover:not([disabled]):not(.on):not(.nay):not(.active) {
    border-color: var(--xf-accent);
    color: var(--xf-accent);
}
.xf-pager button.on,
.xf-pager button.nay,
.xf-pager button.active,
.xf-pager button[aria-current="page"] {
    background: var(--xf-accent-btn-dark);
    border-color: var(--xf-accent-btn-dark);
    color: #fff;
    font-weight: 600;
}
/* Nut "…" ngan cach cac quang so bi bo bot: khong bam duoc thi dung ve nhu nut. */
.xf-pager button[disabled] {
    border-color: transparent;
    background: transparent;
    color: var(--xf-mut);
    cursor: default;
}

/* -----------------------------------------------------------------------------------------
   PHAN TRANG VE BANG THE <a>  (22/09/2026)
   Man nao doi trang bang duong dan that (bam la tai lai trang) thi so trang la <a href>,
   khong phai <button>. Cung mot dien mao voi hai dang kia.
   ⚠⚠ PHAI co :link/:visited va ban neo cho che do toi. Theme khai
        a, a:link, a:active, a:visited { color:#1a3f5e }        (0,1,1)
        html[data-xtheme="dark"] a:link { … }                   (0,2,2)
   nen `.xf-pager a` tran (0,1,1) THUA ca hai — so trang bi cuop mau, ban toi thanh chu xanh
   dam tren nen xanh dam, gan nhu doc khong ra. Ba man tung phai tu vá bang `!important`
   dung vi cai nay. Giu them `!important` o rieng thuoc tinh color cho chac.
   ----------------------------------------------------------------------------------------- */
/* ⚠⚠ ">" LA CON TRUC TIEP, KHONG DUOC BO. Luat nay dat !important de thang bay a:link cuop
   mau. Viet ".xf-pager a" (hau due) thi no quet trung ca pager dang <ul class="pagination">
   cua nv_generate_page — o do the <a> KHONG mang class .active (class nam o <li> cha), nen
   luat "trang dang mo to chu trang" bi !important nay de bep: so trang dang mo thanh chu
   navy tren nen xanh dam, tuong phan 1,6:1. Chu du an bat duoc o ban SANG 22/09/2026.
   Voi ">" thi hai dang markup tach han nhau: pager the <a> co <a> la con truc tiep, con
   pager <ul> thi <a> la chau nen khong dinh luat nay. */
.xf-pager > a,
.xf-pager > a:link,
.xf-pager > a:visited {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    border: 1px solid var(--xf-line);
    border-radius: 8px;
    background: var(--xf-card);
    color: var(--xf-ink) !important;
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    text-decoration: none;
    transition: background .12s, border-color .12s, color .12s;
}
.xf-pager > a:hover:not(.on):not(.nay):not(.active),
.xf-pager > a:focus:not(.on):not(.nay):not(.active) {
    border-color: var(--xf-accent);
    color: var(--xf-accent) !important;
    text-decoration: none;
}
.xf-pager > a.on,
.xf-pager > a.nay,
.xf-pager > a.active,
.xf-pager > a[aria-current="page"],
html[data-xtheme="dark"] .xf-pager > a.on:link,
html[data-xtheme="dark"] .xf-pager > a.nay:link,
html[data-xtheme="dark"] .xf-pager > a.active:link,
html[data-xtheme="dark"] .xf-pager > a[aria-current="page"]:link {
    background: var(--xf-accent-btn-dark);
    border-color: var(--xf-accent-btn-dark);
    color: #fff !important;
    font-weight: 600;
    cursor: default;
}
/* Dau "…" giua hai quang so: khong phai nut, khong vien. */
.xf-pager .dots {
    display: inline-flex;
    align-items: center;
    padding: 0 4px;
    color: var(--xf-mut);
}
/* Trang DANG MO thi khong con la cho de bam — con tro phai noi dieu do. */
.xf-pager button.on,
.xf-pager button.nay,
.xf-pager button.active,
.xf-pager button[aria-current="page"] {
    cursor: default;
}

/* =========================================================================================
   NÚT "QUAY LẠI" DÙNG CHUNG  (22/09/2026)
   Chủ dự án: *"đồng bộ các trang ... trang chi tiết hay trang thêm đều thêm một nút Quay lại
   nằm bên phải của trang, với style như này, chế độ sáng, chế độ tối"*.

   Trước đây mỗi màn tự khai `.nh-back` một kiểu — đã đếm được 12 màn, 5 trong số đó còn phải
   tự vá lại bẫy `a:link` cướp màu. Nay chỉ còn MỘT nguồn duy nhất ở đây.

   Cách dùng: đặt class `xf-quaylai` lên thẻ `<a>` (hoặc `<button>`). Màn nào chưa có thì
   `js/xiris_quaylai.js` tự chèn — xem chú thích trong tệp đó.

   ⚠⚠ ĐỘ ĐẶC HIỆU CỐ Ý CAO: `html body a.xf-quaylai:link` = (0,2,3).
      Phải thắng cho bằng được hai thứ:
        · `a,a:link,a:visited{color:#1a3f5e}` của theme (0,1,1) — bẫy cướp màu kinh điển;
        · luật riêng của từng màn kiểu `.nh-wrap a.nh-back` (0,2,1), vốn nằm trong <style>
          của trang nên ĐỨNG SAU tệp này trong thứ tự tài liệu.
      Viết `.xf-quaylai` trơn (0,1,0) là thua cả hai, nút ra màu navy trên nền tối.
   ⚠ KHÔNG dùng !important: còn phải chừa đường cho màn nào cần đè lại có chủ đích.
   ========================================================================================= */
html body .xf-quaylai,
html body a.xf-quaylai,
html body a.xf-quaylai:link,
html body a.xf-quaylai:visited {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    /* ⚠⚠ BỘ SỐ CHUẨN = nút của màn Nhập hàng (chủ dự án 22/09/2026 chỉ đích danh: "lấy style
       nút này làm chuẩn làm cho mấy màn khác như vậy luôn"). Nguồn: .nh-export-btn trong
       themes/theme_xiris/modules/duan/nhap_hang_view.tpl.
       ⚠ ĐO THEO ĐỆM, KHÔNG đặt chiều cao cố định: đặt height + line-height:1 là nút lệch hẳn
         so với các nút cùng hàng (chúng chỉ khai padding). Để yên line-height cho nó thừa
         hưởng — ép line-height:1 làm nút thấp đi ~3px dù đệm giống hệt. */
    padding: 6px 12px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 600;
    /* ⚠⚠ NỀN CÓ SẴN Ở CẢ HAI BẢN MÀU, KHÔNG ĐỢI HOVER.
       Chủ dự án: *"chế độ sáng thì thêm background sẵn không cần hover mới hiện background"*.
       Bản gốc của màn Nhập hàng để nền = --nh-card (bản sáng là #fff) nên nút nhìn như không
       có nền, phải rê chuột vào mới thấy. Nay nền là một lớp tint nhạt của chính màu nhấn:
       vẫn nhẹ, nhưng nhìn phát biết đó là nút. */
    /* ⚠ 22/09/2026 — BẢN SÁNG PHẢI TRUNG TÍNH. Trước đây nền/viền/chữ đều là một lớp tint
       xanh của màu nhấn; chủ dự án: *"đừng có màu mè gì hết, chế độ sáng thì màu mè vậy nè"*.
       Nay xám trung tính — vẫn CÓ nền sẵn (không đợi hover) đúng yêu cầu cũ, chỉ bỏ màu.
       Bản TỐI giữ nguyên: chủ dự án chỉ đích danh bản sáng. */
    border: 1px solid #d7dde5;
    background: #f5f7f9;
    color: #334155;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
html body a.xf-quaylai:hover,
html body button.xf-quaylai:hover {
    background: #e9edf2;
    border-color: #c3ccd6;
    text-decoration: none;
}
html body .xf-quaylai i,
html body .xf-quaylai .xf-ql-mt {
    font-size: 12px;
    line-height: 1;
    /* Mũi tên không được kéo cao dòng chữ — giữ nguyên chiều cao nút. */
    flex: 0 0 auto;
}

html[data-xtheme="dark"] body .xf-quaylai,
html[data-xtheme="dark"] body a.xf-quaylai,
html[data-xtheme="dark"] body a.xf-quaylai:link,
html[data-xtheme="dark"] body a.xf-quaylai:visited {
    /* Bản tối: nền xanh đêm đặc + viền và chữ theo màu nhấn — đúng như ảnh chủ dự án gửi.
       ⚠ Nền phải ĐẶC (hex), không dùng --xf-card: bản tối của biến đó là #00000047 (mờ 28%),
         nút sẽ thành cửa kính (xem mục LUẬT modal/sticky phải HEX ĐẶC ở đầu tệp này). */
    background: #0f2438;
    border-color: rgba(56, 189, 248, .42);
    color: #7dd3fc;
}
html[data-xtheme="dark"] body a.xf-quaylai:hover,
html[data-xtheme="dark"] body button.xf-quaylai:hover {
    background: #15304a;
    border-color: rgba(56, 189, 248, .70);
}

/* ⚠ NÚT QUAY LẠI LUÔN ĐỨNG SÁT MÉP PHẢI CỦA HÀNG NÚT.
   22/09/2026, chủ dự án: *"chuyển qua phải"* — ở Chi tiết phiếu vận hành nút "Danh sách" đang
   dồn trái, nằm ngay cạnh "Xuất Excel / In PDF".
   ⚠⚠ BẮT BUỘC CÓ :last-child. Bỏ đi thì nút nào đứng ĐẦU hàng sẽ đẩy luôn MỌI nút phía sau
      sang phải — hỏng cả hàng. Chỉ phần tử CUỐI mới được quyền nuốt khoảng trống thừa.
   ⚠ Hàng không phải flex thì luật này vô hại: margin auto của hộp inline tính ra 0.
   Nhờ vậy .pvv-actions (đang bị đè justify-content:flex-start) đẩy được nút sang phải mà
   không phải sửa CSS riêng của từng màn. */
html body .xf-quaylai:last-child {
    margin-left: auto;
}

/* ⚠⚠ HAI LUẬT NÀY ĐÁ NHAU NẾU CÙNG BẬT — phải tắt cái trên đi.
   `margin-left:auto` nuốt TRỌN khoảng trống thừa, nên trong một hàng đã `justify-content:
   flex-end` thì nút cuối bị đẩy ra sát mép phải còn mấy nút kia ở lại bên TRÁI — đúng cái bố
   cục chủ dự án vừa bảo sửa. Hàng nào js/xiris_quaylai.js đã dồn phải (class .xf-hang-nut)
   thì trả margin về 0 để cả cụm nút đứng liền nhau bên phải. */
.xf-hang-nut .xf-quaylai:last-child {
    margin-left: 0;
}

/* Thanh chứa nút khi JS tự chèn: đẩy nút sát mép PHẢI của vùng nội dung. */
.xf-quaylai-bar {
    display: flex;
    justify-content: flex-end;
    margin: 0 0 12px;
}

/* ⚠⚠ ĐẶT CHỒNG LÊN HÀNG ĐẦU SẴN CÓ, KHÔNG CHIẾM HÀNG RIÊNG.
   22/09/2026 — bản đầu chèn nút làm con đầu của .content_main nên nó chiếm trọn một hàng và
   ĐẨY BREADCRUMB XUỐNG; chủ dự án bắt ngay: *"sao nút quay lại đẩy breadcrumb xuống là sao"*.
   Nay js/xiris_quaylai.js gắn nút vào chính hàng breadcrumb/tiêu đề và cho nó position:absolute
   -> không làm xê dịch bất cứ thứ gì.
   ⚠ JS chỉ gắn khi hàng đó KHÔNG bị cắt (overflow:visible) — nhét thẻ tuyệt đối vào hàng có
     overflow:hidden là mất hút, đúng bẫy tooltip đã gặp ở Pha hoá chất. */
.xf-quaylai-noi {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
}

/* ĐIỆN THOẠI: breadcrumb dài thì xuống hai, ba dòng, mà nút lại neo giữa hàng -> nút nằm đè
   lên chữ (đo thật 09/10/2026 trên màn Chi tiết bồn: "Pha & tiêu hao hóa chất" bị nút che mất
   một nửa). Neo nút lên MÉP TRÊN và bắt hàng chừa sẵn chỗ bên phải, chữ sẽ tự ngắt dòng trước
   khi chạm tới nút.
   Vẫn giữ absolute: chuyển về static là nút chiếm nguyên một hàng và đẩy breadcrumb xuống —
   đúng cái chủ dự án đã chê ở bản đầu. */
@media (max-width: 640px) {
    /* Nhân đôi class để nâng độ ưu tiên: hàng breadcrumb đang nhận padding-right 2px từ CSS
       khung của hệ thống, cùng hạng với luật một class nên hơn thua tuỳ thứ tự nạp tệp —
       thứ không nên đem ra đánh cược. Nhân đôi thì luôn thắng mà không phải dùng !important. */
    .xf-quaylai-cha.xf-quaylai-cha {
        padding-right: 104px;
    }
    .xf-quaylai-noi {
        top: 0;
        transform: none;
    }
}

/* Bản in không cần nút điều hướng. */
@media print {
    .xf-quaylai,
    .xf-quaylai-bar {
        display: none !important;
    }
}

/* =========================================================================================
   MŨI TÊN LÊN ĐẦU / XUỐNG CUỐI TRANG  (22/09/2026)
   Phần chạy ở js/xiris_len_xuong.js — nó tự dựng thẻ, màn không phải khai gì.
   ⚠ bottom 78px chứ không phải 16px: góc phải dưới đã có nút bánh răng của NukeViet, để 16px
     là bị nó đè lên mặt. Nút bánh răng cao ~44px + lề, nên đẩy lên 78px là vừa.
   ⚠ Chừa thêm safe-area cho iPhone có thanh gạt dưới màn hình.
   ========================================================================================= */
.xf-goc {
    position: fixed;
    /* ĐỨNG THẲNG HÀNG VỚI NÚT NHẮC VIỆC (29/09/2026, chủ dự án: *"nút lên xuống cho bằng với
       nút nhắc việc đi, sao lệch lên trên vậy"*). Đo trước khi sửa: nhắc việc đáy 40px, cụm
       mũi tên đáy 78px — lệch đúng 38px, nhìn như bị treo lơ lửng.

       ⚠ NÚT BÁNH RĂNG CỦA NUKEVIET NẰM NGAY DƯỚI, đừng tưởng góc này trống.
         .floating-btn (css/configuration.css) fixed right 10px, 35×35; và từ 991.98px trở
         xuống — ĐÚNG khoảng mà cụm mũi tên này hiện ra — style.responsive.css hạ nó xuống
         bottom 5px, tức nó chiếm dải đáy 5→40px.
         Cụm mũi tên để đáy 40px là NGỒI VỪA KHÍT NGAY TRÊN nó, không chạm.
       ⚠⚠ ĐỪNG hạ xuống thấp hơn 40px. Bản 29/09 từng cho đáy 16px ở khổ dưới 600px để bám
          theo nút nhắc việc — số nghe thì hợp lý nhưng 16px rơi thẳng vào giữa dải của bánh
          răng (5→40), hai nút chồng mặt nhau. Giữ 40px cho mọi khổ.
       ⚠ Bản 29/09 cũng từng dịch cụm này sang phải 62px để né bánh răng; chủ dự án bác:
         *"cho sát bên phải nha"* — nó đè lên nội dung và trông như bị lạc giữa trang.
         Né theo CHIỀU DỌC (đáy 40px) chứ không né theo chiều ngang. */
    right: calc(14px + env(safe-area-inset-right, 0px));
    bottom: calc(40px + env(safe-area-inset-bottom, 0px));
    z-index: 121;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.xf-goc[hidden] { display: none; }
.xf-goc-nut {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    padding: 0;
    border-radius: 50%;
    cursor: pointer;
    border: 1px solid var(--xf-line);
    /* ⚠ HEX ĐẶC, không dùng --xf-card: bản tối --xf-card là rgba ~28% nên nút nổi trên nội
       dung sẽ nhìn xuyên thấu chữ phía sau. Luật chung cho mọi thứ đè lên nội dung. */
    background: #ffffff;
    color: var(--xf-ink);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
    font-size: 15px;
    transition: background .12s, border-color .12s, color .12s;
}
html[data-xtheme="dark"] .xf-goc-nut { background: #0d1b2a; }
.xf-goc-nut:hover { border-color: var(--xf-accent); color: var(--xf-accent); }
.xf-goc-nut[hidden] { display: none; }

/* =========================================================================================
   THANH TAB — TRƯỢT NGANG TRÊN ĐIỆN THOẠI  (22/09/2026)
   Gắn class "xf-tabs" cho thẻ bọc các tab là xong. Màn rộng giữ nguyên lưới của màn; dưới
   760px đổi thành MỘT HÀNG trượt ngang.
   Vì sao: 5 tab xếp dọc ăn hết gần nửa màn hình trước khi thấy được dòng dữ liệu đầu tiên.
   Vì sao không đổi thành ô chọn: ô chọn phải chạm hai lần (mở rồi chọn), còn hàng trượt vẫn
   giữ được một chạm — mà tab là thứ người ta đổi qua lại liên tục.
   Phần kéo tab đang mở vào tầm mắt nằm ở js/xiris_tabs.js.
   ========================================================================================= */
@media (max-width: 760px) {
    /* ⚠⚠ TIỀN TỐ `html ` LÀ BẮT BUỘC. Luật nền của màn là `.dsnk-tabs{display:grid}`
       — cùng độ đặc hiệu (0,1,0) với `.xf-tabs`, mà CSS của màn nạp SAU tệp này nên nó thắng.
       Đã đo thật: giữ `.xf-tabs` trần thì 5 tab vẫn xếp 3 hàng, không trượt gì cả. Thêm
       `html ` lên (0,2,0) là đủ thắng, không phải dùng !important. */
    html .xf-tabs {
        display: flex;
        gap: 8px;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        /* Thanh cuộn ngang mảnh xíu nằm dưới hàng tab nhìn rất bẩn; ẩn đi, người dùng vuốt
           là biết còn tab bên phải (tab bị cắt ngang ở mép đã là gợi ý rồi). */
        scrollbar-width: none;
        -ms-overflow-style: none;
        /* Chừa lề hai bên bằng padding chứ không bằng margin: có padding thì tab đầu và tab
           cuối không dính sát mép màn khi trượt tới đầu/cuối. */
        padding-bottom: 2px;
    }
    html .xf-tabs::-webkit-scrollbar { display: none; }
    html .xf-tabs > * {
        flex: 0 0 auto;
        white-space: nowrap;
    }
}

/* =========================================================================================
   BỘ NÚT DÙNG CHUNG  .xf-nut  (22/09/2026)
   Chủ dự án: *"lấy style nút này làm chuẩn làm cho mấy màn khác như vậy luôn"* rồi
   *"gom luôn 2 nút excel pdf đi ủa mình nói 3 nút đó luôn á"*.
   Bản mẫu: .nh-export-btn / .nh-back của themes/theme_xiris/modules/duan/nhap_hang_view.tpl.

   Cách dùng: gắn `xf-nut` + biến thể (`xf-nut-excel` / `xf-nut-pdf`). Nút quay lại đã có
   class riêng `xf-quaylai` cùng bộ số. Màn CŨ không phải sửa gì — js/xiris_quaylai.js tự
   nhận diện và gắn hộ (xem gomNutXuat()).

   ⚠⚠ ĐỘ ĐẶC HIỆU: phải là `html body .xf-nut.xf-nut-excel` = (0,2,2).
      Luật của từng màn là `.pvv-export-btn.xls{background:var(--ok)}` = (0,2,0) và nó nằm
      trong <style> của TRANG nên đứng SAU tệp này. Viết `html body .xf-nut-excel` chỉ được
      (0,1,2) — thua, nút giữ nguyên nền đặc cũ.
   ⚠⚠ NỀN CÓ SẴN Ở CẢ HAI BẢN MÀU, KHÔNG ĐỢI HOVER — chủ dự án: *"chế độ sáng thì thêm
      background sẵn không cần hover mới hiện background"*.
   ⚠ Nền bản tối dùng HEX ĐẶC, không lấy --xf-card (bản tối là #00000047, mờ 28% -> nút thành
     cửa kính); xem mục LUẬT modal/sticky phải HEX ĐẶC ở trên.
   ========================================================================================= */
html body .xf-nut {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid #cfdbe6;
    background: #eef3f8;
    color: #334155;
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}
html body a.xf-nut:hover,
html body button.xf-nut:hover {
    background: #e1e9f2;
    border-color: #aebfd0;
    text-decoration: none;
}

/* Excel — xanh lá */
html body .xf-nut.xf-nut-excel,
html body a.xf-nut.xf-nut-excel:link,
html body a.xf-nut.xf-nut-excel:visited {
    border-color: #a7f3d0;
    background: #e7f7f0;
    color: #047857;
}
html body .xf-nut.xf-nut-excel:hover {
    background: #047857;
    border-color: #047857;
    color: #fff;
}

/* PDF — đỏ */
html body .xf-nut.xf-nut-pdf,
html body a.xf-nut.xf-nut-pdf:link,
html body a.xf-nut.xf-nut-pdf:visited {
    border-color: #fecaca;
    background: #fdecec;
    color: #dc2626;
}
html body .xf-nut.xf-nut-pdf:hover {
    background: #dc2626;
    border-color: #dc2626;
    color: #fff;
}

/* ── Bản tối ── */
html[data-xtheme="dark"] body .xf-nut {
    border-color: rgba(148, 163, 184, .30);
    background: #13253a;
    color: #cbd5e1;
}
html[data-xtheme="dark"] body a.xf-nut:hover,
html[data-xtheme="dark"] body button.xf-nut:hover {
    background: #1b3350;
    border-color: rgba(148, 163, 184, .55);
}
html[data-xtheme="dark"] body .xf-nut.xf-nut-excel,
html[data-xtheme="dark"] body a.xf-nut.xf-nut-excel:link,
html[data-xtheme="dark"] body a.xf-nut.xf-nut-excel:visited {
    border-color: rgba(52, 211, 153, .42);
    background: #0c2a22;
    color: #6ee7b7;
}
html[data-xtheme="dark"] body .xf-nut.xf-nut-excel:hover {
    background: #059669;
    border-color: #059669;
    color: #fff;
}
html[data-xtheme="dark"] body .xf-nut.xf-nut-pdf,
html[data-xtheme="dark"] body a.xf-nut.xf-nut-pdf:link,
html[data-xtheme="dark"] body a.xf-nut.xf-nut-pdf:visited {
    border-color: rgba(248, 113, 113, .42);
    background: #2d1418;
    color: #fca5a5;
}
html[data-xtheme="dark"] body .xf-nut.xf-nut-pdf:hover {
    background: #dc2626;
    border-color: #dc2626;
    color: #fff;
}

@media print {
    .xf-nut {
        display: none !important;
    }
}

/* =========================================================================================
   Ô TRẢI TRỌN HÀNG TRONG THẺ — class "xf-o-doc"  (22/09/2026)
   Gắn thêm class này cho <td> nào mà giá trị KHÔNG vừa nửa phải của thẻ: nhãn nằm một dòng
   riêng, giá trị nằm dưới và trải trọn bề ngang.
   Vì sao cần: khuôn thẻ mặc định chia nhãn 44% – giá trị 56%, tính cho một dòng chữ ngắn.
   Ô nào chứa cả một danh sách (tệp đính kèm) hay một lưới con (người duyệt) thì 56% đó chỉ
   còn ~150px — chữ rớt từng ký tự một: "hoa-don-pac-t / hang-9-2026.p / df".
   ⚠ Nhắm bằng class đặt tay chứ ĐỪNG nhắm bằng [data-nhan="…"]: data-nhan do
     js/xiris_bang_the.js chép từ chữ trong <thead>, sửa tiêu đề cột một chữ là luật chết
     âm thầm mà không ai biết.
   ========================================================================================= */
@media screen and (max-width: 820px) {
    table.xf-the > tbody > tr > td.xf-o-doc {
        display: block;
        padding: 9px 12px;
        text-align: left;
        border-top: 1px solid var(--xf-line);
    }
    table.xf-the > tbody > tr > td.xf-o-doc > .xf-nh {
        display: block;
        flex: none;
        max-width: none;
        padding: 0 0 7px;
        align-self: auto;
    }
    table.xf-the > tbody > tr > td.xf-o-doc > .xf-gt {
        display: block;
        padding: 0;
        border-left: 0;
        text-align: left;
    }
}

/* =========================================================================================
   Ô ĐẦU HÀNG VIẾT BẰNG <th> CŨNG PHẢI GẬP THÀNH THẺ  (22/09/2026)
   Bảng NHẬP xoay ngang (màn Ghi chỉ số đồng hồ: hàng là trường, cột là từng đồng hồ) đặt ô
   đầu hàng bằng <th class="lbl"> — thường kèm position:sticky để cuộn ngang vẫn thấy tên
   trường. Bộ thẻ từ trước tới giờ chỉ khai luật cho <td> trong <tbody>, nên <th> đó không
   gập: nó giữ nguyên là ô bảng, kéo cả hàng rộng ra và thẻ vỡ.
   js/xiris_bang_the.js thì đã chạy đúng từ đầu — nó duyệt mọi con của <tr>, không phân biệt
   thẻ — nên chỉ thiếu đúng phần kiểu dáng này.
   ⚠ Đã quét cả 24 tệp .tpl đang bật xf-the: KHÔNG tệp nào có <th> trong <tbody>, nên khối
     này thuần BỔ SUNG, không thể làm đổi màn nào đang chạy. Cũng vì thế mà viết riêng một
     khối thay vì nhân đôi selector ở mọi luật <td> phía trên — ít chỗ sửa, ít chỗ sai.
   ========================================================================================= */
@media screen and (max-width: 820px) {
    table.xf-the > tbody > tr > th {
        display: block;
        width: auto !important;
        min-width: 0 !important;
        max-width: none !important;
        /* Gỡ sticky: ô dính mà gập thẻ thì nó nhảy ra khỏi thẻ, đè lên ô khác. */
        position: static !important;
        box-shadow: none !important;
        background: transparent;
        border: 0;
        padding: 0 12px;
        text-align: right;
        white-space: normal !important;
    }
    table.xf-the > tbody > tr > th[hidden] { display: none !important; }
    table.xf-the > tbody > tr > th[data-nhan] { display: flex; align-items: stretch; }
    table.xf-the > tbody > tr > th.xf-tieude {
        order: -1;
        font-size: 15px;
        padding: 10px 12px;
        text-align: left;
        background: rgba(125,125,125,.08);
        border-bottom: 1px solid var(--xf-line);
    }
    table.xf-the > tbody > tr > th.xf-tieude > .xf-nh { display: none; }
    table.xf-the > tbody > tr > th.xf-tieude > .xf-gt {
        display: block;
        padding: 0;
        border-left: 0;
        text-align: left;
    }
}

/* =========================================================================================
   CHÚ GIẢI CỦA NÚT SAO CHÉP LINK  (22/09/2026)
   Chủ dự án: *"hover dô không hiện tooltip mà copy thành công cũng không có tooltip, tất cả
   các màn luôn á"*. Bản cũ dựa vào thuộc tính `title` của trình duyệt: hiện chậm ~1 giây,
   tuỳ trình duyệt, và trên điện thoại thì không có hover nên chẳng bao giờ thấy.
   Nay js/xiris_copy.js tự vẽ bong bóng này; phần chạy nằm bên đó.
   ⚠ Nền khai HEX ĐẶC, không dùng biến --xf-card/--xf-zone (chúng cố ý là rgba mờ) — lớp nổi
     mà trong suốt thì chữ dưới nó xuyên lên, đọc không ra.
   ⚠ pointer-events:none — bong bóng hiện NGAY TRÊN nút, để nó ăn chuột thì rê vào là
     mouseout khỏi nút, bong bóng tắt, rồi lại hiện: nhấp nháy liên tục.
   ========================================================================================= */
.xiris-copy-tip {
    position: fixed;
    left: -9999px;
    top: -9999px;
    z-index: 2147483000;
    width: max-content;
    max-width: 260px;
    padding: 6px 10px;
    border-radius: 8px;
    background: #1f2937;
    color: #ffffff;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.35;
    text-align: left;
    white-space: normal;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
    pointer-events: none;
    opacity: 0;
    transform: translateY(3px);
    transition: opacity .12s ease, transform .12s ease;
}
.xiris-copy-tip.hien { opacity: 1; transform: translateY(0); }
.xiris-copy-tip.ok { background: #15803d; color: #ffffff; }
.xiris-copy-tip.loi { background: #b91c1c; color: #ffffff; }
/* Bản tối: chú giải lật sang nền sáng cho nổi trên nền navy của trang. */
html[data-xtheme="dark"] .xiris-copy-tip { background: #e2e8f0; color: #0f172a; }
html[data-xtheme="dark"] .xiris-copy-tip.ok { background: #22c55e; color: #052e16; }
html[data-xtheme="dark"] .xiris-copy-tip.loi { background: #fca5a5; color: #450a0a; }

/* =========================================================================================
   KẺ DỌC GIỮA CÁC Ô BẢNG — DÙNG CHUNG  (22/09/2026)
   Chủ dự án: *"tất cả các bảng thêm border dô, sao thấy cái có cái không vậy"*.
   Quét 107 tệp .tpl: 34 tệp tự khai luật `td + td { border-left }`, 30 tệp không — nhìn vào
   thấy chỗ có chỗ không. Khai một lần ở đây thì từ nay bảng mới cũng có sẵn.
   ⚠ Màu lấy đúng màu 34 tệp kia đang dùng: mờ và trung tính nên chạy được cả bản sáng lẫn
     bản tối, khỏi phải khai hai lần.
   ⚠ CHẾ ĐỘ THẺ trên điện thoại KHÔNG bị ảnh hưởng: luật của bộ thẻ
     `table.xf-the > tbody > tr > td { border-left: 0 }` là (0,1,4), mạnh hơn luật này
     (0,1,3) — thẻ vẫn sạch như cũ.
   ⚠ 34 tệp cũ giữ nguyên luật riêng của nó (trùng y hệt, không hại gì) — không đi gỡ để
     khỏi đụng vào mấy màn đang chạy ổn.
   ========================================================================================= */
.content_main table td + td,
.content_main table th + th {
    border-left: 1px solid rgba(125, 125, 125, .22);
}

/* =========================================================================================
   NHÃN "DỰ ÁN" CỦA Ô CHỌN DỰ ÁN  (24/09/2026)
   Chủ dự án gửi ảnh mẫu và chốt: mọi màn có ô chọn dự án đều phải có nhãn đứng BÊN TRÁI ô,
   in hoa cỡ nhỏ. js/xiris_quaylai.js::chuanHoaNhanDuAn() lo phần DOM (chèn nhãn nếu thiếu,
   xoay khối bọc thành hàng ngang); ở đây chỉ còn kiểu chữ.
   ⚠ Nhắm cả `label` lẫn `span` vì nhãn có sẵn của mỗi màn mỗi kiểu thẻ.
   ⚠ `flex:0 0 auto` + `nowrap`: trong hàng ngang, nhãn mà co lại là gãy thành "DỰ / ÁN".
   ========================================================================================= */
/* =========================================================================================
   Ô CHỌN DỰ ÁN Ở MÀN HẸP: KHÔNG ĐƯỢC ĐẨY RỘNG CẢ TRANG  (24/09/2026)
   Chủ dự án: *"option dự án vẫn bị lệch, màn 320 cũng lệch... sửa là phải sửa hết"*.
   Rà cả 107 .tpl: khoảng 20 màn khai `min-width`/`width` cứng 210–350px cho ô chọn dự án
   hoặc cụm bọc nó, KHÔNG kèm max-width (tong_quan, giam_sat_bao_tri, duyet_bao_tri_tuan,
   thanh_toan_ky, scada_pid, phan_anh_khach_hang, hoi_ai…). Trên máy 320px (trừ lề còn ~288px)
   là tràn, cả trang vuốt ngang được.
   Sửa một chỗ cho cả 28 màn thay vì đi sửa từng tệp: bám vào [data-xf-duan] —
   js/xiris_quaylai.js::chuanHoaNhanDuAn() đánh dấu đúng cụm bọc ô chọn dự án ở MỌI màn.
   ⚠ `max-width` mới là thứ chặn được `width` NỘI DÒNG có !important mà select2 đặt lên vỏ;
     `min-width:0` mới gỡ được sàn cứng của từng màn. Phải có cả hai.
   ⚠ Chỉ từ 560px trở xuống: rộng hơn thì mấy bề rộng 240–350px kia vẫn vừa, giữ nguyên
     thiết kế của từng màn.
   ========================================================================================= */
@media screen and (max-width: 560px) {
    [data-xf-duan] {
        min-width: 0 !important;
        max-width: 100% !important;
    }
    [data-xf-duan] > select,
    [data-xf-duan] > .select2-container {
        min-width: 0 !important;
        max-width: 100% !important;
    }
}

.xf-nhan-duan {
    flex: 0 0 auto;
    margin: 0;
    color: var(--xf-mut);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .4px;
    line-height: 1.2;
    text-transform: uppercase;
    white-space: nowrap;
}


/* ==========================================================================
 * SELECT2 KHONG DUOC RONG HON KHUNG  (25/09/2026)
 * Chu du an: "sao minh chon du an lai bi tran nua roi ... xem het tat ca site".
 *
 * Dem duoc 41 cho trong 107 tep .tpl khai be rong CO DINH cho select2 — tu 240px
 * den 440px (lich_su_bao_tri 440, cau_hinh 350, scada 280...). O may 320-390px thi
 * bat cu so nao tu ~300px tro len la day ca trang tran ngang.
 *
 * ⚠⚠ Vi sao phai !important: select2 GHI be rong vao STYLE NOI TUYEN cua vo
 *    (`<span class="select2-container" style="width:440px">`). Luat CSS thuong,
 *    du dat sau, van thua style noi tuyen — chi `max-width` + !important moi de duoc.
 * ⚠⚠ `max-width:100%` MOT MINH KHONG DU: no tinh theo THE CHA, ma co man the cha
 *    rong hon khung (thanh cong cu tu cuon ngang). Nen ken them `100vw - 16px`.
 * ⚠ Hop xo (.select2-dropdown) do select2 gan thang vao <body> va cung mang be rong
 *   noi tuyen -> phai chan rieng, neu khong hop van tran du o da hep lai.
 * ⚠ Chu dai thi cat bang ba cham, khong de no keo hop rong ra.
 * ========================================================================== */
@media screen and (max-width: 820px) {
    html body .select2-container{/*s2-khong-tran*/
        max-width:min(100%, calc(100vw - 16px))!important; min-width:0!important}
    html body .select2-container .select2-selection--single{max-width:100%}
    html body .select2-container .select2-selection__rendered{
        max-width:100%; overflow:hidden; text-overflow:ellipsis}
    html body .select2-container--open .select2-dropdown{
        max-width:calc(100vw - 16px)!important}
}

/* =========================================================================================
   TRÌNH XEM TÀI LIỆU DÙNG CHUNG  (25/09/2026)
   Chủ dự án: *"mình cần xem tài liệu, ảnh nè trên phần mềm luôn, dạng như khi bấm nó mở modal
   xong mình xem được trên đó các tài liệu luôn"* — và không gửi tệp ra thư viện Office trực
   tuyến ("làm vậy bị lộ tài liệu"). Sửa lần 2 cùng ngày: *"mở hộp bé thôi như thư viện office
   vậy á"* — bản đầu trải kín màn hình, nhìn như đã rời khỏi phần mềm.

   Hành vi nằm ở js/xiris_xemtep.js: nó bắt MỌI thẻ <a> có cặp `tep=<số>` + `khoi=<tên>` trong
   href (dấu nhận biết do cổng tệp ở tầng 1 để lại), nên không màn nào phải sửa .tpl.

   HAI LỚP: .xf-xt là NỀN MỜ phủ trang, .xf-xt-hop là HỘP đứng giữa.
   ⚠⚠ RUỘT HỘP LÀ HEX ĐẶC, không một chỗ nào rgba. Bản tối đã ăn lỗi "đừng có trong suốt cái
     background" nhiều lần rồi. Chỉ NỀN MỜ phía sau mới được rgba — đúng khuôn .pa-modal của
     màn Phản ánh khách hàng đang dùng.
   ⚠ Hộp cố ý TỐI ở cả hai bản sáng/tối: đang xem ảnh/PDF thì nền tối mới đọc được, và khỏi
     phải khai màu hai lần.
   ⚠ z-index 11200 — phải cao hơn .pa-modal (11050) của màn Phản ánh khách hàng, không thì mở
     tệp từ trong hộp chi tiết phản ánh sẽ bị hộp kia che.
   ⚠ [hidden] phải khai lại: .xf-xt có display:flex nên thuộc tính hidden của HTML không ăn.
   ========================================================================================= */
.xf-xt {
    position: fixed; inset: 0; z-index: 11200;
    display: flex; align-items: center; justify-content: center;
    padding: min(2.5vh, 22px) min(2vw, 24px);
    background: rgba(2, 8, 23, .68);
}
.xf-xt[hidden] { display: none; }
html.xf-xt-mo { overflow: hidden; }

/* HỘP CAO THEO NỘI DUNG, không cao cứng — chủ dự án 25/09: *"ở điện thoại khung cao quá vậy,
   ảnh có cao tới vậy đâu"*. Ảnh ngang (tiêu đề phiếu, ảnh chụp banner) chỉ cao vài trăm px mà
   hộp cứ 640px là thừa ra hai mảng đen to đùng.
   ⚠ RIÊNG khung PDF phải cao CỨNG (.cao, JS tự gắn): iframe cao 100% mà bố cao "auto" thì
     không có mốc để tính -> khung dẹp lép. */
.xf-xt-hop {
    position: relative;
    display: flex; flex-direction: column;
    width: min(1500px, 100%); height: auto; max-height: 100%;
    overflow: hidden;
    border: 1px solid #22303e; border-radius: 14px;
    background: #0b1119; color: #e8eef5;
    box-shadow: 0 24px 70px rgba(0, 0, 0, .45);
}
/* TÀI LIỆU (PDF / Word / Excel): khung TO HẲN, gần kín màn hình — chủ dự án 25/09: *"khung này
   hơi bé, mình để 100% mà cái khung nhỏ quá nên xem không được"*, kèm ảnh mẫu một hộp xem file
   trải gần trọn bề ngang.
   ⚠ 25/09, sửa lần 2 theo chủ dự án — *"ảnh cũng cho mở to bằng tài liệu luôn đi"*: bề ngang
     nay khai chung ở .xf-xt-hop, ẢNH và TÀI LIỆU rộng bằng nhau. Class .cao giờ CHỈ còn khác
     nhau ở CHIỀU CAO.
   ⚠ Chiều cao CỨNG (100% chứ không auto) vì iframe/bảng bên trong cần một mốc để bám; ảnh thì
     vẫn cao theo đúng ảnh, dài quá mới cuộn. */
.xf-xt-hop.cao { height: 100%; }

.xf-xt-thanh {
    display: flex; align-items: center; gap: 10px;
    flex: 0 0 auto; min-height: 46px; padding: 7px 9px 7px 14px;
    background: #111c27; border-bottom: 1px solid #22303e;
}
.xf-xt-ten {
    flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 13px; font-weight: 600;
}
.xf-xt-dem { flex: 0 0 auto; color: #8fa3b8; font-size: 12px; }
.xf-xt-nhom { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.xf-xt-b {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0;
    border: 1px solid #2b3b4c; border-radius: 8px;
    background: #16222f; color: #cfe0f0 !important;
    font-size: 13.5px; line-height: 1; cursor: pointer; text-decoration: none !important;
}
.xf-xt-b:hover { background: #1d2f40; border-color: #3d5266; }
.xf-xt-dong { background: #1d2a37; }

/* Ruột hộp: nội dung ĂN TRỌN KHUNG, dài quá thì CUỘN — chủ dự án 25/09: *"cho nội dung full
   khung luôn, ở điện thoại thì cho scroll thôi"*. Bản trước bóp ảnh cho vừa khung nên ảnh dọc
   chụp bằng điện thoại co lại tí xíu giữa hai mảng đen to đùng.
   ⚠ display:block chứ không flex — flex căn giữa thì ảnh không trải hết bề ngang được. Riêng
     lúc chờ và lúc báo "không xem được" mới thêm class .giua để căn giữa (JS tự bật/tắt). */
.xf-xt-than {
    position: relative; flex: 1 1 auto; min-height: 0;
    display: block; overflow: auto; padding: 0;
    -webkit-overflow-scrolling: touch;
}
/* Lúc chờ thì chừa sẵn một khoảng, không thì hộp co lại còn mỗi thanh tiêu đề rồi giật nảy
   lên khi ảnh vẽ xong. */
.xf-xt-than.dangcho { min-height: 150px; }
.xf-xt-than.giua { display: flex; align-items: center; justify-content: center; padding: 8px; }
.xf-xt-anh { display: block; width: 100%; height: auto; cursor: zoom-in; }
/* Bấm vào ảnh -> CỠ THẬT (ảnh máy ảnh thì to hơn khung), cuộn cả hai chiều để soi chi tiết. */
.xf-xt-anh.that { width: auto; max-width: none; cursor: zoom-out; }
.xf-xt-khung { display: block; width: 100%; height: 100%; border: 0; background: #fff; }
/* Tự căn giữa bằng vị trí tuyệt đối, khỏi phụ thuộc ruột hộp đang là block hay flex. */
.xf-xt-cho {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    color: #8fa3b8; font-size: 13px; white-space: nowrap;
}

/* ===== TÀI LIỆU WORD / EXCEL DỰNG NGAY TRONG HỘP =====
   mammoth (.docx) và SheetJS (.xlsx/.xls/.csv) đổi tệp thành HTML NGAY TRONG TRÌNH DUYỆT của
   người dùng — tệp không đi ra ngoài, khác hẳn trình xem trực tuyến của Office (máy chủ của họ
   tự tải tệp về mới dựng được).
   Nền GIẤY TRẮNG cho giống trang tài liệu thật, chữ đen, đọc mới đỡ mỏi mắt. */
.xf-xt-giay {
    min-height: 100%; padding: 26px 30px;
    background: #fff; color: #1b2430;
    font-size: 13.5px; line-height: 1.65;
}
.xf-xt-giay img { max-width: 100%; height: auto; }
.xf-xt-giay table { border-collapse: collapse; width: auto; max-width: 100%; margin: 10px 0; }
.xf-xt-giay td, .xf-xt-giay th {
    border: 1px solid #c9d2dd; padding: 5px 9px; font-size: 12.5px; vertical-align: top;
}
.xf-xt-giay th { background: #eef2f7; font-weight: 600; }
.xf-xt-giay h1, .xf-xt-giay h2, .xf-xt-giay h3 { margin: 16px 0 8px; line-height: 1.35; }
.xf-xt-giay p { margin: 0 0 9px; }
.xf-xt-giay a { color: #0369a1; }

/* =========================================================================================
   BẢNG TÍNH EXCEL — dựng cho GIỐNG EXCEL THẬT (25/09/2026)
   Chủ dự án: *"bảng excel giờ làm như bảng excel cho mình, như thật luôn"*.
   Có hàng chữ cái cột (A, B, C...), cột số dòng, kẻ lưới đủ, thẻ chọn sheet nằm DƯỚI.
   ⚠ Hàng chữ cái GHIM TRÊN, cột số dòng GHIM TRÁI, ô góc ghim cả hai — cuộn tới đâu cũng biết
     mình đang ở ô nào. Ô góc phải z-index cao nhất, không thì nó chui xuống dưới hai cái kia.
   ========================================================================================= */
.xf-xt-than.xl { display: flex; flex-direction: column; overflow: hidden; }
.xf-xt-xl { flex: 1 1 auto; min-height: 0; overflow: auto; background: #fff; }

.xf-xt-xl-bang {
    border-collapse: separate; border-spacing: 0;
    background: #fff; color: #1b2430;
    font-size: 12.5px; line-height: 1.45;
}
.xf-xt-xl-bang caption.cat {
    caption-side: top; text-align: left;
    padding: 7px 12px; background: #fff7ed; color: #9a3412;
    font-size: 12px; border-bottom: 1px solid #fed7aa;
}
.xf-xt-xl-bang th, .xf-xt-xl-bang td {
    border-right: 1px solid #d7dee6; border-bottom: 1px solid #d7dee6;
    padding: 4px 8px; white-space: nowrap; vertical-align: top;
    max-width: 480px; overflow: hidden; text-overflow: ellipsis;
}
/* Hàng chữ cái cột */
.xf-xt-xl-bang th.cot {
    position: sticky; top: 0; z-index: 2;
    background: #eef1f5; color: #4b5a6b;
    font-weight: 600; text-align: center; min-width: 64px;
}
/* Cột số dòng */
.xf-xt-xl-bang th.dong {
    position: sticky; left: 0; z-index: 2;
    background: #eef1f5; color: #4b5a6b;
    font-weight: 500; text-align: center; min-width: 42px;
}
/* Ô góc trên-trái */
.xf-xt-xl-bang th.goc {
    position: sticky; top: 0; left: 0; z-index: 3;
    background: #e5e9ee; min-width: 42px;
}
.xf-xt-xl-bang td.so { text-align: right; font-variant-numeric: tabular-nums; }
.xf-xt-xl-bang td.giua { text-align: center; }
.xf-xt-xl-bang td.rong { color: #8494a6; font-style: italic; padding: 16px; }
.xf-xt-xl-bang tbody tr:hover td { background: #f3f8fd; }

/* Hàng thẻ chọn sheet — nằm DƯỚI bảng, đúng chỗ của Excel. */
.xf-xt-sheet {
    flex: 0 0 auto;
    display: flex; gap: 4px; flex-wrap: wrap;
    padding: 6px 8px;
    background: #111c27; border-top: 1px solid #22303e;
}
.xf-xt-sheet > button {
    padding: 5px 13px; border: 1px solid #2b3b4c; border-radius: 6px 6px 0 0;
    background: #16222f; color: #cfe0f0; font-size: 12px; cursor: pointer;
}
.xf-xt-sheet > button.chon { background: #fff; border-color: #fff; color: #10233a; font-weight: 600; }

.xf-xt-khong {
    display: flex; flex-direction: column; align-items: center; gap: 10px;
    max-width: 400px; padding: 24px 20px; text-align: center;
    border: 1px solid #22303e; border-radius: 14px; background: #131f2b;
}
.xf-xt-khong > .fa { font-size: 30px; color: #7f97ae; }
.xf-xt-khong b { font-size: 13.5px; word-break: break-word; }
.xf-xt-khong span { color: #9db0c4; font-size: 12.5px; }
.xf-xt-taive {
    display: inline-flex; align-items: center; gap: 7px; margin-top: 4px;
    padding: 9px 16px; border-radius: 9px;
    background: #0369a1; color: #fff !important;
    font-size: 12.5px; font-weight: 600; text-decoration: none !important;
}
.xf-xt-taive:hover { background: #0284c7; }

.xf-xt-di {
    position: absolute; top: calc(50% + 23px); transform: translateY(-50%);
    display: flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; padding: 0;
    border: 1px solid #2b3b4c; border-radius: 50%;
    background: #16222f; color: #cfe0f0; font-size: 14px; cursor: pointer;
}
.xf-xt-di:hover { background: #1d2f40; }
.xf-xt-di.truoc { left: 10px; }
.xf-xt-di.sau { right: 10px; }
.xf-xt-di[hidden] { display: none; }

/* Điện thoại: hộp gần kín màn cho đỡ phí chỗ, nhưng vẫn là HỘP (còn viền, còn bo góc). */
@media (max-width: 820px) {
    .xf-xt { padding: 10px; }
    .xf-xt-hop { width: 100%; border-radius: 12px; }
    .xf-xt-hop.cao { height: 100%; }
    .xf-xt-thanh { min-height: 42px; padding: 6px 7px 6px 11px; }
    .xf-xt-ten { font-size: 12.5px; }
    .xf-xt-b { width: 30px; height: 30px; }
    .xf-xt-than.giua { padding: 6px; }
    .xf-xt-di { width: 32px; height: 32px; }
    .xf-xt-di.truoc { left: 5px; }
    .xf-xt-di.sau { right: 5px; }
}

/* Bản in không bao giờ có hộp này — tránh trang giấy trắng thừa nếu lỡ in lúc đang mở. */
@media print { .xf-xt { display: none !important; } }

/* =========================================================================================
   BẢN IN / XUẤT PDF — LUẬT DÙNG CHUNG  (25/09/2026)
   Chủ dự án: *"sao in cái danh sách sự cố lạ vậy, nếu xuất pdf hay excel thì in hết, bỏ cái
   phân trang ra đi"* (ảnh: mỗi dòng phiếu kéo theo một đoạn `[/index.php?language=vi&nv=duan…]`).

   1. ĐỪNG IN ĐƯỜNG DẪN RA GIẤY. Bộ CSS in của Bootstrap có luật `a[href]:after{content:" ("
      attr(href) ")"}` — ý tốt cho trang web tin tức (đọc bản in vẫn biết link đi đâu), nhưng ở
      đây link là URL nội bộ dài ngoằng có đủ tham số lọc, in ra chỉ tổ rác trang giấy.
   2. BỎ THANH PHÂN TRANG. Trên giấy không ai bấm được sang trang 2.
   ⚠ Độ đặc hiệu: luật của Bootstrap là (0,1,1) nên phải thêm `.content_main` cho thành (0,2,1)
     mới đè được — dùng `content:none` chứ không phải chuỗi rỗng, để gỡ hẳn ô giả.
   ========================================================================================= */
@media print {
    .content_main a[href]:after,
    .content_main a[href]::after { content: none !important; }
    .xf-pager { display: none !important; }
}


/* =========================================================================================
   CHU TRONG O CHON PHAI NAM GIUA HOP  (25/09/2026)
   Chu du an: "no bi lech ne, con trang nao bi lech ban chinh het di chu bi hoai".

   Do tren man Cap nuoc: hop o chon cao 31px (tam doc 126) nhung phan chu bi ghim
   `line-height: 36px` -> chu roi xuong tam 130: lech 4px so voi hop va so voi nhan
   "Du an" ben canh. Cung benh do do duoc o man Pha hoa chat (hop 44px, lech 8px).

   Goc benh: `line-height` la so CUNG cua bo select2, con chieu cao hop thi moi man tu
   dat (31 / 33 / 38 / 44px). Hop khac 36 la chu lech. Duoi tung man khong het —
   dat mot luat o day cho ca site.

   ⚠⚠ Phai co `html body` de len (0,4,2): nhieu man khai
      `.abc-page .select2-container--default .select2-selection--single
       .select2-selection__rendered { line-height: 33px }` = (0,4,0) va nam trong khoi CSS
      cua trang nen dung SAU tep nay.
   ⚠ Chi bo dem TREN/DUOI; dem trai/phai giu nguyen (cho chua mui ten xo).
   ⚠ Dung flex thay vi sua line-height: chu nam giua theo CHIEU CAO THAT cua hop, hop cao
     bao nhieu cung dung, ke ca man cho chu xuong hai dong.
   ========================================================================================= */
/* 26/09/2026 — chủ dự án: *"sao option lại lệch nữa rồi, bạn không làm tất cả option cùng 1
   kiểu được hả, đừng có bị lệch nữa chớ"*. Luật dưới đây có từ 25/09 nhưng KHÔNG ăn: đo trên
   host thấy nhiều màn khai `line-height: 36px !important` ngay trong <style> của trang (màn
   Lịch sử bảo trì còn ba lớp 36 / 32 / 34px) — `!important` của trang thắng luật thường ở đây,
   chữ vẫn tràn xuống dưới đáy ô 3-5px. Nên phải đánh dấu !important cho đúng mấy tính chất
   canh giữa; bề rộng, màu, cỡ chữ của từng màn vẫn giữ nguyên. */
html body .select2-container--default .select2-selection--single
    .select2-selection__rendered {/*s2-chu-giua-hop*/
    display: flex !important;
    align-items: center !important;
    min-height: 100% !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    line-height: 1.3 !important;
}
/* Bản thân Ô CHỌN cũng phải hết đệm dọc (26/09/2026). Đo trên host: theme để
   `.select2-selection--single { padding-top: 2px }` mà không có đệm dưới -> phần ruột bị đẩy
   xuống 2px, canh giữa cỡ nào cũng còn lệch đúng 2px đó. */
html body .select2-container--default .select2-selection--single {/*s2-hop-het-dem-doc*/
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
/* Mui ten xo cung phai giua theo hop, khong thi no lech nguoc lai voi chu. */
html body .select2-container--default .select2-selection--single
    .select2-selection__arrow { display: flex; align-items: center; justify-content: center;
    height: 100%; top: 0; }

/* =========================================================================================
   HÀNG ĐẦU CÓ HỘP "ĐI ĐẾN TRANG KHÁC": TÊN DỰ ÁN DÀI KHÔNG ĐƯỢC ĐẨY NÚT XUỐNG HÀNG
   (26/09/2026 — chủ dự án: *"nếu mà option dự án mà dài quá thì nút bị chèn xuống hàng nè,
   bạn chỉnh lại đừng cho xuống hàng nha"*).

   Hàng đầu của cả nhà Bảo trì là flex CÓ wrap. Ô chọn dự án nở theo tên dự án, tên dài là
   đẩy nút + hộp rụng xuống hàng dưới. Chặn bằng cách ghim trần bề rộng ô chọn rồi cắt bằng
   ba chấm — giữ wrap làm van an toàn cho khổ hẹp, không ép nowrap (ép là tràn ngang).

   ⚠ Dùng `:has(> .xbtdh)` để bắt ĐÚNG hàng chứa hộp, khỏi phải sửa 9 màn mỗi màn một tên lớp.
   ⚠ Chỉ áp từ 768px trở lên: dưới đó hàng đầu cố ý xếp dọc, ô chọn phải rộng hết khổ.
   ========================================================================================= */
@media screen and (min-width: 768px) {
    html body :has(> .xbtdh) .select2-container {/*hang-dau-khong-xuong-dong*/
        max-width: min(360px, 100%) !important;
        min-width: 0 !important;
    }
    html body :has(> .xbtdh) .select2-selection__rendered {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

/* =========================================================================================
   ẨN NÚT BÁNH RĂNG NỔI Ở GÓC PHẢI DƯỚI  (29/09/2026 — chủ dự án: *"ẩn nút này đi cho mình"*)

   `#config-btn.floating-btn` + hộp `#config-panel` đi kèm do khung giao diện dựng ra, KHÔNG
   nằm trong mấy tệp .tpl của module duan (đã dò cả layout, block, module menu/wework). Vì vậy
   chặn bằng CSS ở đây — một luật cho cả site, và gỡ ra là hiện lại ngay, không phải mò lại
   xem markup nằm ở đâu.

   ⚠ Ẩn CẢ hộp popup: chỉ giấu nút thì hộp vẫn bung ra được bằng phím tab + Enter.
   ⚠ `display:none` chứ không `visibility:hidden`: nút để `position:fixed`, giấu kiểu kia là
     nó vẫn chiếm chỗ bấm ở góc màn, che nút khác.
   ========================================================================================= */
html body #config-btn.floating-btn,
html body #config-panel { display: none !important; }

/* =========================================================================================
   VÒNG FOCUS: BẤM CHUỘT KHÔNG CÒN KHUNG ĐEN  (29/09/2026)
   Chủ dự án: *"bấm một thứ gì trên màn hình, ví dụ ở menu, nó đều có dấu gạch đen bao quanh —
   mặc định của cái gì vậy, bỏ hết đi được không"*.

   THỦ PHẠM là Bootstrap 3 (themes/theme_xiris/css/bootstrap.min.css), ba luật:
       a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}
       input[type=file|radio|checkbox]:focus{…}
       .btn:focus,.btn:active:focus,…{…}
   Chúng dùng `:focus` — tức BẤM CHUỘT cũng ăn, không riêng bàn phím. Cái "khung đen" chính là
   `-webkit-focus-ring-color`.

   ⚠⚠ KHÔNG tắt sạch focus. Người dùng bàn phím (Tab) mất dấu là không còn biết mình đang đứng
     ở ô nào — màn nhập liệu của site này toàn biểu mẫu dài, tắt hẳn là không dùng nổi. Nên:
       · BẤM CHUỘT  -> `:focus:not(:focus-visible)` -> bỏ hẳn vòng.
       · BÀN PHÍM   -> `:focus-visible` -> vòng MẢNH theo màu hệ thống thay cho khung đen.
     `:focus-visible` là thứ trình duyệt tự quyết: bấm chuột thì không bật, Tab thì bật.

   ⚠ Độ đặc hiệu: luật Bootstrap là (0,1,1)/(0,2,0); ở đây dùng thêm !important cho chắc, vì
     bootstrap.min.css nạp TRƯỚC tệp này nhưng còn .btn:active:focus (0,3,0) cao hơn.
   ========================================================================================= */
:focus:not(:focus-visible) {
    outline: none !important;
    outline-offset: 0 !important;
}
:focus-visible {
    outline: 2px solid var(--xf-accent) !important;
    outline-offset: 2px !important;
}
