/* GENERATED FILE — KHÔNG SỬA TRỰC TIẾP.
   Nguồn: styles/manifest.json · SHA-256 aa24a4bbf3f7d72ef4d855419e93cec1ac3181a2005a900ca119afd3d14a14a4
   Tạo lại bằng: npm run build:styles */

/* ===== SOURCE: styles/foundation.css ===== */
/* ============================================================
   VLXD THANH HIỀN — phần mềm bán hàng
   Bảng màu: xanh da trời (chủ đạo) · cam sáng (điểm nhấn) · trắng
   ============================================================ */

:root{
  /* XÁM THAN trung tính (b105 — chủ tiệm chọn 05/08/2026):
     nền lùi lại để màu CAM một mình nổi bật. Tên biến giữ nguyên --sky-*
     cho đỡ phải sửa hàng trăm chỗ — hiểu là "thang màu chủ đạo". */
  --sky-900:#181B20;
  --sky-800:#22262E;
  --sky-700:#2E333D;
  --sky-600:#3B424F;
  --sky-500:#4E5766;
  --sky-400:#8791A0;
  --sky-300:#BBC2CC;
  --sky-100:#E7EAEE;
  --sky-50:#F4F5F7;
  /* cam sáng — CHỈ cho hành động chính và số cần chú ý */
  --or:#F97316;
  --or-6:#EA6A0B;
  --or-7:#C25706;
  --or-safe:#A94704;
  --or-safe-hover:#873801;
  --or-50:#FFF2E4;
  /* trung tính */
  --ink:#1B1E24;
  --ink-2:#2C313A;
  --slate:#61697A;
  --slate-2:#61697A;
  --line:#D8DCE2;
  --line-2:#EBEDF1;
  --paper:#FFFFFF;
  --bg:#ECEEF1;
  --green:#0C7A57;
  --green-soft:#E1F4ED;
  --red:#C6342A;
  --red-soft:#FCEBE9;

  --r:8px;
  --r-lg:12px;
  --r-sm:6px;
  --shadow:0 1px 2px rgba(24,27,32,.05), 0 2px 8px rgba(24,27,32,.05);
  --shadow-md:0 2px 6px rgba(24,27,32,.07), 0 8px 24px rgba(24,27,32,.08);
  --shadow-lg:0 12px 48px rgba(24,27,32,.24);

  /* Nhịp giao diện b157: một nguồn duy nhất cho khoảng cách, chiều cao điều
     khiển và chuyển động. Giữ nguyên hệ font và thang chữ của app cũ. */
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  --space-4:16px;
  --space-5:24px;
  --control-h:40px;
  --motion-fast:120ms;
  --motion-base:180ms;
  --focus-ring:0 0 0 3px rgba(249,115,22,.2);

  --f-ui:"Be Vietnam Pro", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  --f-mono:"TH Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  /* b225 · font cho SỐ. Cùng bộ với --f-mono (mỗi chữ số một bề ngang nên
     số thẳng cột), nhưng số 0 KHÔNG có dấu chấm ở giữa — anh Đạt soi phiếu
     bán thấy chấm giữa số 0 rối mắt. Xem fonts/TH-MONO-GHI-CHU.txt. */
  --f-num:var(--f-mono);

  --rail:56px;   /* b242 · thanh bên CHỈ CÒN BIỂU TƯỢNG, chữ hiện khi rê chuột */
  --head:56px;
}

*{box-sizing:border-box;touch-action:manipulation}   /* touch-action: b146 — chạm đôi không phóng trang (xem khối b146 ở workflows.css) */
html,body{height:100%}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}   /* b146 — chữ không tự phồng khi xoay ngang máy */
body{
  margin:0; font-family:var(--f-ui); background:var(--bg); color:var(--ink);
  font-size:14px; line-height:1.45; -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale; overflow:hidden;
  font-feature-settings:"cv05","ss01";
}

button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;border:0;background:none}
input,select,textarea{
  background:var(--paper); border:1px solid var(--line); border-radius:var(--r);
  padding:8px 10px; width:100%; outline:none; transition:border-color .12s, box-shadow .12s;
}
input:focus,select:focus,textarea:focus{border-color:var(--sky-500);box-shadow:0 0 0 3px var(--sky-100)}
input[readonly]{background:var(--sky-50);color:var(--slate)}
/* b297 · anh Đạt 24/09 (ảnh iPhone 13 Pro Max): "mở phiếu thuê. Phần ngày tháng cũng bị dính. Và khung
   phiếu thuê bị xê dịch". iPhone vẽ ô ngày theo bề rộng RIÊNG của nó — "ngày 24 thg 9, 2026" cần ~212px —
   và bỏ qua cả width:100% lẫn min-width:0: hai ô chia đôi 396px (mỗi ô ~190px) đè lên nhau, ô phải thò ra
   ngoài khung ~20px, nên cả phiếu kéo ngang được. Chromium không vậy — bộ đo chạy Chromium nên không thấy.
   Chữa theo cách WebKit iOS cần: bỏ giao diện gốc (appearance:none) thì ô mới chịu co theo khung; bấm vào
   vẫn ra bánh xe chọn ngày. iPhone còn canh GIỮA ngày → canh trái cho thẳng hàng các ô khác; ô ngày rỗng
   không sụp chiều cao (min-height). Chỉ WebKit trên iPhone/iPad có -webkit-touch-callout ⇒ máy tính và
   Android không bị đụng một điểm ảnh nào. */
@supports (-webkit-touch-callout: none){
  input[type=date]{-webkit-appearance:none;appearance:none;min-width:0;max-width:100%}
  input[type=date]::-webkit-date-and-time-value{text-align:left;margin:0;min-height:1.5em}
}
/* b284 · CHỮ MỜ luôn là CHỮ, không phải SỐ. Ô nào dùng font số (ô quét mã, ô tiền, mã số
   thuế) thì chữ mờ cũng thành font số — đứng cạnh ô thường là thấy lệch nét (soi ảnh 21/09).
   Chữ ĐÃ GÕ giữ nguyên font số: đọc dãy mã vạch cần từng số đều bề ngang. */
input::placeholder,textarea::placeholder{font-family:var(--f-ui);letter-spacing:0}
:focus-visible{outline:2.5px solid var(--or);outline-offset:2px;border-radius:4px}
input:focus-visible,select:focus-visible,textarea:focus-visible{outline-offset:0}
button:focus-visible,a:focus-visible,[tabindex]:focus-visible{box-shadow:var(--focus-ring)}
.num{font-variant-numeric:tabular-nums;font-family:var(--f-mono)}
.mut{color:var(--slate)}

/* ---------- đăng nhập & tài khoản (b154) ----------
   Giữ nguyên hệ font cũ: tất cả thành phần kế thừa --f-ui/--f-mono. */
.authgate{
  position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:20px;
  background:radial-gradient(circle at 50% 15%,#3B424F 0,#22262E 42%,#181B20 100%);
}
.authgate[hidden]{display:none}
.auth-card{width:min(410px,100%);background:var(--paper);border:1px solid rgba(255,255,255,.15);
  border-radius:var(--r-lg);box-shadow:var(--shadow-lg);padding:28px}
/* b294 · điện thoại: thẻ rộng ra để hàng "☐ Ghi nhớ đăng nhập · Quên mật khẩu?" (cần 287px) nằm MỘT hàng
   từ 360px trở lên — với đệm cũ (20 + 28px) iPhone 375px chỉ còn 277px và nhãn gãy đôi. */
@media (max-width:560px){
  .authgate{padding:var(--space-3)}
  .auth-card{padding:var(--space-5) var(--space-4)}
}
.auth-logo{width:52px;height:52px;margin:0 auto 10px;border-radius:12px;background:var(--or);
  color:#fff;display:grid;place-items:center}
.auth-logo svg{width:30px;height:30px}
.auth-title{text-align:center;font-size:24px;font-weight:800;letter-spacing:-.3px;margin-bottom:var(--space-5)}
/* b294 · chỉ hiện lúc MẤT KẾT NỐI — bình thường thẻ đăng nhập không có dòng chữ phụ nào (anh Đạt 24/09). */
.auth-canh{margin:calc(-1 * var(--space-2)) 0 var(--space-4);padding:var(--space-2) var(--space-3);border-radius:var(--r-sm);
  background:var(--red-soft);color:var(--red);font-size:12.5px;font-weight:600;line-height:1.45;text-align:center}
.auth-card form{display:grid;gap:12px}
/* b300 · thẻ Nhận tiệm (đường dẫn #ve=…) — một câu chào trên form */
.auth-chao{margin:calc(-1 * var(--space-3)) 0 var(--space-4);text-align:center;color:var(--ink-2);line-height:1.5}
.auth-card .f input[readonly]{background:var(--sky-50);color:var(--ink-2)}
.auth-go{width:100%;height:44px;margin-top:2px}
/* b293 · ô đăng nhập theo chuẩn (web.dev sign-in form · NIST 800-63B-4 §3.1.1.2): ô và nút cao 44px
   để đủ vùng chạm; nút Hiện/Ẩn nằm TRONG ô mật khẩu bên phải, chữ --or-safe (5,31:1 trên trắng). */
.auth-card .f input{min-height:44px}
.auth-pass{position:relative}
.auth-pass input{width:100%;padding-right:64px}
.auth-hien{position:absolute;right:2px;top:50%;transform:translateY(-50%);min-height:40px;min-width:56px;
  padding:0 12px;border:0;border-radius:var(--r-sm);background:transparent;color:var(--or-safe);
  font:inherit;font-size:13px;font-weight:700;cursor:pointer}
.auth-hien:hover{background:var(--or-50)}
.auth-hien:focus-visible{outline:2px solid var(--or-safe);outline-offset:-2px}
/* b294 · một hàng: "☐ Ghi nhớ đăng nhập" trái · "Quên mật khẩu?" phải (mẫu Microsoft/Google).
   Cả hai là vùng chạm ≥44px. Không có ô ghi nhớ (một máy / mất kết nối) thì nút Quên vẫn nằm phải. */
.auth-dong{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--space-2);min-height:44px}
.auth-nho{display:flex;align-items:center;gap:var(--space-2);min-height:44px;cursor:pointer;
  font-weight:600;color:var(--ink);line-height:1.35;white-space:nowrap}
.auth-nho input{width:20px;height:20px;margin:0;flex:0 0 20px;accent-color:var(--or-safe)}
.auth-quen{margin-left:auto;min-height:44px;padding:0 var(--space-1);border:0;background:transparent;
  font:inherit;font-weight:600;color:var(--or-safe);cursor:pointer;white-space:nowrap}
@media (hover:hover){.auth-quen:hover{text-decoration:underline}}   /* điện thoại: chạm xong không dính gạch chân */
.auth-quen:focus-visible{outline:2px solid var(--or-safe);outline-offset:2px;border-radius:var(--r-sm)}
.auth-quen-tb{margin-top:calc(-1 * var(--space-1));color:var(--slate);font-size:12.5px;text-align:right}
.auth-quen-tb[hidden]{display:none}
.auth-err{padding:9px 11px;border-radius:var(--r-sm);background:var(--red-soft);color:var(--red);
  font-size:12.5px;font-weight:600}
.auth-err[hidden]{display:none}
.auth-who{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:12px;border:1px solid var(--line);
  border-radius:var(--r);background:var(--sky-50)}
.auth-who>span:not(.tag){color:var(--slate);font-size:12.5px}
.auth-actions{display:grid;gap:8px;margin-top:14px}
.auth-actions .btn{justify-content:center}
.auth-table .mut{font-size:12px;margin-top:2px}
.auth-user-chip{display:flex;align-items:center;gap:6px;max-width:180px}
.auth-user-chip span{max-width:112px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body.auth-locked>.app{filter:blur(2px);pointer-events:none;user-select:none}

/* ---------- khung ---------- */
.app{display:grid;grid-template-columns:var(--rail) 1fr;height:100vh}

.rail{
  background:linear-gradient(180deg,#2E333D 0%,#1F232B 100%);
  display:flex; flex-direction:column; padding:10px 8px 8px; gap:1px; overflow-y:auto;
  box-shadow:inset -1px 0 0 rgba(255,255,255,.06);
}
.rail::-webkit-scrollbar{width:0}
.brand{
  display:flex;flex-direction:column;align-items:center;gap:7px;
  padding:8px 4px 16px; color:#fff;
}
.brand-mark{
  width:40px;height:40px;border-radius:11px;background:#fff;
  display:grid;place-items:center;color:#fff;font-weight:800;font-size:16px;
  letter-spacing:-.4px;box-shadow:0 3px 10px rgba(0,0,0,.22);
}
.brand-mark.logo{padding:4px}
.brand-mark svg{width:100%;height:100%;display:block}
.brand-name{
  font-size:12px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;text-align:center;line-height:1.4;
}
.brand-name .brand-sub{
  font-size:12px;font-weight:600;letter-spacing:.1em;color:var(--sky-300);
}

.navbtn{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:5px;
  padding:10px 4px;border-radius:var(--r);color:#9AA3B2;
  font-size:12px;font-weight:600;text-align:center;line-height:1.25;letter-spacing:.01em;
  transition:background .12s,color .12s;
}
.navbtn svg{width:20px;height:20px;stroke-width:1.75;opacity:.92}
.navbtn:hover{background:rgba(255,255,255,.07);color:#fff}
.navbtn.on{background:rgba(255,255,255,.12);color:#fff}
.navbtn.on svg{opacity:1}
.navbtn.on::before{
  content:'';position:absolute;left:-8px;top:10px;bottom:10px;width:3px;border-radius:0 3px 3px 0;
  background:var(--or);
}
.rail-sp{flex:1}
.rail-line{height:1px;background:var(--sky-600);margin:6px 14px 4px}
.rail-ft{
  color:#AEB8C6;font-size:11px;text-align:center;padding:8px 2px 2px;   /* b323 · số bản ≥ 11px (anh cho), tương phản ≥ 4,5 trên thanh tối */
  letter-spacing:.06em;line-height:1.4;
  display:flex;align-items:center;justify-content:space-between;gap:7px;   /* huy hiệu trạng thái máy chủ (trang-thai.css) */
}

/* ══════════ b242 · THANH BÊN GỌN — chỉ biểu tượng, chữ hiện khi rê chuột ══════════
   Anh Đạt 16/09, gửi kèm ảnh thanh bên của app Claude: *"làm theo ảnh t gửi.
   V gọn app hơn, đỡ nguy cơ nhấn nhầm. Logo cũng để đúng kích thước lại"*.

   VÌ SAO GIỮ THANH chứ không giấu hẳn (anh hỏi 16/09, em đã đo và trả lời):
   thanh này là đường đi DUY NHẤT giữa các màn. Giấu đi thì mỗi lần đổi màn tốn
   2 cú bấm thay vì 1, và người mới — nhất là tiệm lạ sắp mời dùng thử — mở app
   lên không thấy đường nào mà đi. Thu còn biểu tượng giữ nguyên MỘT cú bấm.

   ĐO ĐƯỢC (245 tên hàng thật, 16/09): 92px → 48px trả lại chỗ cho lưới hàng,
   tên vừa một dòng 78% → 82% ở màn 1920, và 30% → 39% ở màn 1600.
   Chọn 56px chứ không 48px: vùng bấm phải đủ 40px (token --control-h) cộng lề
   8px mỗi bên. 48px thì nút chỉ còn 32px — nhỏ hơn ngưỡng bấm nhầm.

   CHỈ ÁP CHO MÁY TÍNH. Điện thoại (≤880px) thanh này nằm DƯỚI ĐÁY và VẪN CÓ
   CHỮ — `responsive-core.css` đặt --rail:0 rồi `mobile.css` dựng lại thành
   thanh đáy. Đụng vào đây mà quên chặn theo bề ngang là mất chữ ở đáy điện
   thoại, đúng cái tiệm đang dùng hằng ngày. */
@media (min-width:881px){
  /* Ô chữ hiện khi rê chuột phải THOÁT ra ngoài thanh, nên thanh không được
     cắt. Chỉ bỏ cắt khi cửa sổ đủ cao để 9 nút + logo + chân nằm gọn — đo được
     490px là đủ, lấy 640px cho rộng tay. Cửa sổ thấp hơn thì thanh cuộn lại
     như cũ và ô chữ bị cắt, nhưng đó là cảnh hiếm trên máy bàn. */
  .rail{overflow:hidden}
  @media (min-height:600px){ .rail{overflow:visible} }

  /* ---- logo: ngang hàng với thanh tiêu đề ----
     🔴 Anh Đạt 16/09 (lần hai): "vẫn lệch mà", gửi kèm ảnh cắt logo đặt cạnh
     chữ "Bán hàng" trên thanh tiêu đề. Lần trước em chỉnh lệch MÉP NGANG, còn
     cái anh thấy là lệch DỌC: thanh tiêu đề cao 56px nên tâm chữ ở y=28, mà
     logo nằm ở y 16→56, tâm 36 — thấp hơn đúng 8px. Nhìn dọc xuống thì logo
     và dòng chữ đầu màn không cùng một đường.
     Vá: khối logo cao ĐÚNG bằng `--head` và căn giữa trong đó, nên tâm logo
     luôn bằng tâm thanh tiêu đề, kể cả khi đổi `--head` sau này. */
  .rail{padding-top:0}
  .brand{height:var(--head);justify-content:center;margin-bottom:8px}

  /* ---- khung logo BẰNG ĐÚNG bề ngang nút ----
     🔴 Anh Đạt 16/09: "logo chỉnh cho cân với hàng ngang luôn, hiện tại lệch".
     Đo ra thì cả hai đều đúng tâm 28px — lệch không phải ở tâm mà ở MÉP: nút
     rộng 40px (x 8→48), khung logo 36px (x 10→46), thụt vào 2px mỗi bên. Ô
     trắng tương phản mạnh nên 2px đó nhìn ra ngay. Nay khung logo = 40px, mép
     trùng khít mép nền nút — cùng một cột thẳng từ trên xuống. */
  .brand{padding:0;gap:0}
  .brand-mark{width:40px;height:40px;border-radius:11px}
  .brand-name{display:none}

  /* ---- nút: chỉ còn biểu tượng ---- */
  .navbtn{padding:9px 4px;gap:0;min-height:40px;justify-content:center}
  .navbtn svg{width:21px;height:21px}

  /* ---- chữ thành ô chỉ dẫn nổi bên phải ----
     Giữ nguyên thẻ <span> làm tên đọc được của nút (trình đọc màn hình vẫn
     đọc đúng), chỉ đổi cách vẽ. Đừng thay bằng display:none — làm thế là nút
     mất tên, người khiếm thị nghe thành "nút" trống. */
  .navbtn>span{
    position:absolute;left:calc(100% + 9px);top:50%;
    transform:translateY(-50%) translateX(-4px);
    background:#1B1F26;color:#fff;padding:7px 11px;border-radius:9px;
    font-size:12.5px;font-weight:600;letter-spacing:0;line-height:1;
    white-space:nowrap;text-transform:none;
    opacity:0;pointer-events:none;z-index:90;
    box-shadow:0 8px 24px rgba(0,0,0,.30);
    transition:opacity .12s ease,transform .12s ease;
  }
  .navbtn:hover>span,
  .navbtn:focus-visible>span{opacity:1;transform:translateY(-50%) translateX(0)}
  @media (prefers-reduced-motion:reduce){
    .navbtn>span{transition:none}
  }

  /* ---- chân thanh: xếp dọc cho vừa 56px ---- */
  .rail-line{margin:6px 10px 4px}
  /* b284 · huy hiệu Online RỘNG 49px mà ô chân chỉ chừa 40px (padding 8px mỗi bên) → chữ
     xuống hai dòng, pill trườn ra khỏi cột (soi ảnh 21/09). Hạ đệm ngang còn 2px cho đủ
     52px, và khóa nowrap để không bao giờ gãy dòng nữa. Số ms đã dọn sang tooltip. */
  /* b293 · VẪN TRÀN — đo 22/09: `.rail` còn padding 8px mỗi bên nên lòng chân chỉ 36px,
     chữ "● Online 2" cần 54px ⇒ số "2" rơi ra ngoài nền (anh Đạt chụp ảnh). Bản vá b284 chỉ
     hạ đệm của .rail-ft, quên lớp ngoài (Sổ lỗi #93). Nay chân thanh THOÁT đệm của .rail
     (margin âm) để dùng trọn 56px, và huy hiệu bỏ giãn chữ + bớt đệm — giữ đủ chữ, giữ cỡ 8px
     (phương án C anh Đạt chọn 22/09). KHÔNG đụng padding của .rail: nó xếp các nút điều hướng. */
  .rail-ft{display:flex;flex-direction:column;align-items:center;padding:8px 0 2px;margin:0 -8px}
  .rail-ft .server-mode{max-width:none;white-space:nowrap;letter-spacing:0;padding:3px 4px;gap:3px}
}

/* Cỡ chữ lớn: thanh rộng hơn một chút và biểu tượng to hơn — người dùng chế độ
   này nhìn kém, biểu tượng 21px là nhỏ. Chữ vẫn chỉ hiện khi rê chuột. */
@media (min-width:881px){
  body.big{--rail:64px}
  body.big .navbtn{min-height:46px}
  body.big .brand-mark{width:48px;height:48px;border-radius:13px}   /* = bề ngang nút ở cỡ chữ lớn */
  body.big .navbtn>span{font-size:14px;padding:8px 12px}
}

.main{display:flex;flex-direction:column;min-width:0;overflow:hidden}
.head{
  height:var(--head);flex:0 0 var(--head);background:var(--paper);
  border-bottom:1px solid var(--line);display:flex;align-items:center;
  gap:10px;padding:0 16px;
}
.head h1{margin:0;font-size:16px;font-weight:750;letter-spacing:-.35px;white-space:nowrap;line-height:1.2}
.head .sub{font-size:12px;color:var(--slate);font-weight:500;white-space:nowrap;line-height:1.2}
/* Đầu màn Bán hàng (anh Đạt chốt 03/09): tên màn và số hóa đơn cùng độ cao
   chữ, không cái nào bị đẩy lên. Tên tiệm là thông tin PHỤ — chữ thường,
   nhạt, tách bằng một vạch đứng chứ không dính thành một chuỗi nặng. */
.pos-head-invoice{display:inline-flex;align-items:baseline;gap:9px;padding-left:2px}
.pos-head-invoice b{font-family:var(--f-mono);font-size:13px;color:var(--ink-2);font-weight:700;letter-spacing:-.01em}
.pos-head-shop{font-style:normal;font-size:12px;font-weight:500;color:var(--slate-2);letter-spacing:.01em;
  padding-left:9px;border-left:1px solid var(--line-2)}
.head-sp{flex:1}
@media (max-width:1240px){.pos-head-shop{display:none}}
.pill{
  display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:100px;
  font-size:12px;font-weight:600;background:var(--sky-50);color:var(--sky-700);
  white-space:nowrap;
}
.pill .dot{width:7px;height:7px;border-radius:50%;background:var(--green)}
.pill.or{background:var(--or-50);color:var(--or-7)}
.pill.or .dot{background:var(--or)}
.pill.warn{background:var(--red-soft);color:var(--red)}
.pill.warn .dot{background:var(--red)}

.view{flex:1;overflow:auto;padding:18px}
/* b300 · khung chờ trong index.html — hiện lúc gói giao diện còn đang tải/chạy; app vẽ màn đầu tiên là nó mất */
.kc{display:grid;gap:14px;max-width:1100px}
.kc-chu{margin:0;color:var(--slate);font-size:14px;font-weight:600}
.kc-o{height:56px;border-radius:var(--r-lg);background:var(--paper);box-shadow:var(--shadow)}
.kc-luoi{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:12px}
.kc-luoi i{height:112px;border-radius:var(--r-lg);background:var(--paper);box-shadow:var(--shadow);animation:kc-nhip 1.4s ease-in-out infinite}
@keyframes kc-nhip{50%{opacity:.5}}
@media (prefers-reduced-motion:reduce){.kc-luoi i{animation:none}}
.view.pos{padding:0;overflow:hidden}

/* ---------- nút ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  min-height:var(--control-h);padding:9px 15px;border-radius:var(--r);font-weight:600;font-size:13.5px;
  background:var(--paper);border:1px solid var(--line);color:var(--ink);
  white-space:nowrap;transition:background .08s ease-out,border-color .08s ease-out;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
}
.btn:hover{background:var(--sky-50);border-color:var(--sky-300)}
.btn:active{transform:translateY(1px)}
.btn svg{width:16px;height:16px;stroke-width:2}
.btn.pri{background:var(--sky-600);border-color:var(--sky-600);color:#fff}
.btn.pri:hover{background:var(--sky-700);border-color:var(--sky-700)}
.btn.acc{
  background:var(--or-safe);border-color:var(--or-safe);color:#fff;
  box-shadow:0 1px 2px rgba(194,87,6,.2);
}
.btn.acc:hover{background:var(--or-safe-hover);border-color:var(--or-safe-hover)}
.btn.dg{color:var(--red);border-color:#EDD3D0}
.btn.dg:hover{background:var(--red-soft);border-color:#E3B9B4}
.btn.sm{min-height:34px;padding:6px 11px;font-size:12.5px}
.btn.big{padding:13px 20px;font-size:15px;font-weight:700;width:100%;letter-spacing:.01em}
.btn[disabled]{opacity:1;cursor:not-allowed;box-shadow:none;background:#F1F3F5;
  border-color:#DEE1E6;color:#9097A2}
.btn.pri[disabled]{background:#D9DDE2;border-color:#D9DDE2;color:#7D858F}
.btn.acc[disabled]{background:#F6E7DA;border-color:#EED8C5;color:#A47D64}
.btn[disabled]:hover{background:#F1F3F5;border-color:#DEE1E6;color:#9097A2}
.btn.pri[disabled]:hover{background:#D9DDE2;border-color:#D9DDE2;color:#7D858F}
.btn.acc[disabled]:hover{background:#F6E7DA;border-color:#EED8C5;color:#A47D64}
.btn[disabled]:active{transform:none}

/* Một hành động chính, các công cụ ít dùng nằm trong menu theo ngữ cảnh. */
.head-actions{position:relative;z-index:12}
.head-actions>summary{list-style:none;cursor:pointer}
.head-actions>summary::-webkit-details-marker{display:none}
.head-actions[open]>summary{background:var(--sky-50);border-color:var(--sky-300)}
.head-actions-menu{
  position:absolute;right:0;top:calc(100% + 8px);width:300px;padding:6px;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-md);display:grid;gap:2px
}
.head-actions-menu button{display:flex;align-items:center;gap:10px;width:100%;padding:10px;
  border-radius:var(--r);text-align:left;color:var(--ink)}
.head-actions-menu button:hover{background:var(--sky-50)}
.head-actions-menu button>svg{width:18px;height:18px;flex:0 0 auto;color:var(--slate)}
.head-actions-menu button>span{display:flex;flex-direction:column;min-width:0}
.head-actions-menu strong{font-size:13px;font-weight:700}
/* b296 · đường lui về màn cha — đứng TRƯỚC tiêu đề, không lẫn vào dãy nút việc (soát 24/09 mục 14) */
.head-back{display:inline-flex;align-items:center;gap:var(--space-1);min-height:40px;padding:0 var(--space-2) 0 var(--space-1);
  margin-left:calc(-1 * var(--space-1));border:0;border-radius:var(--r-sm);background:none;cursor:pointer;
  color:var(--slate);font:600 12.5px/1 var(--f-ui);white-space:nowrap}
.head-back:hover{background:var(--sky-50);color:var(--ink)}
.head-back svg{width:16px;height:16px}
/* Nút icon 33px -> 40px cho đạt vùng bấm (sổ tay mục 1, đồng bộ .icobtn.lg b130).
   (Nút ✕ bỏ dòng trong phiếu b229 đã thôi ở b296 — dòng phiếu dùng nút ⋯, pos.css .dmenu.) */
/* 🔴 `display:grid` là KHỐI — hai nút icon cạnh nhau tự xếp CHỒNG DỌC, dù ô
   chứa đã khai `white-space:nowrap` (nowrap chỉ lo chữ, không lo khối). Bảng
   thiết bị cho thuê vì thế có bút chì nằm trên thùng rác, dòng cao gấp đôi và
   hai đích bấm dính nhau. `inline-grid` giữ nguyên cách xếp bên trong, chỉ đổi
   cách nút đứng với nút bên cạnh. */
.icobtn{
  width:40px;height:40px;border-radius:var(--r);display:inline-grid;place-items:center;vertical-align:middle;
  color:var(--slate);transition:background .12s,color .12s;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
}
.icobtn:hover{background:var(--sky-100);color:var(--sky-700)}
.icobtn svg{width:18px;height:18px;stroke-width:2}
.icobtn.xl{width:33px;height:33px}
.icobtn.xl svg{width:16px;height:16px}
.icobtn.dg:hover{background:var(--red-soft);color:var(--red)}

/* ===== SOURCE: styles/pos.css ===== */
/* ---------- màn bán hàng ---------- */
/* Bố cục màn Bán hàng:
   tab hóa đơn trên cùng · thanh quét · phiếu bán hàng ở giữa · bán chạy bên phải
   Kết quả tìm chỉ bung ra khi gõ/nói, không chiếm chỗ thường trực. */
/* Bố cục màn Bán hàng: hàng hóa bên trái · phiếu bán hàng bên phải, cả hai cùng nhìn thấy.
   Cột trái là một vùng cuộn: gõ tìm thì kết quả chèn lên trên, hàng bán chạy tụt xuống. */
.pos3{display:grid;grid-template-columns:minmax(0,1fr) 440px;gap:18px;height:100%;min-height:0;padding:12px 14px 14px}
.pos3-main{display:flex;flex-direction:column;min-width:0;min-height:0;gap:10px;overflow:hidden}
/* Khu trên cuộn được (hàng trong kho / kết quả tìm),
   dải Hàng bán chạy ghim cứng ở đáy — không xê dịch khi tìm hàng. */
.pane{flex:1;min-height:0;display:flex;flex-direction:column;contain:layout paint;
  padding:9px 10px 10px;background:#EEF3F7;border:1px solid #C8D4DC;border-radius:var(--r-lg)}
.results{overflow:auto;min-height:0;padding-right:2px}
.results::-webkit-scrollbar{width:8px}
.results::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.tabsbar:empty{display:none}
.results[hidden]{display:none}
.results{display:block}

.scanner{
  background:var(--paper);border:1.5px solid var(--sky-600);
  border-radius:var(--r-lg);padding:11px 14px;
  display:flex;align-items:center;gap:12px;box-shadow:0 2px 12px rgba(24,27,32,.08);
  transition:border-color .12s, box-shadow .12s;
}
.led{
  width:9px;height:9px;border-radius:50%;background:#42D39B;flex:0 0 auto;
  box-shadow:0 0 0 3px rgba(66,211,155,.22);animation:pulse 2.2s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){.led{animation:none}}
.scan-field{flex:1;min-width:0}
.scan-field input{
  background:transparent;border:0;padding:0;color:var(--ink);font-family:var(--f-mono);
  font-size:19px;font-weight:700;letter-spacing:.04em;
}
.scan-field input:focus{box-shadow:none}
/* Ô quét lúc nào cũng đang chờ gõ — vẽ khung cam quanh input thành cái hộp thô.
   Bỏ khung ở riêng ô này; thay bằng cả THANH QUÉT sáng nhẹ lên khi có con trỏ. */
#scan:focus-visible{outline:none}
.scanner:focus-within{border-color:var(--ink-2);box-shadow:0 0 0 3px rgba(59,66,79,.14), 0 2px 12px rgba(24,27,32,.08)}
.scan-field input::placeholder{color:var(--slate);font-weight:400;letter-spacing:0}
.scan-cam{
  width:40px;height:40px;border-radius:var(--r);background:var(--sky-50);border:1px solid var(--line);
  display:grid;place-items:center;color:var(--sky-700);flex:0 0 auto;transition:background .12s,color .12s;
}
.scan-cam:hover{background:var(--or-safe);border-color:var(--or-safe);color:#fff}
.scan-cam svg{width:19px;height:19px;stroke-width:1.8}

/* thẻ sản phẩm → styles/the-hang.css (b298: mọi luật của thẻ hàng về MỘT tệp — gốc, chữ to,
   ảnh trong thẻ, điện thoại, màn ≥1600px). Ở đây chỉ còn dòng "Còn N kết quả" bên dưới lưới. */
.res-more{text-align:center;font-size:12px;color:var(--slate);padding:10px 0 4px}
.res-more b{color:var(--ink-2)}

/* b183 · Dải danh mục ở quầy (anh Đạt chốt 03/09): không tiêu đề, không khung
   bao, không nút Quản lý. Chỉ còn những ô LỚN tô đặc màu xanh than — khác hẳn
   thẻ hàng màu trắng bên trên nên nhìn một cái là biết đâu là bộ lọc, đâu là
   hàng. Ô đang chọn đổi sang cam, chữ đen (6,35:1). */
.pos-quick{flex:0 0 auto;padding:0;background:transparent;border:0}
.pos-quick[hidden]{display:none}
/* Máy tính: ô xuống dòng thay vì trốn sang phải — cuộn ngang bằng chuột khó, mà ô bị cắt nửa thì không ai bấm. */
/* b324 · anh Đạt 28/09: trả về y hệt b310 (flex-wrap) — anh chốt giữ dáng b310 "đang sử dụng tốt". Lưới
   auto-fill của b323 làm tiệm một nhóm bị cụt chữ ("Hay bán (mẫ…"); chữ lớn ra 4 ô + ô cuối dài hết hàng là ĐÚNG. */
.pos-qcats{display:flex;flex-wrap:wrap;gap:var(--space-3);padding:2px 2px 4px}
.pos-qcat{flex:1 1 150px;min-width:0;min-height:64px;display:flex;flex-direction:column;justify-content:center;gap:2px;
  padding:var(--space-2) var(--space-4);text-align:left;background:#173247;border:2px solid #173247;border-radius:var(--r-lg);color:#fff;
  transition:background-color var(--motion-fast),border-color var(--motion-fast),transform var(--motion-fast)}
.pos-qcat:hover{background:#071F31;border-color:#071F31}
.pos-qcat:active{transform:scale(.98)}
.pos-qcat.on{background:var(--or);border-color:var(--or-6);color:var(--ink)}
.pos-qcat.on:hover{background:var(--or-6)}
.pos-qcat strong,.pos-qcat small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pos-qcat strong{font-size:16px;font-weight:700;line-height:1.25}
.pos-qcat small{font-size:12.5px;font-weight:400}

/* Trình quản lý danh mục: chỉ sửa bản nháp. posQuickSave mới ghi cấu hình. */
.posq-manager{display:grid;grid-template-columns:290px minmax(0,1fr);gap:14px;min-height:430px}
.posq-side,.posq-edit{min-width:0;border:1px solid var(--line);border-radius:var(--r);padding:10px;background:var(--bg)}
.posq-side{display:flex;flex-direction:column;gap:9px}.posq-side-hd{display:flex;justify-content:space-between;color:var(--slate);font-size:12px}
.posq-catlist{display:flex;flex-direction:column;gap:6px;overflow:auto;max-height:340px}
.posq-catrow{display:grid;grid-template-columns:minmax(0,1fr) 40px 30px 30px 30px;gap:4px;align-items:center;padding:3px;border:1px solid transparent;border-radius:8px}
.posq-catrow.off .posq-catpick strong{color:var(--slate);text-decoration:line-through}
/* công tắc bật/tắt danh mục — xanh than = đang hiện ở quầy */
.posq-toggle{width:36px;height:20px;border-radius:999px;background:#AEBFCB;border:0;position:relative;justify-self:center;
  transition:background-color var(--motion-fast)}
.posq-toggle i{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;transition:left var(--motion-fast)}
.posq-toggle.on{background:#173247}.posq-toggle.on i{left:18px}
.posq-catrow.on{border-color:#173247;background:#EAF3F8}.posq-catpick{text-align:left;min-width:0;padding:5px}
.posq-catpick strong,.posq-catpick small{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.posq-catpick strong{font-size:12px}.posq-catpick small{font-size:12px;color:var(--slate)}
.posq-edit{background:#fff}.posq-picked{display:flex;justify-content:space-between;align-items:center;gap:var(--space-2);flex-wrap:wrap;font-size:12px;color:var(--slate);margin:7px 0}
.posq-picked-act{display:flex;gap:var(--space-3)}.posq-picked-act .text-action{font-size:12px}.posq-picked-act .text-action.dgr{color:var(--red)}
.posq-products{display:grid;grid-template-columns:1fr 1fr;gap:7px;max-height:326px;overflow:auto;padding-right:3px}
.posq-product{display:grid;grid-template-columns:24px minmax(0,1fr);align-items:center;gap:7px;text-align:left;
  padding:8px;border:1px solid var(--line);border-radius:8px;background:#fff}
.posq-product.on{border-color:#173247;background:#EAF3F8}.posq-check{width:20px;height:20px;display:grid;place-items:center;
  border:1px solid #9EB1BE;border-radius:5px;color:#fff;background:#fff;font-weight:800}
.posq-product.on .posq-check{background:#173247;border-color:#173247}
.posq-product strong,.posq-product small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.posq-product strong{font-size:12px}.posq-product small{font-size:12px;color:var(--slate)}
.posq-none,.posq-empty{padding:20px;text-align:center;color:var(--slate);font-size:12px}.posq-products>.posq-none{grid-column:1/-1;padding:8px 4px 10px;text-align:left}.posq-empty{display:grid;place-content:center;gap:5px;height:100%}

/* Một popup duy nhất, không nhận chuột, nên rê ảnh không bao giờ cướp cú bấm
   của thẻ sản phẩm. JavaScript tự đặt nó bên trái khi bên phải là phiếu. */
.pos-img-preview{position:fixed;z-index:120;width:270px;pointer-events:none;filter:drop-shadow(0 12px 25px rgba(7,31,49,.24))}
.pos-img-preview[hidden]{display:none}.pos-img-frame{padding:10px;background:#fff;border:2px solid #173247;border-radius:12px}
.pos-img-frame img{display:block;width:246px;height:222px;object-fit:contain;background:#F7FAFC;border-radius:8px}
.pos-img-frame strong,.pos-img-frame small,.pos-img-frame b{display:block;margin-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pos-img-frame strong{font-size:14px;color:var(--ink)}.pos-img-frame small{font-size:12px;color:var(--slate)}
.pos-img-frame b{font-size:16px;color:#173247}

/* ---------- hóa đơn đang bán ---------- */
.tape-col{position:relative;display:grid;grid-template-rows:1fr;min-height:0;min-width:0;overflow:hidden}
/* Khung phiếu dùng lưới 3 hàng: răng cưa · ruột phiếu (co giãn) · răng cưa.
   Phần thanh toán nằm cuối ruột phiếu, luôn dính đáy, không bao giờ bị đẩy khỏi màn hình. */
.tape{
  background:var(--paper);display:grid;grid-template-rows:auto 1fr auto;min-height:0;
  position:relative;border-radius:8px;overflow:hidden;
  /* Tách hẳn khỏi khu giữa: viền xanh đậm + bóng đổ sâu.
     Trước đây nền #F4F5F7 và phiếu #FFFFFF chỉ chênh 1,07 lần — mắt không tách được. */
  border:2px solid var(--sky-600);
  box-shadow:0 4px 16px rgba(8,51,79,.14), 0 1px 3px rgba(8,51,79,.10);
}

.zig{height:7px;flex:0 0 7px;background-color:transparent;
  background-image:
    linear-gradient(45deg, var(--paper) 50%, transparent 50%),
    linear-gradient(-45deg, var(--paper) 50%, transparent 50%);
  background-size:10px 7px;background-repeat:repeat-x;
}
.zig.top{transform:rotate(180deg)}
/* 4 hàng: đầu phiếu / khách / danh sách hàng / chân phiếu.
   b304 · ruột KHÔNG đệm ngang — mỗi khối tự đệm; dòng hàng và hai dải nền (đầu, chân) chạy trọn bề ngang,
   khỏi kéo lề âm như trước. */
.tape-in{display:grid;grid-template-rows:auto auto 1fr auto;grid-template-columns:minmax(0,1fr);min-height:0;min-width:0;overflow:hidden}
.tape-in>*{min-width:0}

/* ═══ b304 · ĐẦU PHIẾU MỘT DÒNG: HĐ · số món · [Thuế · giảm giá] · [⋯] ═══
   Bỏ thanh tối "PHIẾU BÁN HÀNG" + dòng tên tiệm + ngày giờ (b303: 42 + 34px): đầu màn đã có số HĐ và tên tiệm, phiếu
   in có ngày. Điện thoại dùng đúng các lớp này trong .gio-top (mobile-runtime.css). Sửa hóa đơn cũ: nền cam (hoa-don.css). */
.tape-bar{display:flex;align-items:center;gap:6px;min-height:42px;padding:0 6px 0 14px;
  border-bottom:1px solid var(--line)}
.tape-td{flex:1 1 auto;min-width:0;display:flex;align-items:center;white-space:nowrap;overflow:hidden;color:var(--ink)}
.tape-td b{font:700 14px var(--f-mono)}
.tape-td svg{width:14px;height:14px;margin-right:6px;flex:0 0 auto}
.tape-phu{margin-left:4px;overflow:hidden;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--slate)}
.tape-tg{flex:0 0 auto;position:relative;height:30px;padding:0 12px;border:1px solid var(--line);border-radius:99px;
  background:#fff;font:600 12.5px var(--f-ui);color:var(--sky-700);white-space:nowrap}
.tape-tg:hover{border-color:var(--sky-400)}
.tape-tg.on{background:var(--sky-100);border-color:var(--sky-400);color:var(--sky-800)}
.tape-tg:has(+ .tape-dots[hidden]){margin-right:6px}   /* sửa hóa đơn cũ: ⋯ ẩn — nút không dính mép phải */
/* đã đặt thuế hoặc giảm giá mà bảng đang gấp → chấm cam, khỏi quên là phiếu có cộng / trừ */
.tape-tg.co::after{content:"";position:absolute;top:-2px;right:-2px;width:9px;height:9px;border-radius:50%;
  background:var(--or);border:2px solid #fff}
.tape-dots{flex:0 0 auto;width:32px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--slate)}
.tape-dots:hover,.tape-dots[aria-expanded="true"]{background:var(--sky-100);color:var(--ink)}
.tape-dots svg{width:18px;height:18px}
.tape-dots[hidden]{display:none}
/* ═══ b307 · ĐẦU PHIẾU DỄ NHÌN CHO NGƯỜI LỚN TUỔI — anh Đạt 25/09 đối chiếu ═══
   Nền XANH THAN cùng biến --sky-900 đang dùng ở ô "Tiền mặt" đang chọn (.pseg.on) và thanh bên (.rail) — KHÔNG
   thêm mã màu mới. Chữ trắng / --sky-300 đạt tương phản 17,3:1 / 9,6:1 trên nền này (≥ 4.5:1 WCAG AA). Vòng focus
   mặc định (outline cam 2,5px, tương phản 6,2:1 trên nền tối) không cần sửa gì thêm — đã thấy rõ.
   .tape-bar.ed / .gio-top.ed (sửa hóa đơn cũ) GIỮ NGUYÊN nền cam đã có (hoa-don.css): máy tính tự thắng nhờ
   specificity 2 lớp; .gio-top trên điện thoại chưa có nền riêng cho lúc sửa nên loại tay bằng :not(.ed) ở đây,
   đừng bỏ — bỏ là chữ cam (--or-safe, 2,95:1) rơi lên nền xanh than, hỏng tương phản. */
.tape-bar:not(.ed),.gio-top:not(.ed){background:var(--sky-900)}
.tape-bar:not(.ed) .tape-td,.gio-top:not(.ed) .tape-td{color:#fff}
.tape-bar:not(.ed) .tape-phu,.gio-top:not(.ed) .tape-phu{color:var(--sky-300)}
.tape-bar:not(.ed) .tape-dots,.gio-top:not(.ed) .tape-dots{color:var(--sky-300)}
/* răng cưa đầu phiếu (7px, máy tính) nằm ngay trên thanh: nền trắng của nó thành một dải trắng lạc trên nền tối ⇒ tô cùng
   màu thanh (giữ nguyên chiều cao — không đổi số món thấy trọn). Sửa hóa đơn cũ (thanh cam) giữ răng cưa như cũ. */
.tape:has(> .tape-in > .tape-bar:not(.ed)) > .zig.top{background:var(--sky-900)}

/* Khách: chưa chọn thì hai ô gõ (dải dưới); đã chọn thì MỘT THẺ (khach-hang.css .custline) — cùng nền, cùng vạch trái. */
.cust-band{padding:6px 7px;background:#EEF5F8;border-left:3px solid #315C73;border-radius:8px}
.cust-row{display:grid;grid-template-columns:minmax(0,1fr) 134px 34px;gap:6px}
.cust-row input{padding:7px 9px;font-size:13px;background:#fff;border-color:#C8D8E1}
.cbtn{
  display:grid;place-items:center;border:1px solid var(--line);border-radius:var(--r);
  background:#fff;color:var(--sky-700);
}
.cbtn svg{width:15px;height:15px;stroke-width:2}
.cbtn:hover{background:var(--sky-100);border-color:var(--sky-400)}
.cbtn.on{background:var(--sky-600);border-color:var(--sky-600);color:#fff}
/* --giu-day: đệm đáy tạm sau khi bỏ dòng (xem GIU_DAY trong pos.js) */
.items{overflow-y:auto;overflow-x:hidden;min-height:0;padding:0 0 calc(4px + var(--giu-day, 0px))}
.items::-webkit-scrollbar{width:7px}
.items::-webkit-scrollbar-thumb{background:var(--line);border-radius:7px}
/* ═══ b304 · DÒNG PHIẾU [tên] [ô SL] [thành tiền] [⋯] — đúng thứ tự hóa đơn in: Tên · SL · Thành tiền ═══
   Lịch sử: b229 bốn cột [X][tên][giá][bút] → b296 ba cột [tên][tiền][⋯] + một hàng −/+ · đơn vị · ghi chú riêng bên
   dưới (b303 mỗi món 85–146px: 1366×768 chỉ thấy trọn 2/6 món). Nay MỘT hàng: ô SL là ô gõ luôn có sẵn; dải lẻ ⇄
   nguyên · − · + · Xong chỉ mở dưới dòng đang sửa (.sl-dai). Tên sát mép trái (luật 24/09 giữ nguyên). Các cột canh
   DÒNG ĐẦU của tên (--dong1): tên dài hai dòng thì SL, tiền, ⋯ không trôi xuống giữa. --cot-but/--khe = cột ⋯ và khe
   cột: hàng pha màu (management.css .maurow) chừa đúng bằng đó để tiền màu thẳng cột thành tiền. */
.item{
  --dong1:21px;--cot-but:22px;--khe:10px;   /* b307 · theo cỡ chữ mới (tên 16 / tiền 18px) */
  display:grid;grid-template-columns:minmax(0,1fr) 54px 116px var(--cot-but);column-gap:var(--khe);align-items:start;
  padding:8px 4px 8px 12px;border-bottom:1px solid var(--line-2);transition:background .12s;
}
.item:hover,.item:focus-within{background:var(--sky-50)}
.item.mo{background:#FFF9F2}   /* dòng đang mở dải số lượng — đứng SAU :hover để thắng nó */
/* b307 · tên hàng + thành tiền TO THÊM MỘT BẬC (thang chữ TO-NHAN-DIEN.md: tên t3→t4, tiền t4→t5 — người lớn tuổi
   đọc phiếu xa hơn). Cột tiền vẫn 96px cố định; chỉ số RẤT DÀI (.dai, ≥ 100 triệu) mới cần cỡ tự co để lọt cột —
   giữ nguyên các cỡ đó (đã tính khít, xem #187 số dài nhất có thật). */
.item .nm{grid-column:1;grid-row:1;min-width:0;display:flex;flex-direction:column;gap:2px;
  font-size:16px;font-weight:600;line-height:var(--dong1);overflow-wrap:anywhere}
.item .ghi{display:flex;align-items:baseline;gap:4px;font-size:12px;font-weight:500;font-style:italic;line-height:16px;color:var(--sky-600)}
.item .ghi svg{width:11px;height:11px;flex:0 0 auto;stroke-width:2;position:relative;top:1px}
.item .vuot{font-size:12px;font-weight:600;line-height:16px;color:var(--or-safe)}
/* Ô SỐ LƯỢNG: số to ở giữa, đơn vị nhỏ dưới đáy — bấm chỗ nào trong ô cũng là gõ. */
.slo{grid-column:2;grid-row:1;position:relative;display:block;height:40px;margin-top:-1px;cursor:text}
.slo input{position:absolute;inset:0;width:100%;height:100%;padding:0 2px 12px;border-radius:8px;
  text-align:center;font:700 15px var(--f-mono);color:var(--ink)}
.slo input:hover{border-color:var(--sky-400)}
.slo input:focus,.item.mo .slo input{border-color:var(--or);box-shadow:var(--focus-ring)}
.slo.dai input{font-size:13px}   /* số lẻ dài ("12,375") vẫn lọt ô */
.dvi{position:absolute;left:2px;right:2px;bottom:4px;pointer-events:none;text-align:center;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;font-size:12px;font-weight:600;line-height:12px;color:var(--slate)}
/* b223 · CỤM TIỀN: đúng MỘT con số (thành tiền); "đơn giá × số lượng" chỉ hiện khi số lượng khác 1 — bỏ hẳn là mất
   thông tin, để thường trực là lại thành hai số như trước b223. b229 · 16px: "giá tiền nhìn to hơn 1 chút". */
.item .tt{grid-column:3;grid-row:1;display:flex;flex-direction:column;align-items:flex-end;gap:1px;
  font:800 18px var(--f-mono);text-align:right;white-space:nowrap}
.item .tt b{font-weight:800;line-height:var(--dong1)}
/* Cột tiền rộng CỐ ĐỊNH để ô SL mọi dòng thẳng hàng — số dài phải tự thu vào cột, không được tràn sang trái (ô SL nằm đè
   lên phần tràn: kiểm độc lập 25/09 thấy "1.800.000 × 2,5" thành "800.000 × 2,5"). Thành tiền từ 100 triệu ("125.000.000",
   11 ký tự) chữ nhỏ lại (.dai, pos-phieu.js) — tới 99 triệu vẫn 16px như luật b229; dòng "đơn giá × SL" được xuống dòng. */
.item .tt.dai b{font-size:14.5px}
.item .tt.over b,.item .tt.over .ttin{color:var(--or-7)}
/* Đang sửa đơn giá: ô nhập lấn sang chỗ ô SL (ẩn tạm) — giá cả triệu ("1.800.000 / tấn") gõ vẫn thấy đủ số trên điện
   thoại; số lượng vẫn đọc được ở dòng "đơn giá × SL" ngay dưới. */
.item .tt.dangsua{grid-column:2/4}
.item:has(.tt.dangsua) .slo{display:none}
/* Ô nhập đơn giá mở ra ĐÚNG chỗ con số vừa đứng — mắt không phải đi tìm. */
.item .ttin{
  width:100%;height:24px;padding:0 5px;text-align:right;
  font-family:var(--f-mono);font-size:inherit;font-weight:800;color:var(--ink);
  border:1px solid var(--sky-400);border-radius:5px;background:var(--sky-50);
}
.item .ttin:focus{box-shadow:none;background:#fff}
.item .ttx{font-size:12px;font-weight:500;line-height:15px;color:var(--slate-2);white-space:normal}
.item .dmenu{
  grid-column:4;grid-row:1;justify-self:end;width:26px;height:26px;margin:-3px -4px 0 0;
  display:grid;place-items:center;border-radius:5px;
  color:var(--slate-2);opacity:.5;transition:opacity .12s,color .12s,background .12s;
}
.item .dmenu svg{width:16px;height:16px}
/* ⋯ MỜ THƯỜNG TRỰC chứ không ẩn hẳn (cùng lý do cây bút cũ, anh Đạt 10/09): ẩn đi thì không ai biết
   là bấm được. Rê vào / đang mở menu thì đậm. Máy cảm ứng: đậm luôn (management.css, mobile-runtime.css). */
.item:hover .dmenu,.item:focus-within .dmenu,.item .dmenu[aria-expanded="true"]{opacity:1}
.item .dmenu:hover,.item .dmenu[aria-expanded="true"]{background:var(--sky-100);color:var(--sky-700)}
/* menu ⋯ — gắn vào <body> (ngoài danh sách cuộn nên không bị xén), vị trí đặt bằng JS */
.dmenu-pop{position:fixed;z-index:95;min-width:210px;padding:var(--space-1);display:grid;gap:2px;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-md)}
.dmenu-pop button{display:flex;align-items:center;gap:var(--space-2);width:100%;min-height:36px;padding:0 var(--space-3);
  border:0;border-radius:var(--r);background:none;text-align:left;cursor:pointer;font:600 13px/1.2 var(--f-ui);color:var(--ink)}
.dmenu-pop button:hover,.dmenu-pop button:focus-visible{background:var(--sky-50)}
.dmenu-pop button svg{width:16px;height:16px;flex:0 0 auto;color:var(--slate)}
.dmenu-pop button b{font-family:var(--f-mono);font-weight:700}
.dmenu-pop .dg,.dmenu-pop .dg svg{color:var(--red)}
.dmenu-pop .dmenu-vach{height:1px;margin:2px var(--space-2);background:var(--line)}
/* b304 · dòng đầu menu của một món: mã · tên — mã hàng rời khỏi dòng phiếu cho tên rộng chỗ, đối chiếu ở đây */
.dmenu-td{max-width:260px;padding:6px 12px 8px;margin-bottom:2px;border-bottom:1px solid var(--line);
  font-size:12.5px;line-height:1.35;color:var(--slate)}
.dmenu-td b{display:block;margin-bottom:1px;font-size:12px;color:var(--ink)}
/* ═══ b304 · DẢI SỬA SỐ LƯỢNG — chỉ dòng đang mở (pos.js slMo) ═══
   Lẻ ⇄ nguyên là hai nút đoạn ghi rõ quy đổi ("Tấn = 20 bao") thay nút ⇄ phải đọc title mới biết đang bán theo gì.
   Cùng kiểu đoạn với ô Thuế GTGT trong bảng Thuế · giảm giá (.tg-doan). */
/* b309 · mã nhiều đơn vị (Mét · Cuộn 100m · Cuộn 50m): dải xuống hàng thay vì cắt mất nút cuối */
.sl-dai{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px;padding:6px;
  border:1px solid #F3C9A2;border-radius:10px;background:#fff}
.sl-cach{flex:1 1 auto}
.sl-doan,.tg-doan{display:inline-flex;max-width:100%;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:#fff}
.sl-doan{flex-wrap:wrap}
/* ba đơn vị trở lên: nhóm đơn vị một hàng, − + Xong cùng hàng dưới canh phải (không tách đôi) */
.sl-doan.nhieu+.sl-cach{flex:0 0 100%;height:0;margin:-3px 0}
.sl-doan.nhieu+.sl-cach+.sl-b{margin-left:auto}
.sl-doan button,.tg-doan button{height:32px;padding:0 12px;font:600 13px var(--f-ui);color:var(--ink-2);white-space:nowrap}
.sl-doan button+button,.tg-doan button+button{border-left:1px solid var(--line)}
.sl-doan button.on,.tg-doan button.on{background:var(--sky-900);color:#fff}
.sl-doan i{font-style:normal;font-size:12px;font-weight:500;opacity:.8}
.sl-b{width:40px;height:32px;border:1px solid var(--line);border-radius:8px;background:#fff;
  font:700 18px/1 var(--f-ui);color:var(--sky-700)}
.sl-b:hover{background:var(--sky-100)}
.sl-xong,.nt-xong{height:32px;padding:0 14px;border-radius:8px;background:var(--sky-900);color:#fff;font:700 13px var(--f-ui)}
/* Ô ghi chú: CHỈ khi mở từ ⋯ → Ghi chú (một lối vào, b296). Đọc ghi chú thì ở dòng nghiêng dưới tên (.ghi). */
.item .ntrow{grid-column:1/-1;display:flex;align-items:center;gap:6px;margin-top:8px}
.item .ntrow svg{width:12px;height:12px;flex:0 0 auto;stroke:var(--slate-2);stroke-width:1.9}
.item .ntin{flex:1;min-width:0;height:32px;padding:0 10px;border-color:var(--or);border-radius:8px;background:#fff;font-size:13px}
.item .ntin::placeholder{color:var(--slate-2);font-style:italic}
.item .ntin:focus{box-shadow:var(--focus-ring)}
/* Dòng sơn pha: ô "? lít" + hàng mã màu (management.css .maurow) nằm ngay dưới dòng, thuộc về dòng đó. */
.item .son{grid-column:1/-1;display:flex;align-items:flex-start;gap:6px;margin-top:6px;min-width:0}
.item .son .litsel{margin-top:2px}
/* b225 · CHỌN DUNG TÍCH ngay trên dòng hàng sơn. Anh Đạt 10/09: "phần này chủ
   động thay đổi được số lít vì có sơn 15L, 17L". Dùng <select> chứ không dựng
   hộp riêng: trên điện thoại nó mở bằng bánh xe sẵn có của máy, một chạm là
   xong, và không cần thêm một lớp nổi nào nữa trong phiếu. */
.litsel{
  /* `width:auto` KHÔNG thừa: luật nền cho mọi select là width:100%, để nguyên
     thì ô dung tích chiếm trọn một dòng và đẩy hàng màu xuống — đúng cái ảnh
     chụp 10/09. Sổ lỗi #121. */
  flex:0 0 auto;width:auto;min-width:62px;height:26px;padding:0 2px 0 6px;
  border:1px solid var(--line);border-radius:6px;
  background:var(--paper);font-family:var(--f-num);font-variant-numeric:tabular-nums;
  font-size:12px;font-weight:700;color:var(--ink-2);cursor:pointer;
}
.litsel:hover{border-color:var(--sky-400);background:var(--sky-50)}
.litsel:focus{outline:2px solid var(--sky-400);outline-offset:1px}
/* Chưa chọn dung tích thì nổi màu cam: chưa có số lít là chưa tính được tiền màu. */
.litsel.chua{border-color:#F3C9A2;background:var(--or-50);color:var(--or-safe)}
.empty-tape{
  display:grid;place-content:center;text-align:center;gap:8px;color:var(--slate);
  padding:30px 10px;
}
.empty-tape svg{width:34px;height:34px;stroke-width:1.4;margin:0 auto;color:var(--sky-300)}
.empty-tape p{margin:0;font-size:12.5px;max-width:220px}

/* ═══ b304 · CHÂN PHIẾU ═══
   [Tiền mặt · CK · Ghi nợ] CÙNG HÀNG với KHÁCH TRẢ (máy tính lẫn điện thoại). Máy tính: Khách đưa + gợi ý một hàng,
   gõ rồi thì hàng đó thành "Thối lại". Thuế GTGT · Giảm giá gấp sau nút ở đầu phiếu (.tg-bang, nhãn TRÊN ô để hai cột
   vừa 320px); đã đặt thì dòng Tiền hàng · Giảm · Thuế (.tg-tong) hiện ngay trên KHÁCH TRẢ. Chân còn hai nút phụ —
   "Xóa hết" vào ⋯ đầu phiếu. */
.tape-ft .trow{color:var(--ink-2)}
.tape-ft .trow .num{color:var(--ink)}
.tape-ft input,.tape-ft select{background:var(--paper)}
.tg-tong{padding:0 0 6px;margin-bottom:6px;border-bottom:1px dashed var(--line)}
.tg-tong .trow{font-size:12.5px;padding:1px 0}
.tg-bang{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px 12px;align-items:end;margin-bottom:8px;
  padding:8px 10px 10px;border:1px solid var(--line);border-radius:10px;background:#fff}
.tg-o{display:flex;flex-direction:column;align-items:flex-start;gap:3px;min-width:0}
.tg-nhan{font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--slate)}
/* width 0 + min-width 100%: ô lấp đầy cột nhưng KHÔNG đòi bề ngang riêng — để yên thì bề ngang mặc định của ô (20 ký tự,
   16px trên điện thoại) nong cột trái ra và bóp ô Giảm giá còn 40px (đo b304 ở 390px: "44.00" bị cắt). */
.tg-bang input{width:0;min-width:100%;height:32px;padding:0 10px;text-align:right;font:700 13px var(--f-mono)}
.tg-goi .cashsug{justify-content:flex-start}
.tra-hang{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px}   /* số quá dài thì KHÁCH TRẢ xuống dòng, không cắt nút */
.tra-hang .payseg{display:flex;flex:0 1 auto;min-width:0}
.tra-hang .trow.tot{flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-end;gap:0;margin:0 0 0 auto;
  padding:0;border:0;line-height:1.05;letter-spacing:0;text-transform:none}
.tra-hang .trow.tot .num{font-size:22px}
.tot-nhan{font-size:12.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--sky-700)}
.dua-hang{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px}
.dua-o{flex:0 0 auto;display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--slate);white-space:nowrap}
.dua-o input{width:104px;height:32px;padding:0 8px;text-align:right;font:700 13px var(--f-mono)}   /* đủ "10.000.000" */
.dua-so{white-space:nowrap}
.dua-hang .cashsug{flex:1 1 0}
.dua-hang .chgline{margin-left:auto;padding:0;font-size:13px}
/* b305 · ① khách đưa thiếu: phần thiếu đi đâu — vào nợ của ai (xám), hay vì sao chưa ghi nợ được (đỏ, bấm thanh toán sẽ bị chặn) */
.dua-no{margin-top:6px;padding:5px 8px;border-radius:var(--r-sm);background:var(--sky-50);font-size:12.5px;line-height:1.4;color:var(--slate)}
.dua-no b{color:var(--ink);font-weight:700}
.dua-no.chua{background:var(--red-soft);color:var(--red)}
/* b306 · TRẢ NHIỀU CÁCH. Hàng "Chuyển khoản" đứng TRÊN hàng Tiền mặt, cùng khuôn ô với Khách đưa cho hai số thẳng cột; nút
   "Chuyển khoản phần thiếu" nằm cuối dải phần thiếu — một chạm mở hàng CK đúng số còn thiếu. */
.dua-no{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px}
.ck-thieu{margin-left:auto;height:26px;padding:0 9px;border:1px solid var(--line);border-radius:6px;background:#fff;
  font:600 12px var(--f-ui);color:var(--sky-800);white-space:nowrap;text-transform:none;letter-spacing:0}
.ck-thieu:hover{border-color:var(--sky-500)}
.ck-hang .ck-qr{min-height:32px;height:32px;padding:0 10px}
.ck-hang .ck-qr svg{width:14px;height:14px}
/* đ / % của ô Giảm giá cả phiếu — đoạn nhỏ ngay cạnh nhãn, cùng kiểu .tg-doan; chữ thường (nhãn in hoa, "đ" không thành "Đ") */
.tg-kieu{display:inline-flex;margin-left:6px;border:1px solid var(--line);border-radius:6px;overflow:hidden;vertical-align:middle}
.tg-kieu button{height:20px;padding:0 8px;font:700 12px var(--f-ui);color:var(--ink-2);text-transform:none;letter-spacing:0}
.tg-kieu button+button{border-left:1px solid var(--line)}
.tg-kieu button.on{background:var(--sky-900);color:#fff}
.tra-qr{width:100%;height:34px;margin-top:8px}
.tra-qr svg{width:15px;height:15px}
/* b319 · ③ QR chuyển khoản trong khung phiếu: mã 132px (bấm = phóng to) + số tiền + tài khoản; chờ tiền về chỉ khi tiệm đã nối SePay */
.ck-khung{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-top:8px;padding:10px;border:1.5px solid #173247;border-radius:var(--r-lg);background:var(--paper)}
.ck-khung .tra-qr{flex:0 0 auto;width:132px;height:132px;margin:0;padding:0;border:0;border-radius:var(--r-sm);background:#fff;cursor:zoom-in}
.ck-khung .tra-qr svg{width:100%;height:100%;display:block}
.ck-tt{flex:1 1 140px;min-width:0;display:flex;flex-direction:column;gap:2px}
.ck-tt small{font-size:12.5px;color:var(--slate)}
.ck-tt b{font-size:21px;font-weight:800;color:#B34700;font-family:var(--f-mono);letter-spacing:-.02em}
.ck-nh{font-size:14px;font-weight:700;color:var(--ink)}
.ck-ten{font-size:12.5px;color:var(--slate);overflow-wrap:anywhere}
.ck-tt .qr-ck{margin-top:4px}
/* Dòng tổng của mọi phiếu trong app (hóa đơn, cho thuê, đơn đặt, ca bán) — phiếu bán chỉnh riêng ở .tra-hang trên. */
.trow.tot{
  font-size:12px;font-weight:700;color:var(--sky-700);padding-top:7px;margin-top:5px;
  border-top:1px solid #D2D7DE;letter-spacing:.08em;text-transform:uppercase;
}
.trow.tot .num{font-size:21px;color:var(--or-safe);letter-spacing:-.5px;white-space:nowrap}   /* b229 · chữ "đ" không rớt xuống dòng riêng trên điện thoại */
.tape-acts{display:grid;gap:6px;margin-top:8px}
.tape-acts .btn.big{min-height:46px}
.acts-2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.acts-2 .btn{min-height:36px}
.acts-2:has(> :only-child){grid-template-columns:1fr}   /* không có máy chủ thì chỉ còn "Lưu, không in" — trọn hàng */
.kbd{
  font-family:var(--f-mono);font-size:12.5px;font-weight:700;padding:1px 5px;border-radius:4px;
  background:var(--sky-50);border:1px solid var(--line);color:var(--slate);
}
.btn.acc .kbd, .btn.pri .kbd{background:rgba(255,255,255,.22);border-color:rgba(255,255,255,.3);color:#fff}
/* Phím tắt in trên nút cam: mảng trắng mờ .22 làm nền sáng lên, chữ trắng chỉ
   còn 3,84. Đổi sang mảng TỐI mờ — nền đậm lại, chữ trắng lên 6,3
   (đo bằng tests/browser/pos-do.js). */
.tape-acts .btn.acc .kbd{background:rgba(0,0,0,.16);border-color:rgba(255,255,255,.34);color:#fff}

/* ===== SOURCE: styles/the-hang.css ===== */
/* ============================================================
   the-hang.css · THẺ HÀNG Ở QUẦY BÁN — MỌI LUẬT Ở MỘT CHỖ (b298)
   ============================================================
   Trước b298 thẻ hàng nằm rải ba tệp: gốc ở pos.css, chữ to + ảnh trong thẻ +
   khối ≥1600px ở large-ui.css, bản điện thoại ở đầu mobile.css. Muốn biết một
   thẻ trông ra sao phải đọc cả ba, và đã có một lỗi "ai đứng sau thì thắng"
   (16/09, ghi ở khối cuối tệp). Nay gom NGUYÊN VĂN về đây, giữ đúng thứ tự cũ:
     1 · gốc (từ pos.css)         2 · chữ to body.big (large-ui §3)
     3 · ảnh trong thẻ, màu độ dày data-ly (large-ui)
     4 · điện thoại ≤880px (mobile.css)
     5 · màn ≥1600px — PHẢI Ở CUỐI TỆP (cổng trong tests/kiem-giao-dien.js)
   Tệp đứng ngay sau pos.css trong styles/manifest.json. Không tệp nào khác được
   đặt luật cho .grid-p · .pcard · .stk · .plv — có cổng chặn.
   Chỉ đảo một cặp so với trước: khối 5 trước nằm TRÊN khối 4. Hai điều kiện
   (max-width:880px) và (min-width:1600px) loại trừ nhau nên thứ tự đó không
   đổi được một điểm ảnh — đã so ảnh A/B mọi cỡ màn, cả thẻ có ảnh và data-ly.
   ============================================================ */

/* ---- 1 · Gốc ---- */
.grid-p>.pcard{content-visibility:auto;contain-intrinsic-size:118px}

/* khóa cứng 3 cột — màn rộng thì thẻ TO ra chứ không đẻ thêm cột (chủ tiệm chốt) */
.grid-p{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.pcard{
  background:var(--paper);border:1.5px solid #173247;border-radius:var(--r-lg);
  padding:11px 13px;text-align:left;display:flex;flex-direction:column;gap:4px;
  min-height:104px;
  transition:border-color .08s ease-out, background-color .08s ease-out;
  position:relative;overflow:hidden;
  contain:layout style paint;              /* trình duyệt khỏi tính lại cả trang */
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;               /* bỏ 300ms chờ bấm đúp trên cảm ứng */
}
.pcard{box-shadow:0 1px 3px rgba(7,31,49,.10)}
.pcard:hover{border-color:#071F31;background:#F5FAFD;box-shadow:0 3px 10px rgba(7,31,49,.13)}
/* b293 · BỎ viền cam "khớp nhất" (.best) và trạng thái "đã trong phiếu" cố định (.incart).
   Anh Đạt 22/09: viền cam *"chả có tác dụng gì"*, ×N *"lúc chọn hiện rồi tự mất"*.
   Màu cam trên thẻ nay chỉ còn MỘT nghĩa: VỪA LẤY xong (~2 giây). */
.stk.stk-tam{background:var(--or-safe);color:#fff}          /* chữ trắng trên #A94704 = 5,6:1 */
.pcard.vua-lay .stk:not(.stk-tam){visibility:hidden}
.pcard.vua-lay{animation:vuaLay .6s ease-out}
.pcard.vua-lay .stk-tam{animation:tanDan 2s linear forwards}
@keyframes vuaLay{from{background:var(--or-50);border-color:var(--or)}}
@keyframes tanDan{0%,78%{opacity:1}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.pcard.vua-lay,.pcard.vua-lay .stk-tam{animation:none}}
.pcard:active,.pcard.tapped{border-color:var(--or);background:var(--or-50)}
.pcard .pn{
  font-weight:700;font-size:15px;line-height:1.3;color:var(--ink);padding-right:46px;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.pcard .pmeta{font-size:12.5px;color:var(--slate);font-family:var(--f-mono);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pcard.wide{min-height:126px}
.pcard .pwhole{
  font-size:12px;color:var(--sky-700);background:var(--sky-50);
  border-radius:5px;padding:3px 6px;line-height:1.35;
}
.pcard .pwhole b{font-family:var(--f-mono);font-size:12px}
.pcard .pwhole .mut{font-size:12px}
.plv{
  font-size:12px;font-weight:700;padding:1px 5px;border-radius:4px;margin-left:5px;
  background:var(--sky-100);color:var(--sky-700);vertical-align:1px;
}
.pcard .prow{display:flex;align-items:baseline;gap:6px;margin-top:auto;padding-right:51px}
.pcard .pp{font-weight:800;font-size:17px;color:var(--ink);font-family:var(--f-mono);letter-spacing:-.02em}
.pcard .pu{font-size:12px;color:var(--slate);font-weight:500}
.stk{
  position:absolute;right:9px;top:8px;font-size:12.5px;font-weight:800;padding:3px 7px;border-radius:999px;
  background:var(--green-soft);color:var(--green);font-family:var(--f-mono)
}
.stk.low{background:var(--or-50);color:var(--or-safe)}
.stk.zero{background:var(--red-soft);color:var(--red)}

/* b319 · nhãn "Giá mới dd/mm" (lịch sử giá, mốc 36): nền cam nhạt, chữ cam đậm #B34700 (5,00:1) — ô hàng, dòng phiếu, danh sách Sản phẩm */
.gia-moi{align-self:flex-start;display:inline-block;font-size:12px;font-weight:700;line-height:1.3;padding:1px 6px;border-radius:4px;
  background:var(--or-50);color:#B34700;white-space:nowrap}
body.big .gia-moi{font-size:14px}   /* b319 kiểm độc lập: chữ lớn thì nhãn cũng lớn */
/* b324 · anh Đạt 28/09: nhãn về chỗ b322 — phần tử riêng dưới dòng mã (sau .pmeta · .pwhole — pos.js · renderResults), không chen dòng giá
   (b323 để nhãn trong .prow: máy tính "đ/Bao" rớt dòng; điện thoại nhãn position:absolute ĐÈ 1/3 dưới ảnh).
   Máy tính: dòng chữ nhỏ riêng dưới mã, đủ chữ "Giá mới dd/mm". Điện thoại: cùng dòng mã (khối 4 · 4b). */
.gia-moi .gm-n{display:none}
.grid-p.anh .pcard>.gia-moi{margin:0 10px;align-self:flex-start}   /* ô ảnh lớn không có lề trong — nhãn thẳng hàng tên, dưới ảnh (ngoài ảnh) */
.grid-p{grid-auto-rows:1fr}   /* b323 · mọi ô hàng cùng hàng — và cả lưới — cao bằng nhau (ô cao nhất quyết) */

/* ---- 2 · Chữ to (body.big) ---- */
body.big .grid-p{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
body.big .pcard{min-height:132px;padding:14px 15px}
body.big .pcard .pn{font-size:17.5px;-webkit-line-clamp:3}
body.big .pcard .pmeta{font-size:14px}
body.big .pcard .pp{font-size:20px}
body.big .pcard .pu{font-size:13px}
body.big .pcard .stk{font-size:14px;padding:3px 8px}

/* ---- 3 · Ảnh trong thẻ ---- */
.pcard .pimg{
  position:absolute;right:9px;bottom:8px;top:auto;width:39px;height:39px;object-fit:contain;
  background:#fff;border:1px solid #AEBFCB;border-radius:7px;padding:2px;cursor:zoom-in;
}
.pcard.wide .pimg{width:46px;height:46px}
/* b202 · MÀU ĐỘ DÀY nằm ở VIỀN Ô ẢNH — anh Đạt 05/09: "ý t chỉ cần đổi màu phần viền
   nhỏ này thôi". Chỉ thẻ hàng sắt mới mang `data-ly`, xem lySat() trong catalog-core.js.
   Viền dày lên 2px và bớt padding 1px để ô ảnh không đổi kích thước.
   Quy ước: xám 0,8–0,9ly · xanh lá 1ly · đỏ 1,1–1,2ly · vàng 1,3–1,4ly (và 2ly). */
.pcard[data-ly] .pimg{border-color:var(--ly);border-width:2px;padding:1px}
.pcard[data-ly="08"]{--ly:#8A939F}
.pcard[data-ly="10"]{--ly:#0B8A34}
.pcard[data-ly="12"]{--ly:#D42A20}
.pcard[data-ly="14"]{--ly:#F5C400}
body.big .pcard .pimg{width:48px;height:48px;bottom:9px}
body.big .pcard .pn{padding-right:58px}
body.big .pcard .prow{padding-right:60px}

/* ---- 4 · Điện thoại ≤880px ---- */
@media (max-width:880px){
  /* thẻ hàng: xếp một cột thành dòng ngang, hết cảnh chữ bị cắt cụt */
  .grid-p,
  body.big .grid-p{grid-template-columns:1fr;gap:7px}   /* b319 · chữ lớn trước đây đè lại 3 cột ⇒ tên + giá bị cắt (đo 390px) */
  .pcard{display:grid;
    gap:2px 0;text-align:left}
  /* ══════ b242 · Ô ẢNH 24%, CHỪA SẴN CHO MỌI THẺ, TỒN Ở GÓC DƯỚI PHẢI ══════
     Anh Đạt 16/09, ba câu: *"khung ảnh nhỏ lắm"* · *"số lượng hàng tồn góc bên
     phải dưới cùng"* · *"khung ảnh vẫn là 24%, cùng tỉ lệ bản PC"*.

     Bản 15/09 để ảnh 64px CỐ ĐỊNH và chỉ thẻ CÓ ảnh mới được chừa cột — hai chỗ sai:
       · 64px nằm giữa thẻ cao 126px ⇒ thừa 62px chiều dọc, nhìn ra ô tem;
       · thẻ không ảnh chữ bắt đầu lệch 71px so với thẻ có ảnh ⇒ lưới so le,
         mà 4/5 mã trong sổ chưa có ảnh nên đó là cảnh thường gặp.

     Nay dùng ĐÚNG cách của bản máy tính: ảnh đặt tuyệt đối ở mép trái, cao bằng
     cả thẻ, rộng theo TỈ LỆ bề ngang thẻ, và thẻ chừa chỗ bằng `padding-left`
     nên mọi thẻ — có ảnh hay chưa — đều thẳng một cột. Máy tính 29%, điện thoại
     24% (anh Đạt chốt): thẻ điện thoại chỉ rộng 346px nên cùng một tỉ lệ ăn ít
     pixel hơn nhiều.

     Và đổi từ lưới NGANG (ảnh · chữ · giá) sang lưới DỌC — giá xuống hàng thứ ba.
     Đo tên hàng thật ở khổ 390px:
        cũ: ảnh 64px + cột giá 102px đứng suốt thẻ → chỗ cho tên 146px
        nay: ảnh 24% (≈83px), giá ăn một hàng ngang → chỗ cho tên ≈229px
     Ảnh to hơn mà tên còn rộng thêm hơn một nửa, thẻ vẫn cao chừng ấy.

     `object-fit:contain` chứ không `cover`: ảnh hàng chụp nền trắng, contain chỉ
     thêm lề trắng trên nền thẻ cũng trắng, mà món hàng còn nguyên đầu đuôi.
     Giữ `border-style` để thẻ hàng sắt mang data-ly vẫn tô được màu độ dày — b202. */
  /* b293 · `.pcard.best` đã bỏ hẳn (anh Đạt 22/09), nên không còn phải kể tên nó ra đây. */
  .pcard,
  .pcard.wide,
  .pcard:has(.pimg){position:relative;grid-template-columns:minmax(0,1fr) auto;
    align-items:start;padding:11px 12px;padding-left:calc(24% + 12px)}
  /* b324 · anh Đạt 28/09 · ẢNH ĐÈ CHỮ ở cỡ chữ LỚN: `body.big .pcard{padding:14px 15px}` và `body.big .pcard .pimg{48px}`
     (0,2,1 · 0,3,1 — "body.big" là thẻ + lớp) thắng hai luật điện thoại trên (0,2,0 · 0,3,0) ⇒ thẻ CÓ ảnh mất cột 24%,
     ảnh co 48px dính góc trên-trái ĐÈ tên (có từ b242, đo lại b310 · b323). Nêu tên body.big ra để thắng lại —
     cho MỌI thẻ dòng ngang, có ảnh hay chưa (luật b242: cột chừa sẵn ⇒ chữ thẳng hàng, như cỡ chữ thường).
     Lưới ô ảnh lớn / phím nhanh (khối 4b) có bố cục riêng nên không đụng. */
  body.big .grid-p:not(.anh) .pcard{padding-left:calc(24% + 12px)}   /* b328 · phím nhanh điện thoại = thẻ dòng ngang VLXD (khối 4b) */
  .pcard .pimg,
  .pcard:has(.pimg) .pimg,
  body.big .pcard:has(.pimg) .pimg{display:block;position:absolute;inset:0 auto 0 0;
    width:24%;height:100%;object-fit:contain;padding:0;background:transparent;
    border:1px solid transparent;border-width:0;
    border-radius:var(--r-sm) 0 0 var(--r-sm)}
  .pcard .pn,
  .pcard:has(.pimg) .pn{grid-column:1/-1;grid-row:1;font-size:14px;line-height:1.3;
    padding-right:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
    overflow:hidden}
  /* Mã · hãng cắt ba chấm chứ đừng vỡ dòng: mã hàng đứng đầu nên phần bị cắt là
     tên hãng, thứ đọc được từ chính tên hàng. */
  .pcard .pmeta,
  .pcard:has(.pimg) .pmeta{grid-column:1;grid-row:2;font-size:12.5px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pcard .pwhole,
  .pcard:has(.pimg) .pwhole{grid-column:1/-1;font-size:12px}
  /* b324 · anh Đạt 28/09: nhãn "Giá mới dd/mm" CÙNG DÒNG MÃ (cột phải, lưới 2 cột "chữ · tự co") — như dòng Sản phẩm b323 —
     không đè ảnh, không thêm dòng (ô cao bằng nhau), mã dài tự cắt ba chấm chứ nhãn không bị cắt. Thẻ không nhãn: cột phải rộng 0. */
  .pcard>.gia-moi{grid-column:2;grid-row:2;align-self:center;margin-left:8px;padding:0 5px}
  /* Hàng giá: giá bám trái, NHÃN TỒN đẩy hẳn sang phải — anh Đạt chốt 16/09,
     giống hệt bố cục đã chốt cho máy tính. */
  .pcard .prow,
  .pcard:has(.pimg) .prow{grid-column:1/-1;grid-row:3;display:flex;flex-direction:row;
    align-items:baseline;justify-content:space-between;gap:10px;
    white-space:nowrap;padding-right:0}
  .pcard .pp{font-size:15px}
  .pcard .stk{position:static;flex:0 0 auto;top:auto;right:auto;margin-left:auto}
  /* b293 · ×N tạm đứng ĐÚNG chỗ nhãn tồn: nhãn gốc ẩn đi nên huy hiệu tạm tự đẩy sang phải */
  .pcard.vua-lay .stk:not(.stk-tam){display:none}
}

/* ---- 4b · b308 · kiểu ô theo ngành (shared/nganh.js) — chỉ tiệm BẬT "ô ảnh lớn" / "phím nhanh" mới mang lớp này;
   VLXD (Thanh Hiền) không có .anh / .phim nên không một luật nào dưới đây chạm tới nó ---- */
.grid-p.anh{grid-template-columns:repeat(4,minmax(0,1fr))}
.grid-p.anh .pcard,
.grid-p.anh .pcard:has(.pimg){display:flex;flex-direction:column;align-items:stretch;padding:0 0 10px;min-height:0;gap:2px}   /* b310 · stretch: điện thoại (.pcard align-items:start) làm ô chữ cái chỉ rộng nửa thẻ */
.grid-p.anh .pcard .pimg,
.grid-p.anh .pcard:has(.pimg) .pimg{position:static;inset:auto;width:100%;height:auto;aspect-ratio:1;object-fit:cover;
  border:0;border-bottom:1px solid var(--line);border-radius:0;padding:0;background:var(--sky-50)}
.grid-p.anh .pcard:not(:has(.pimg))::before{content:attr(data-chu);display:flex;align-items:center;justify-content:center;aspect-ratio:3/2;background:var(--sky-100);border-bottom:1px solid var(--line);color:var(--sky-500);font-size:30px;font-weight:800;letter-spacing:.04em}   /* chưa chụp ảnh: ô nền thấp hơn, khỏi trống cả thẻ */
.grid-p.anh .pcard .pn{padding:6px 10px 0;font-size:14px;-webkit-line-clamp:2}
.grid-p.anh .pcard .prow{padding:0 10px}
.grid-p.anh .pcard .pmeta{display:none}
.grid-p.phim .pcard{min-height:88px}
@media (max-width:880px){
  .grid-p.anh{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* b328 · anh Đạt 29/09: "điện thoại màn bán cần xem được 6 ô nếu chia 2 — nhưng nếu không xem được hết chữ thì về giao diện như bán VLXD".
     Đo 29/09 (tạp hóa, hàng mẫu có ảnh): chia 2 cột thấy 6 ô ở 390px (4 ô ở 360px) nhưng 7–8/8 ô bị cắt tên ("Nước ngọt có ga lon…") ⇒ PHÍM NHANH
     trên điện thoại dùng ĐÚNG thẻ dòng ngang của VLXD (khối 4 phía trên: một cột, cột ảnh 24% cao cả thẻ, tên 2 dòng rộng hết thẻ, dòng giá · tồn).
     Bỏ hết luật riêng b308–b324 cho .grid-p.phim ở điện thoại (2 cột, ảnh chỉ cao dòng tên + mã, nhãn gọn "Mới dd/mm", dòng giá gói xuống).
     Máy tính giữ lưới phím nhanh như cũ. Ô ảnh lớn (.anh — thời trang · tiệm bánh) không đổi. Bài: tests/browser/phim-anh-do.js */
  .grid-p.phim{grid-template-columns:1fr}
  .grid-p.anh .gia-moi .gm-g{display:none}
  .grid-p.anh .gia-moi .gm-n{display:inline}
}

/* ---- 5 · Màn ≥1600px ---- */
/* ============================================================
   ẢNH HÀNG TRONG THẺ CHỌN — KHỐI NÀY PHẢI NẰM CUỐI TỆP
   ============================================================
   15/09 · anh Đạt: ảnh sang trái, phủ kín dải, mã sát tên, số lượng góc dưới
   phải. Bề rộng dải chốt 29% bề ngang thẻ, viết bằng PHẦN TRĂM để đổi màn là
   tỷ lệ vẫn đúng.

   29% đo được, không phải con số cho đẹp: 245 tên hàng THẬT của tiệm (ổ điện
   Điện Quang, gạch cắt đá, băng keo Tô Nga Dũng, Luxta, Sopoka) dựng đúng phông
   Be Vietnam Pro 700 cỡ 15px của thẻ — trung vị cần 235px một dòng, 3/4 cần
   279px. Ở thẻ 431px, dải 41% chỉ cho 45% số tên nằm gọn một dòng; hạ xuống 29%
   thì lên 77%. Qua 29% là hết lời — 26% chỉ thêm 4 điểm mà ảnh nhỏ đi thấy rõ.

   🔴 VÌ SAO KHỐI NÀY PHẢI Ở CUỐI TỆP — lỗi thật, 16/09:
   `body.big .pcard .pimg{width:48px;height:48px}` nằm giữa tệp, đặc tả BẰNG
   `.pcard:has(.pimg) .pimg` (cùng 0,3,0) nên ai đứng sau thì thắng. Khối này
   viết ở TRÊN nó, thành ra ở chế độ CHỮ TO ảnh mất `width:29%` và `height:100%`,
   chỉ còn `left:0;top:0` của `inset` → co về 48px dính góc trên-trái, ĐÈ LÊN
   tên và mã hàng. Bản thường nhìn đúng, bản chữ to hỏng — không ai thấy cho tới
   khi anh Đạt mở bằng chế độ chữ to.
   ⇒ Khối ở cuối tệp, VÀ có bản riêng cho `body.big`, không trông vào thứ tự.
   ⇒ `tests/kiem-giao-dien.js` có cổng cấm mọi dòng đặt cỡ `.pimg` nằm sau khối
      này — thêm một dòng như vậy là bài kiểm đỏ ngay.

   16/09 · object-fit ĐỔI TỪ cover SANG contain. Anh Đạt: "ảnh bị chèn mất đầu
   đuôi, không còn nguyên sản phẩm". cover lấp đầy dải nhưng xén hai rìa — cái
   van mất hai đầu ren, cây ống mất hai đầu. Ảnh hàng của tiệm chụp nền trắng,
   nên contain chỉ thêm lề TRẮNG trên nền thẻ cũng trắng: lề không lộ ra, mà món
   hàng còn nguyên. Đo kho ảnh 16/09: tệp gốc 682–1333 px (BM là 1333×1042),
   thu về khung 125–186 px — tức đang lấy ảnh TO thu nhỏ, không phóng ảnh nhỏ.

   border-width:0 chứ không bỏ hẳn border: viền này là chỗ hiện MÀU ĐỘ DÀY hàng
   sắt (b202, anh Đạt chốt 05/09). Thẻ mang data-ly vẫn tô màu được như cũ.

   Ngưỡng 1600px, không thấp hơn: ở 1440px thẻ chỉ rộng 271px, dải ảnh ăn 78px
   là tên hàng vỡ ba dòng — tệ hơn bản cũ.
   Thẻ KHÔNG có ảnh giữ nguyên hoàn toàn — 4/5 mã trong sổ chưa có ảnh. */
@media (min-width:1600px){
  /* 16/09 · Ô ẢNH CHỪA SẴN CHO MỌI THẺ, kể cả mã chưa có ảnh — anh Đạt chốt:
     "để sẵn ô, sản phẩm chưa có ảnh thì để ô trắng, sau này có ảnh chỉ thay".
     Trước đó chỉ thẻ CÓ ảnh mới lùi chữ, nên lưới so le: thẻ có ảnh chữ bắt đầu
     ở 29%, thẻ không ảnh chữ sát mép trái. 4/5 mã trong sổ chưa có ảnh nên lưới
     so le là cảnh thường gặp, không phải hiếm.
     Chừa chỗ bằng `padding-left` trên MỌI thẻ; nền thẻ vốn trắng nên chỗ chừa
     tự là ô trắng, không cần vẽ thêm gì. Thêm ảnh sau này là nó lấp đúng ô đó,
     lưới không nhảy một pixel nào.
     Bỏ luôn `:has()` ở đây — `.pimg` chỉ tồn tại khi có ảnh, nên `:has` là thừa,
     mà bỏ được thì trình duyệt cũ không hỗ trợ `:has` cũng ra đúng bố cục. */
  .pcard,
  body.big .pcard{min-height:118px;padding-left:calc(29% + 14px)}
  .pcard .pimg,
  .pcard.wide .pimg,
  body.big .pcard .pimg{
    inset:0 auto 0 0;width:29%;height:100%;
    object-fit:contain;padding:0;border-width:0;border-color:transparent;
    background:transparent;border-radius:11px 0 0 11px;
  }
  /* 16/09 · CHẾ ĐỘ CHỮ TO hạ dải ảnh 29% → 25% (anh Đạt chốt "24% là ổn, hoặc 25%").
     Lý do dùng 25% chứ không 24%: đo 245 tên hàng thật ở 1920px, cỡ chữ 17.5px
     của chế độ chữ to — 29% cho 51% tên vừa MỘT dòng, 25% cho 59%, 24% cho 60%.
     Chênh 24 với 25 đúng 1 điểm phần trăm (2 mã trong 245), mà 25% cho ảnh rộng
     hơn 5px. Chỉ hạ ở chế độ chữ to; chữ thường giữ 29% như anh Đạt chốt 15/09,
     vì ở cỡ 15px thì 29% đã cho 74% tên một dòng. Cả hai cỡ đều 100% tên vừa
     trong HAI dòng, nên không có mã nào bị cắt ba chấm.
     Hai dòng này phải đứng SAU khối 29% ở trên: cùng đặc tả 0,3,0 nên ai sau thắng. */
  body.big .pcard{padding-left:calc(25% + 14px)}
  body.big .pcard .pimg,
  body.big .pcard.wide .pimg{width:25%}
  /* Tên và mã thôi chừa chỗ bên phải — ảnh đã sang trái, nhãn tồn đã xuống đáy. */
  .pcard .pn,
  body.big .pcard .pn{padding-right:0}
  /* Nhãn tồn xuống góc dưới phải, cùng hàng với giá, trên MỌI thẻ. (b293: `.pcard.best`
     đã bỏ nên không còn phải kể tên riêng.) */
  .pcard .prow,
  body.big .pcard .prow{padding-right:76px;flex-wrap:wrap}
  .pcard .stk,
  body.big .pcard .stk{top:auto;bottom:10px;right:13px}
}

/* ===== SOURCE: styles/components.css ===== */
/* ---------- bảng ---------- */
.panel{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.panel-hd{
  padding:13px 16px;border-bottom:1px solid var(--line);display:flex;
  align-items:center;gap:12px;flex-wrap:wrap;background:var(--paper);
}
.panel-hd h2{margin:0;font-size:14px;font-weight:700;display:inline-flex;align-items:center;gap:7px}
.panel-hd h2 svg{width:17px;height:17px;stroke-width:2;flex:0 0 auto}
input[type=file]{padding:6px 8px;font-size:12.5px;cursor:pointer}
input[type=file]::file-selector-button{
  font:inherit;font-weight:600;font-size:12.5px;margin-right:9px;padding:5px 11px;cursor:pointer;
  border:1px solid var(--sky-300);border-radius:5px;background:var(--sky-50);color:var(--sky-700);
}
input[type=file]::file-selector-button:hover{background:var(--sky-100)}
details summary::marker{color:var(--sky-500)}
.panel-hd .head-sp{flex:1}
.panel-bd{padding:16px}

table{width:100%;border-collapse:collapse;font-size:13px}
thead th{
  position:sticky;top:0;background:var(--paper);z-index:1;text-align:left;
  padding:10px 12px;font-size:12.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--slate);border-bottom:1.5px solid var(--line);
  white-space:nowrap;
}
tbody td{padding:9px 12px;border-bottom:1px solid var(--line-2);vertical-align:middle}
tbody tr:hover{background:var(--sky-50)}
tbody tr:last-child td{border-bottom:0}
.tbl-wrap{overflow:auto;max-height:calc(100vh - 210px);contain:layout paint}
tbody tr{content-visibility:auto;contain-intrinsic-size:41px}
tbody tr.clk{cursor:pointer}
td.r,th.r{text-align:right}
td.c,th.c{text-align:center}
.tag{
  display:inline-block;padding:2px 7px;border-radius:4px;font-size:12.5px;font-weight:600;
  background:var(--sky-100);color:var(--sky-700);white-space:nowrap;
}
.tag.bp{background:var(--sky-100);color:var(--sky-700)}
.tag.gn{background:var(--green-soft);color:var(--green)}
.tag.rd{background:var(--red-soft);color:var(--red)}
/* b284 · --or-7 trên --or-50 chỉ 4,09:1 (chuẩn 4,5). --or-safe cho 5,31:1, cùng tông cam. */
.tag.am{background:var(--or-50);color:var(--or-safe)}
.tag.gy{background:#EEF0F3;color:var(--slate)}
.status-tag{display:inline-flex;align-items:center;gap:5px}
.status-tag svg{width:13px;height:13px;stroke-width:2.1;flex:0 0 auto}

.toolbar{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.toolbar input,.toolbar select{width:auto;min-width:150px}
.toolbar label{font-size:12px;font-weight:600;color:var(--slate)}
.toolbar-sp{flex:1}
.resource-toolbar{min-height:40px}
.resource-toolbar .resource-search{max-width:420px}
/* 🔴 Ô TÌM CÓ SÀN, KHÔNG CHỈ CÓ TRẦN. Trước đây chỉ khai `max-width:340px`; trên
   thanh công cụ đông nút (màn Sản phẩm có 7 điều khiển) `flex:1` bóp nó xuống
   **176px** — đo được — và chữ mờ nào cũng cụt. Trần lo lúc rộng, sàn lo lúc chật. */
.search-in{position:relative;flex:1 1 220px;min-width:180px;max-width:340px}
.search-in input{padding-left:32px}
.search-in svg{
  position:absolute;left:10px;top:50%;transform:translateY(-50%);
  width:15px;height:15px;color:var(--slate-2);stroke-width:2;pointer-events:none
}

/* ---------- KPI ---------- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(184px,1fr));gap:12px;margin-bottom:16px}
.kpi{
  background:var(--paper);border:1px solid var(--line);border-left:4px solid var(--line);border-radius:var(--r-lg);
  padding:13px 15px 14px;position:relative;overflow:hidden;   /* viền trái 4px đổi màu theo .kpi.gn/.rd/.am/.bp (b121, management.css) */
}
.kpi::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--sky-500)}
.kpi .k{
  font-size:12px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  color:var(--slate);margin-bottom:6px
}
.kpi .v{font-size:23px;font-weight:800;font-family:var(--f-mono);letter-spacing:-.8px;line-height:1.1}
.kpi .n{font-size:12px;color:var(--slate);margin-top:3px}
.kpi.gn::before{background:var(--green)}  .kpi.gn .v{color:var(--green)}
.kpi.rd::before{background:var(--red)}     .kpi.rd .v{color:var(--red)}
.kpi.bp::before{background:var(--sky-600)} .kpi.bp .v{color:var(--sky-700)}
.kpi.am::before{background:var(--or)}      .kpi.am .v{color:var(--or-7)}

/* ---------- hộp thoại ---------- */
.ov{
  position:fixed;inset:0;background:rgba(6,43,68,.45);display:grid;place-items:center;
  padding:20px;z-index:80;backdrop-filter:blur(2px);
}
.ov[hidden]{display:none}
.modal{
  /* b175: min-width:0 — modal là con của lưới .ov, không có nó thì một hàng
     nowrap bên trong (thanh mục Cài đặt) đẩy modal RỘNG HƠN màn điện thoại. */
  background:var(--paper);border-radius:var(--r-lg);width:100%;max-width:660px;min-width:0;
  max-height:90vh;display:flex;flex-direction:column;box-shadow:var(--shadow-lg);
}
.modal.wide{max-width:880px}
.modal.narrow{max-width:440px}
.ov.drawer-host{place-items:stretch end;padding:0;background:rgba(24,27,32,.38)}
.modal.drawer{
  width:min(680px,calc(100vw - 88px));height:100vh;max-width:680px;max-height:100vh;
  border-radius:var(--r-lg) 0 0 var(--r-lg);animation:drawerIn .18s ease-out
}
.modal.drawer.wide{max-width:760px}
.modal.drawer .m-hd{border-radius:var(--r-lg) 0 0 0;position:sticky;top:0;z-index:2}
.modal.drawer .m-ft{position:sticky;bottom:0;background:var(--paper);z-index:2}
.modal.focus{max-width:960px;max-height:94vh}
@keyframes drawerIn{from{transform:translateX(24px);opacity:.7}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.modal.drawer{animation:none}}
.m-hd{
  padding:15px 18px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;
  background:var(--paper);border-radius:var(--r-lg) var(--r-lg) 0 0;
}
.m-hd h3{margin:0;font-size:15.5px;font-weight:700;color:var(--ink);letter-spacing:-.2px}
.m-bd{padding:18px;overflow:auto;flex:1}
.m-ft{padding:13px 18px;border-top:1px solid var(--line);display:flex;gap:9px;justify-content:flex-end;flex-wrap:wrap}
/* b325 · hộp hỏi "Bỏ thay đổi?" nằm trên hộp đang sửa (#hoibo — lớp phủ thứ hai, sau #ov trong DOM) */
#hoibo{z-index:90}
.hb-chu{margin:0;font-size:15px;line-height:1.5;color:var(--ink)}
/* b325 · V9 hộp "Máy đang đăng nhập" (gói tải sau quan-ly · frontend/may-dang-nhap.js) — mỗi máy một dòng, nút Đăng xuất bên phải (điện thoại: xuống dòng, rộng hết) */
.may-ds{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:8px}
.may-dong{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r)}
.may-dong.nay{border-color:var(--sky-400);background:var(--sky-50)}
.may-tt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.may-dau{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.may-ten{font-size:14.5px;color:var(--ink)}
.may-ai{font-size:13px;font-weight:600;color:var(--ink-2)}
.may-phu{font-size:12.5px;color:var(--slate);overflow-wrap:anywhere}
.may-chu{margin:0 0 10px;font-size:14px;line-height:1.5}
@media (max-width:560px){.may-dong{flex-direction:column;align-items:stretch}}
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:13px}
.fgrid .full{grid-column:1/-1}
.f label{
  display:block;font-size:12px;font-weight:700;color:var(--slate);margin-bottom:4px;
  letter-spacing:.02em
}
.f .hint{font-size:12px;color:var(--slate-2);margin-top:3px}
.sect{
  font-size:12px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  color:var(--sky-700);margin:20px 0 11px;padding-bottom:6px;border-bottom:1px solid var(--line);
  grid-column:1/-1
}
.sect:first-child{margin-top:0}
/* Tiêu đề khối có KÈM NÚT — nút thêm dòng đứng ngay trên danh sách, không trôi
   xuống dưới theo số dòng (xem chú thích ở `rentals.js`). Nút giữ cỡ chữ thường
   của nó, không bị hút theo cỡ 10.5px in hoa của tiêu đề. */
.sect-act{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding-bottom:8px;
}
.sect-act>button{
  font-size:12px;font-weight:600;letter-spacing:0;text-transform:none;
  flex:0 0 auto;
}
.note{
  background:var(--sky-50);border:1px solid var(--line);border-left:3px solid var(--sky-500);
  border-radius:var(--r);padding:11px 13px;font-size:12.5px;color:var(--ink-2);
}
.note.am{background:var(--or-50);border-color:#F6D9BC;border-left-color:var(--or)}
.note strong{color:var(--ink)}
/* b238 · khối "lúc mất mạng thì việc gì phải đợi" trong hộp bật bán dự phòng.
   Có lớp riêng để không phải nhét style thẳng vào thẻ — cùng cỡ chữ với danh sách ngay trên nó. */
.note-ds{margin-top:12px}
.note-ds ul{font-size:13px;line-height:1.65;margin:6px 0 0;padding-left:20px}
.cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px 16px;font-size:12.5px}

/* ---------- thông báo ---------- */
.toasts{position:fixed;bottom:18px;left:50%;transform:translateX(-50%);z-index:99;display:grid;gap:8px;justify-items:center;pointer-events:none}
.toast{
  background:var(--sky-900);color:#fff;padding:10px 16px;border-radius:100px;font-size:13px;
  font-weight:600;box-shadow:var(--shadow-lg);animation:up .22s ease-out;max-width:88vw;text-align:center;
}
.toast.ok{background:var(--green)}
.toast.err{background:var(--red)}
@keyframes up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
/* b323 · máy tính: thông báo nằm GIỮA THANH TIÊU ĐỀ (chỗ trống giữa tên màn và nút) — không che ô nhóm hàng / nút ở đáy màn bán */
@media (min-width:881px){ .toasts{top:8px;bottom:auto;height:max-content}   /* height: đè "top + bottom" của .sale-follow + .toasts (bottom:96px) — không thì thông báo kéo dài thành cột */ .toast{max-width:min(460px,40vw);padding:8px 16px} }

/* Dải sau bán: phản hồi + hành động tiếp theo, không khóa màn Bán hàng. */
.sale-follow{
  position:fixed;left:calc(var(--rail) + 18px);right:18px;bottom:18px;z-index:70;
  min-height:64px;padding:10px 12px;display:flex;align-items:center;gap:10px;
  background:var(--sky-900);color:#fff;border:1px solid rgba(255,255,255,.14);
  border-radius:14px;box-shadow:var(--shadow-lg);overflow:hidden
}
.sale-follow[hidden]{display:none}
.sale-follow:not([hidden]) + .toasts{bottom:96px}
.sale-follow.on{animation:followIn .18s ease-out}
.sf-state{width:38px;height:38px;flex:0 0 38px;border-radius:11px;background:var(--green);
  display:grid;place-items:center}
.sf-state svg{width:21px;height:21px;stroke-width:2.5}
.sf-copy{display:flex;align-items:baseline;gap:7px;min-width:0;flex:1;flex-wrap:wrap}
.sf-copy strong{font-size:13.5px;white-space:nowrap}
.sf-copy span{font-size:12px;color:#C9CFD8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sf-copy .num{font-size:14px;font-weight:800;color:#fff}
.sf-actions{display:flex;align-items:center;gap:5px;flex:0 0 auto}
.sf-actions button{min-height:40px;padding:8px 11px;border-radius:9px;color:#fff;
  border:1px solid rgba(255,255,255,.18);display:inline-flex;align-items:center;gap:6px;
  font-size:12px;font-weight:700}
.sf-actions button:hover{background:rgba(255,255,255,.12)}
.sf-actions button svg{width:15px;height:15px}
.sf-actions .sf-close{width:40px;padding:0;justify-content:center;color:#C9CFD8}
.sf-life{position:absolute;left:0;bottom:0;height:3px;background:var(--or);width:100%;
  transform-origin:left;animation:followLife 15s linear forwards}
@keyframes followIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes followLife{to{transform:scaleX(0)}}
@media (prefers-reduced-motion:reduce){.sale-follow.on,.sf-life{animation:none}}

/* ---------- mã vạch / tem ---------- */
.bc svg{display:block;max-width:100%;height:auto}
.labels{display:grid;grid-template-columns:repeat(3,1fr);gap:5px}
.label{
  border:1px dashed var(--line);padding:7px;text-align:center;
  display:flex;flex-direction:column;gap:3px;align-items:center;break-inside:avoid;
}
.label .lc{font-size:12px;font-weight:700;font-family:var(--f-mono);align-self:flex-start}
.label .lp{font-size:12px;font-weight:800;font-family:var(--f-mono)}
.label .ln2{font-size:12px;line-height:1.2}
.label .bcn{font-size:12px;font-family:var(--f-mono);letter-spacing:.06em}

.empty{
  text-align:center;padding:48px 20px;color:var(--slate);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
}
.empty svg{width:38px;height:38px;stroke-width:1.4;color:var(--sky-300);margin-bottom:10px}
/* b296 · soát 24/09 mục 17: luật trên trúng cả biểu tượng TRONG NÚT (cùng độ ưu tiên với `.btn svg`, đứng sau
   nên thắng) ⇒ dấu + 38px, nút "Nhận hàng bảo hành"/"Thêm màu cho khách" cao 68px, to hơn cả nút chính đầu màn. */
.empty .btn svg{width:16px;height:16px;stroke-width:2;color:currentColor;margin:0}
/* b296 · dải cuộn ngang: mép còn nội dung thì mờ dần (lớp do cuonNgangGan() trong common.js gắn) — mục 18 */
.con-phai{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent)}
.con-trai{-webkit-mask-image:linear-gradient(90deg,transparent,#000 32px);mask-image:linear-gradient(90deg,transparent,#000 32px)}
.con-trai.con-phai{-webkit-mask-image:linear-gradient(90deg,transparent,#000 32px,#000 calc(100% - 32px),transparent);
  mask-image:linear-gradient(90deg,transparent,#000 32px,#000 calc(100% - 32px),transparent)}
.empty h3{margin:0 0 5px;font-size:15px;color:var(--ink);font-weight:700}
.empty p{margin:0 auto 14px;font-size:13px;max-width:420px;line-height:1.55}
.empty-actions{display:flex;align-items:center;justify-content:center;gap:var(--space-3);flex-wrap:wrap}
.text-action{min-height:40px;padding:8px 6px;color:var(--sky-700);font-size:12.5px;font-weight:700;
  text-decoration:underline;text-decoration-color:var(--sky-300);text-underline-offset:3px;border-radius:var(--r-sm)}
.text-action:hover{color:var(--ink);text-decoration-color:var(--or)}
.empty-note{margin-top:4px;padding:9px 12px;border-radius:var(--r);background:var(--sky-50);
  color:var(--slate);font-size:12px;font-weight:600}
.onboard-empty{min-height:360px;padding:36px 24px}
.onboard-empty>svg{width:44px;height:44px}
.empty-steps{display:flex;align-items:center;justify-content:center;gap:10px;margin:2px 0 20px;
  width:min(620px,100%)}
.empty-steps>span{flex:1;min-width:0;display:flex;align-items:center;gap:8px;padding:9px 11px;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r)}
.empty-steps b{width:24px;height:24px;flex:0 0 24px;border-radius:50%;display:grid;place-items:center;
  background:var(--sky-900);color:#fff;font:700 12px var(--f-mono)}
.empty-steps em{font-style:normal;color:var(--ink);font-size:12px;font-weight:650;white-space:nowrap}
.empty-steps>i{font-style:normal;color:var(--sky-400);font-size:22px;font-weight:300}

.cam-box{position:relative;background:#000;border-radius:var(--r);overflow:hidden;aspect-ratio:4/3}
.cam-box video{width:100%;height:100%;object-fit:cover;display:block}
.cam-line{
  position:absolute;left:8%;right:8%;top:50%;height:2px;background:var(--or);
  box-shadow:0 0 12px var(--or);animation:sweep 2s ease-in-out infinite;
}
@keyframes sweep{0%,100%{top:26%}50%{top:74%}}
@media (prefers-reduced-motion:reduce){.cam-line{animation:none}}
/* b229 · B5 · dải đỏ BẢN THỬ (máy chủ THU.cmd chạy trên sổ CHÉP từ sổ thật) — viền đỏ quanh màn + nhãn giữa đỉnh.
   pointer-events:none: không chặn bấm; không in ra giấy. */
.ban-thu{position:fixed;top:0;z-index:2147483000;background:#b71c1c;color:#fff;
  font-weight:700;font-size:12px;line-height:1.5;padding:3px 12px;pointer-events:none;
  box-shadow:0 2px 6px rgba(0,0,0,.35);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
html.co-ban-thu::after{content:"";position:fixed;inset:0;border:4px solid #b71c1c;pointer-events:none;z-index:2147483000}
/* b278 · anh Đạt 21/09 chụp 7 ảnh: dải này ĐÈ lên tiêu đề màn ("Bán hàng", "Báo cáo") và
   huy hiệu Online·b277. Nó `position:fixed` nên không chiếm chỗ. Nay thân app lùi xuống
   đúng chiều cao dải (12px × 1.5 + 3px × 2 = 24px). Chỉ bản thử mới có dải nên máy tiệm
   thật không đổi một pixel. Trên điện thoại cộng thêm lề an toàn (mobile-runtime.css). */
html.co-ban-thu .app{padding-top:24px}
.ban-thu{left:0;right:0;transform:none;max-width:none;border-radius:0;text-align:center}
@media print{.ban-thu{display:none}html.co-ban-thu::after{display:none}}
/* b325 · C6 · dải dùng thử (chỉ tiệm thử VPS — reliability-ui.js · daiThu): cùng chỗ + cùng cách chừa chỗ với dải BẢN THỬ (hai dải không bao giờ cùng có) */
.dai-thu{position:fixed;top:0;left:0;right:0;z-index:2147483000;background:var(--ink,#1B1E24);color:#fff;font-weight:700;font-size:13px;line-height:18px;
  padding:3px 12px;text-align:center;pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dai-thu.sap{background:var(--or-ink,#B34700)}.dai-thu.khoa{background:#b71c1c}
html.co-dai-thu .app{padding-top:24px}
@media print{.dai-thu{display:none}}

/* b229 · B8: chốt ngày nói Thừa/Thiếu/Khớp có màu; chừa khoảng giữa hai dòng số máy chủ và ô nhập */
#rc_diff.lech { color: var(--red); font-weight: 700; }
#rc_diff.khop { color: var(--green); font-weight: 700; }
.fgrid:has(#rc_open) { margin-top: 12px; }

/* b229 · B8 (soi ảnh điện thoại): bảng Quản lý tài khoản rộng hơn màn 390px — nút "Cấp mật khẩu tạm" bị giấu bên phải,
   phải vuốt ngang mới thấy. Lên b229 chủ PHẢI cấp mật khẩu tạm cho từng người (000000 bị khóa), có khi làm từ điện thoại
   ⇒ màn hẹp xếp mỗi tài khoản thành một thẻ: tên + nhóm + trạng thái bên trái, hai nút bên phải. */
@media (max-width: 560px) {
  .auth-table thead { display: none; }
  .auth-table tr { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; padding: 10px 0; border-bottom: 1px solid var(--line); }
  .auth-table td { display: block; padding: 0; border: 0; }
  .auth-table td.au-phu { grid-column: 1; font-size: 13px; color: var(--slate); }
  .auth-table td.r { grid-column: 2; grid-row: 1 / span 3; align-self: center; display: flex; flex-direction: column; gap: 6px; }
}

/* ===== SOURCE: styles/print.css ===== */
/* ---------- in ấn ---------- */
#print{display:none}
#print.measure{display:block;position:absolute;left:-10000px;top:0;background:#fff}
/* .p-80 đặt NGOÀI @media print để app đo được chiều dài phiếu trước khi in
   (in vẫn đúng vì trên màn hình #print luôn ẩn) */
/* hóa đơn khổ 80mm (máy in nhiệt) — bố cục kiểu UNIQLO, chốt b114 */
.p-80{width:72mm;box-sizing:border-box;padding:2.5mm 4mm 3mm;font-size:9pt;line-height:1.4;color:#000}
.p-80 tr,.p-80 .nm,.p-80 .chuyen,.p-80 .ft{break-inside:avoid;page-break-inside:avoid}
.p-80 .c{text-align:center}
.p-80 .b{font-weight:700}
.p-80 .lk{display:flex;align-items:center;justify-content:center;gap:2.5mm}
.p-80 .lk-m{width:15mm;height:10mm}
.p-80 .lk-t{text-align:left}
.p-80 .lk-tag{font-size:6.3pt;font-weight:700;letter-spacing:1.6pt;white-space:nowrap}
.p-80 .lk-w{width:33mm;height:6.6mm;display:block}
.p-80 .lk-ad{font-size:8.5pt;line-height:1.45;margin-top:1.2mm;text-align:center}
.p-80 h1{font-size:12pt;margin:2.2mm 0 .5mm;text-align:center;letter-spacing:2pt;font-weight:800}
.p-80 .mt{font-size:8.5pt;margin-bottom:.8mm}
.p-80 hr{border:0;border-top:1px dashed #000;margin:1.8mm 0}
.p-80 table{width:100%;border-collapse:collapse;font-size:9pt}
.p-80 td{padding:.4mm 0;vertical-align:top}
.p-80 .r{text-align:right;white-space:nowrap}
.p-80 .nm{font-weight:600}
.p-80 .sb{font-size:8.5pt}
.p-80 .inote{font-size:8pt;font-style:italic;padding-left:2.5mm;line-height:1.25}
.p-80 .ct{text-align:center}
.p-80 .sum td{padding:.5mm 0}
.p-80 .tot td{font-weight:800;font-size:12pt;padding-top:1.2mm;border-top:1px solid #000}
.p-80 .words{font-size:8pt;font-style:italic;margin-top:.8mm}
.p-80 .chuyen{font-size:8pt;text-align:center;line-height:1.5}
.p-80 .chuyen b{font-weight:800}
.p-80 .ft{text-align:center;font-size:8.5pt;line-height:1.5}
/* VietQR trên bill nhiệt: 30mm cho dễ quét (b132, anh Đạt góp ý — mốc tối
   thiểu của sổ tay là 20mm), viền trắng 4 mô-đun nằm sẵn trong SVG.
   Chữ chỉ một dòng ngắn, SỐ TIỀN tách riêng in to — không để chữ rớt dòng. */
.p-80 .vqr{text-align:center;margin:1.5mm 0 .5mm}
.p-80 .vqr svg{width:30mm;height:30mm}
.p-80 .vqr .t{font-size:8pt;line-height:1.4}
.p-80 .vqr .vamt{font-size:12pt;font-weight:800;margin:.2mm 0 .4mm}
/* Tài khoản dưới mã QR (sửa b147): ngân hàng + số tài khoản một dòng, TÊN CHỦ
   một dòng riêng. Trước đây ba thứ nối bằng dấu chấm giữa nên tên công ty dài
   bị bẻ ngang, nhìn như lỗi in. Tên chừa lề hai bên 3mm để nếu có xuống dòng
   thì cũng gãy ở giữa từ chứ không sát mép giấy. */
.p-80 .vqr .vbank{font-size:8.5pt;font-weight:700;line-height:1.35;margin-top:.3mm}
.p-80 .vqr .vstk{letter-spacing:.35pt}
.p-80 .vqr .vown{font-size:7.5pt;line-height:1.3;letter-spacing:.1pt;padding:0 3mm}
/* b144: mã đánh giá Google trên bill nhiệt (b299 · dời từ workflows.css về đây) */
.p-80 .rvq{text-align:center;margin:1.5mm 0 .5mm;break-inside:avoid;page-break-inside:avoid}
.p-80 .rvq svg{width:24mm;height:24mm}
.p-80 .rvq .t{font-size:8pt;line-height:1.4}
/* Mã vạch số HĐ ở chân bill: cao ~7mm, vạch mảnh ~0.4mm, hai bên trống rộng */
.p-80 .bchd{text-align:center;margin-top:1.6mm}
.p-80 .bchd svg{width:40mm;height:auto}


@media print{
  body{overflow:visible;background:#fff}
  .app,.toasts,.ov{display:none !important}
  #print{display:block !important}

  /* hóa đơn A4/A5 */
  .p-inv{max-width:100%;font-size:11pt;color:#000}
  .p-inv .p-shop{text-align:center;margin-bottom:4mm;font-size:9.5pt;line-height:1.4}
  .p-inv h1{font-size:16pt;margin:0 0 1mm;text-align:center;letter-spacing:.5pt}
  .p-inv .p-sub{text-align:center;font-size:9pt;margin-bottom:5mm}
  .p-inv table{width:100%;border-collapse:collapse;font-size:10pt}
  .p-inv th,.p-inv td{border:1px solid #000;padding:1.6mm 2mm}
  .p-inv th{background:#eee;font-size:9pt;text-transform:uppercase}
  /* Trên màn hình dòng cuối bảng bỏ viền dưới cho thoáng (tbody tr:last-child td),
     nhưng khi IN thì bảng bị hở đáy — trả lại viền cho phiếu in (b123). */
  .p-inv tbody tr:last-child td,.p-list tbody tr:last-child td{border-bottom:1px solid #000}
  .p-inv .p-meta td{border:0;padding:0 0 1mm}
  /* Cột phải của phần thông tin đầu phiếu: trước canh phải nên chữ dí sát mép
     giấy. Nay là một cột rộng cố định, canh trái (b126). */
  .p-inv .p-meta td.rt{width:46%;text-align:left;padding-left:8mm}
  /* Phiếu giao hàng: nhãn thành cột riêng, giá trị có gạch chân để điền tay.
     Trước đây ĐT/Số xe canh phải nên bị dí sát rìa giấy (b123). */
  .p-inv .p-dl{table-layout:fixed}
  .p-inv .p-dl td{padding:0 0 2mm;vertical-align:bottom}
  .p-inv .p-dl .lb{width:26mm;font-weight:700;white-space:nowrap}
  .p-inv .p-dl .lb2{width:18mm;font-weight:700;white-space:nowrap;padding-left:6mm}
  .p-inv .p-dl .vl,.p-inv .p-dl .vl2{border-bottom:1px dotted #999;padding:0 4mm 1mm 2mm}
  .p-inv .p-dl .vl2{width:40mm;padding-right:1mm}
  /* Khối tiền thu hộ khi giao (COD) — b131 thêm ô VietQR bên phải */
  .p-inv .p-cod{border:1.6pt solid #000;padding:2.5mm 3mm;margin-top:4mm;text-align:center;
    display:flex;align-items:center;justify-content:center;gap:5mm}
  .p-inv .p-cod .cod-main{flex:1;min-width:0}
  .p-inv .p-cod .cod-qr{flex:0 0 auto;font-size:7.5pt;line-height:1.35;text-align:center}
  .p-inv .p-cod .cod-qr svg{width:22mm;height:22mm;display:block;margin:0 auto .5mm}
  .p-inv .p-cod .cod-hd{font-size:9.5pt;font-weight:700;letter-spacing:.6pt}
  .p-inv .p-cod .cod-amt{font-size:19pt;font-weight:800;line-height:1.15;margin:.6mm 0}
  .p-inv .p-cod .cod-w{font-size:9pt;font-style:italic}
  .p-inv .p-cod .cod-note{font-size:9pt;margin-top:1.4mm}
  .p-inv .p-cod .cod-tick{margin-left:3mm;white-space:nowrap}
  .p-inv .p-cod.none{border:1pt dashed #666;font-size:9.5pt;font-weight:700;padding:2mm 3mm}
  .p-inv .p-sum{width:74mm;margin-left:auto;margin-top:3mm}
  .p-inv .p-sum td{border:0;padding:.8mm 0;font-size:10pt}
  .p-inv .p-sum td+td{text-align:right}   /* b305 · cột số canh phải bằng lớp — dòng Đã trả · Còn nợ không thêm style= */
  .p-inv .p-sum tr.g td{border-top:1px solid #000;font-weight:700;font-size:11.5pt;padding-top:1.4mm}
  .p-inv .p-words{margin-top:3mm;font-size:9.5pt;font-style:italic}
  .p-sign{display:flex;justify-content:space-around;margin-top:14mm;font-size:10pt;text-align:center}
  .p-ft{margin-top:8mm;text-align:center;font-size:9pt;font-style:italic}

  /* bảng giá / báo cáo */
  .p-list table{width:100%;border-collapse:collapse;font-size:9.5pt}
  .p-list th,.p-list td{border:1px solid #999;padding:1.4mm 2mm}
  .p-list th{background:#eee}
  .p-list tr,.p-list .label{page-break-inside:avoid}
  .labels{display:grid;grid-template-columns:repeat(3,1fr);gap:2mm}
  .label{border:1px dashed #999;padding:2mm}
  .p-h{font-size:14pt;font-weight:800;margin:0 0 4mm}
  @page{size:A4;margin:11mm}
}
@media print{
  body.k80 .p-inv{display:none}
  body:not(.k80) .p-80{display:none}
}

/* ===== SOURCE: styles/responsive-core.css ===== */
/* ---------- màn nhỏ ---------- */
@media (max-width:1240px){ .pos3{grid-template-columns:minmax(0,1fr) 400px} }
@media (max-width:1024px){ .pos3{grid-template-columns:minmax(0,1fr) 360px} }
@media (max-width:880px){
  .app{grid-template-columns:1fr}
  .brand,.rail-sp,.rail-ft,.rail-line{display:none}
  .navbtn svg{width:19px;height:19px}
  /* đệm ĐÁY của .view · .pos3 (chừa thanh dưới + vùng an toàn) ở mobile-runtime.css */
  .view{padding-top:12px;padding-right:12px;padding-left:12px}
  .pos3{grid-template-columns:1fr;padding-top:10px;padding-right:10px;padding-left:10px;height:auto}
  .pane{overflow:visible}
  .results{overflow:visible}
  .fgrid{grid-template-columns:1fr}
  .head{padding:0 12px;gap:9px;min-width:0}   /* min-width:0: huy hiệu + nút tài khoản không bị bóp — lý do ở mobile-runtime.css, .head-may */
  .head .sub{display:none}
  .tbl-wrap{max-height:none}
  .m-ft .btn{flex:1}
  /* b296 · luật hộp kiểu ngăn kéo trên điện thoại chuyển sang cham-dien-thoai.css */
  .resource-toolbar .resource-search{max-width:none;flex:1 0 100%}
  .resource-toolbar .toolbar-sp{display:none}
  .sale-follow{left:8px;right:8px;padding:9px;gap:8px;min-height:60px}
  .sf-state{width:34px;height:34px;flex-basis:34px}
  .sf-copy{display:block}
  .sf-copy strong,.sf-copy span{display:block;max-width:100%}
  .sf-copy span:not(.num){display:none}
  .sf-actions button{width:40px;padding:0;justify-content:center}
  .sf-actions button span{display:none}
  .sf-actions .sf-close{display:none}
}

@media (max-width:560px){
  .onboard-empty{min-height:0;padding:28px 14px}
  .empty-steps{gap:6px;margin-bottom:17px}
  .empty-steps>span{display:block;padding:8px 5px;text-align:center}
  .empty-steps b{margin:0 auto 4px}
  .empty-steps em{font-size:12px;white-space:normal}
  .empty-steps>i{font-size:17px}
  .empty-actions{flex-direction:column;width:100%}
  .empty-actions .btn{width:100%;max-width:320px}
}

/* ---------- bán hàng bằng giọng nói ---------- */
.scan-mic{
  width:40px;height:40px;border-radius:var(--r);background:var(--or-safe);border-color:var(--or-safe);
  display:grid;place-items:center;color:#fff;flex:0 0 auto;transition:background .12s,color .12s;
}
.scan-mic:hover{background:var(--or-safe-hover);border-color:var(--or-safe-hover)}
.scan-mic svg{width:19px;height:19px;stroke-width:1.8}
.scan-mic.on{background:var(--or-safe);border-color:var(--or-safe);color:#fff;box-shadow:0 0 0 0 rgba(249,115,22,.6);animation:mic 1.6s ease-out infinite}
@keyframes mic{0%{box-shadow:0 0 0 0 rgba(249,115,22,.55)}70%{box-shadow:0 0 0 12px rgba(249,115,22,0)}100%{box-shadow:0 0 0 0 rgba(249,115,22,0)}}
@media (prefers-reduced-motion:reduce){.scan-mic.on{animation:none}}

.vpanel{
  background:var(--paper);border:1px solid var(--line);border-left:4px solid var(--or);
  border-radius:var(--r-lg);padding:11px 13px;box-shadow:var(--shadow);
}
.vhead{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--sky-800)}
.vdot{width:9px;height:9px;border-radius:50%;background:var(--or);animation:pulse 1.4s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){.vdot{animation:none}}
.vtts{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;color:var(--slate);white-space:nowrap}
.vtts input{width:auto;margin:0}
.vheard{
  margin-top:8px;font-size:16px;font-weight:600;color:var(--ink);min-height:24px;line-height:1.35;
}
.vmsg{
  margin-top:8px;padding:8px 11px;border-radius:var(--r);font-size:13px;
  background:var(--sky-50);color:var(--ink-2);border:1px solid var(--line);
}
.vmsg.ok{background:var(--green-soft);border-color:#BFE3D5;color:#0B5F44}
.vmsg.err{background:var(--red-soft);border-color:#EDD3D0;color:var(--red)}
.vmsg.ask{background:var(--or-50);border-color:#F6D9BC;color:var(--or-7)}
.vchoices{display:grid;gap:6px;margin-top:8px}
.vch{
  display:flex;align-items:center;gap:9px;text-align:left;width:100%;
  border:1px solid var(--line);border-radius:var(--r);padding:8px 11px;background:var(--paper);
  font-size:13px;transition:border-color .12s,background .12s;
}
.vch:hover{border-color:var(--or);background:var(--or-50)}
.vch b{
  width:22px;height:22px;border-radius:5px;background:var(--sky-600);color:#fff;
  display:grid;place-items:center;font-size:12px;flex:0 0 auto;
}
.vch span.vch-ten{flex:1;font-weight:600}
.vcmds{margin-top:9px;font-size:12px;color:var(--slate-2);line-height:1.5}

/* ---------- cho thuê: dòng thiết bị → styles/phieu-thue.css (b295) ---------- */

/* b223 · khối .pin (ô ĐƠN GIÁ trong hàng dưới) đã BỎ: anh Đạt 10/09 thấy hai
   con số giá trùng nhau trên cùng một dòng. Nay chỉ còn một số — thành tiền —
   và nút ⋯ cạnh nó (.tt / .ttin / .dmenu ở pos.css; b296 thay cây bút).
   b299 · luật CSS của .pin còn sót sau b223 đã xóa hết (không phần tử nào mang lớp đó). */

/* bộ lọc bảng giá */
.chips{display:flex;gap:7px;flex-wrap:wrap}
.chip{
  display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:100px;
  background:var(--sky-100);color:var(--sky-700);font-size:12px;font-weight:600;
  border:1px solid var(--sky-300);
}
.chip i{font-style:normal;font-size:12px;opacity:.7}
.chip:hover{background:var(--sky-300);color:var(--sky-900)}
.pickbar{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 11px;margin-bottom:12px;
  background:var(--or-50);border:1px solid #F6D9BC;border-radius:var(--r);
}
@media print{ .pickbar{display:none} .p-list input[type=checkbox]{display:none} }

/* ===== SOURCE: styles/filters.css ===== */
/* hàng thẻ chọn nhiều mục */
.chiprow:empty{display:none}
.chiprow{margin-top:10px}

.chiprow-lb{
  font-size:12px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:var(--slate);flex:0 0 auto;margin-right:2px;
}
.chiprow-hint{font-size:12px;color:var(--slate-2)}
.chip2{
  display:inline-flex;align-items:center;gap:5px;padding:4px 11px;border-radius:999px;
  border:1px solid var(--line);background:var(--paper);color:var(--ink-2);
  font-size:12.5px;font-weight:600;white-space:nowrap;
}
.chip2 i{
  font-style:normal;font-size:12px;font-weight:700;font-family:var(--f-mono);
  color:var(--slate-2);background:var(--bg);padding:0 5px;border-radius:999px;
}
.chip2:hover{border-color:var(--sky-400);background:var(--sky-50)}
.chip2.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
.chip2.on i{background:rgba(255,255,255,.22);color:#fff}
.chip2.clr{border-style:dashed;color:var(--slate);font-weight:500}
.chip2.lv2{font-size:12px;font-weight:500;color:var(--slate);border-style:dashed}
.chip2.lv2.on{color:#fff;border-style:solid}
.chip2.more{border-style:dashed;color:var(--sky-700);border-color:var(--sky-300);background:var(--sky-50);font-weight:600}
.chip2.more:hover{background:var(--sky-100)}
.chiprow-in{display:flex;align-items:center;gap:6px;flex-wrap:wrap;row-gap:6px}

/* ===== SOURCE: styles/commerce.css ===== */
/* ============ b175 · ngăn Bộ lọc + Cài đặt chia mục + kho tài khoản ============ */

.fpanel{
  background:var(--bg);border:1px solid var(--line);border-radius:var(--r);
  padding:4px 12px 12px;margin-top:10px;
}
.fpanel .chiprow{margin-top:8px}
.btn.fbtn .fn{
  font-family:var(--f-mono);font-size:12px;font-weight:700;background:var(--sky-900);
  color:#fff;border-radius:999px;padding:0 6px;margin-left:2px;
}
.btn.fbtn .caret{margin-left:4px;font-size:12px;color:var(--slate)}
.btn.fbtn.on{border-color:var(--sky-400);background:var(--sky-50)}

.set-nav{
  display:flex;gap:6px;flex-wrap:wrap;margin-bottom:16px;
  border-bottom:1px solid var(--line);padding-bottom:12px;
}
.set-nav button{
  border:1px solid var(--line);background:var(--paper);color:var(--ink-2);
  border-radius:999px;padding:6px 14px;font-size:12.5px;font-weight:600;cursor:pointer;
}
.set-nav button:hover{background:var(--sky-50);border-color:var(--sky-300)}
.set-nav button.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}

.bk-list{display:flex;flex-direction:column;gap:8px}
.bk-row{
  display:flex;align-items:center;gap:10px;justify-content:space-between;
  border:1px solid var(--line);border-radius:var(--r);padding:9px 12px;background:var(--paper);
}
.bk-info{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;min-width:0}
.bk-info .num{font-family:var(--f-mono);font-weight:700}
.bk-ten{font-size:12.5px;color:var(--slate)}
.bk-act{display:flex;gap:6px;flex:0 0 auto}
.bk-edit{
  border:1px solid var(--sky-300);border-radius:var(--r);padding:12px;background:var(--sky-50);
  display:grid;grid-template-columns:1fr 1fr;gap:10px;
}
.bk-edit .f{margin:0}
.bk-edit-bar{grid-column:1/-1;display:flex;justify-content:flex-end}
@media (max-width:880px){
  .bk-edit{grid-template-columns:1fr}
  .bk-row{flex-wrap:wrap}
  .set-nav{overflow-x:auto;flex-wrap:nowrap;padding-bottom:10px}
  .set-nav button{white-space:nowrap}
}

.lrn{
  font-size:12px;font-weight:700;padding:1px 5px;border-radius:4px;
  background:var(--green-soft);color:var(--green);white-space:nowrap;
}
.navbtn.lockbtn{margin-top:6px;border-top:1px solid rgba(255,255,255,.14);padding-top:12px}
.navbtn.lockbtn.on{background:var(--or-safe);border-color:var(--or-safe);color:#fff}
.navbtn.lockbtn.on::before{display:none}
.navbtn.lockbtn.on:hover{background:var(--or-safe-hover);border-color:var(--or-safe-hover)}

/* ============ nhiều hóa đơn cùng lúc ============ */

.tabs::-webkit-scrollbar{height:0}

.tab:hover{background:var(--sky-50);color:var(--ink)}
.tab.on{
  background:var(--sky-900);color:#fff;border-color:var(--sky-900);
}
.tab.on i{opacity:.6;color:#fff}
.tab.on i:hover{background:rgba(255,255,255,.18);color:#fff}

.tab i{font-style:normal;font-size:13px;opacity:.4;padding:2px 4px;border-radius:4px;margin:-2px -4px -2px 0}
.tab i:hover{opacity:1;color:var(--red);background:var(--red-soft)}
.tab.add{
  background:var(--sky-50);border:1.5px dashed var(--sky-300);color:var(--sky-700);
  font-size:13.5px;font-weight:700;padding:9px 14px 9px 11px;gap:6px;
}
.tab.add b{
  font-size:17px;font-weight:700;line-height:1;width:22px;height:22px;border-radius:6px;
  background:var(--sky-600);color:#fff;display:grid;place-items:center;
}
.tab.add:hover{background:var(--sky-100);border-color:var(--sky-500);border-style:solid}
.tab.add:hover b{background:var(--or)}

/* ============ tiền khách đưa · tiền thối ============ */

/* ============ kiểm kho bằng máy quét ============ */
.ck-scan{border-radius:var(--r-lg)}
.ck-step{display:flex;gap:3px;flex:0 0 auto}
.ck-step button{
  padding:6px 9px;border-radius:var(--r-sm);font-size:12px;font-weight:700;
  background:rgba(255,255,255,.12);color:#C9CFD8;
}
.ck-step button:hover{background:rgba(255,255,255,.2);color:#fff}
.ck-step button.on{background:var(--or-safe);border-color:var(--or-safe);color:#fff}
.ck-last:empty{display:none}
.ck-last{margin-bottom:11px}
.ck-last-in{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.ck-lb{
  font-size:12px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--slate);
}
.ck-chip{
  display:inline-flex;align-items:baseline;gap:5px;padding:4px 9px;border-radius:100px;
  background:var(--sky-50);border:1px solid var(--line);font-size:12px;color:var(--ink-2);
}
.ck-chip.new{background:var(--green-soft);border-color:#BFE3D5;color:#0B5F44}
.ck-chip b{font-family:var(--f-mono);font-size:12.5px}
.ck-chip em{font-style:normal;font-size:12px;color:var(--slate-2);font-family:var(--f-mono)}

/* thanh tab xuống dòng thay vì cuộn ngang */
.tabs{display:flex;gap:5px;overflow-x:auto;padding-bottom:0;flex-wrap:wrap;overflow:visible;row-gap:5px}
.tab{display:inline-flex;align-items:center;gap:8px;flex:0 0 auto;padding:10px 14px;border-radius:var(--r);min-height:40px;background:var(--paper);border:1px solid var(--line);color:var(--ink-2);font-size:14px;font-weight:600;white-space:nowrap;transition:background .12s,color .12s,border-color .12s;max-width:180px}
.tab .tl{overflow:hidden;text-overflow:ellipsis}

/* khối kết quả tìm nằm ngay trên hàng bán chạy */

.res-x{
  width:27px;height:27px;border-radius:7px;display:grid;place-items:center;
  background:var(--red);color:#fff;font-size:14px;font-weight:800;box-shadow:0 1px 3px rgba(180,35,35,.24);
}
.res-x:hover{background:#9F1D1D;color:#fff}
/* Tiêu đề khu hàng là MỘT Ô SÁNG bên trái, không phải dải xám vắt ngang cả
   hàng (anh Đạt chốt 03/09). Đệm đều trên dưới nên chữ nằm giữa ô, không bị
   đẩy lên. Số lượng nằm trong huy hiệu cam đặc để đọc được từ xa. */
.res-head{display:flex;align-items:center;gap:8px;margin-bottom:9px;padding:0 0 8px;position:sticky;top:0;background:#EEF3F7;z-index:2}
.res-title{display:inline-flex;align-items:center;gap:7px;min-width:0;padding:7px 12px;border-radius:999px;
  background:var(--paper);border:1.5px solid var(--or);box-shadow:0 1px 4px rgba(249,115,22,.16);
  color:var(--or-safe);font-size:12.5px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;line-height:1;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.res-count{display:inline-grid;place-items:center;min-width:21px;height:21px;padding:0 6px;border-radius:999px;
  background:var(--or);color:var(--ink);font-size:12.5px;font-weight:800;letter-spacing:0}
.res-actions{margin-left:auto;display:flex;align-items:center;justify-content:flex-end;min-width:27px}
.res-head svg{width:14px;height:14px;flex:none;stroke-width:2.2;color:var(--or)}
/* b319 · ô "Danh mục" cạnh Hàng bán chạy + danh sách nhóm hàng (kèm số mã). Nút viền than, đang mở / đang lọc thì tô than chữ trắng. */
.res-dm{display:inline-flex;align-items:center;gap:6px;min-height:34px;padding:0 12px;border-radius:999px;background:var(--paper);
  border:1.5px solid #173247;color:#173247;font-size:13px;font-weight:700;white-space:nowrap;flex:0 0 auto}
.res-dm:hover{background:#F5FAFD}
.res-dm.on{background:#173247;color:#fff}
.res-head .res-dm svg{color:currentColor}
.dm-ds{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:8px}
.dm-nhom{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:52px;padding:8px 14px;text-align:left;
  background:var(--paper);border:1.5px solid var(--line);border-radius:var(--r-lg);color:var(--ink)}
.dm-nhom:hover{border-color:#173247;background:#F5FAFD}
.dm-nhom.on{border-color:var(--or);background:var(--or-50)}
.dm-nhom b{font-size:15px;font-weight:700;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dm-nhom span{flex:0 0 auto;font-size:12.5px;color:var(--slate);font-family:var(--f-mono)}
@media (max-width:360px){.res-dm{min-width:44px;padding:0 12px}.res-dm-t{display:none}}   /* 320px: chữ đè số đếm bên cạnh (kiểm độc lập b319) — còn biểu tượng */
@media (max-width:880px){.res-dm{min-height:44px}.dm-ds{grid-template-columns:1fr}.dm-nhom{min-height:52px}}
/* phiếu bán hàng — dải khách (b304: nền phẳng, vạch mảnh; đầu phiếu một dòng ở pos.css .tape-bar) */
.tape-hd{padding:8px 10px;border-bottom:1px solid var(--line-2)}
.tape-ft{border-top:2px solid var(--sky-600);padding:8px 12px 10px;background:#F7F9FB}
/* Hình thức thanh toán: 3 nút liền nhau thay ô chọn xổ xuống (đối chiếu
   KiotViet, sổ tay mục 1b) — nhìn phát thấy đang chọn gì, bấm 1 nhịp.
   Nút đang chọn nền THAN (cam để dành cho Thanh toán & số tiền — ý đã chốt).
   b304 · đứng cùng hàng KHÁCH TRẢ (pos.css .tra-hang), nút co theo chữ chứ không chia đều. */
.pseg{flex:1 1 auto;min-width:0;min-height:34px;padding:0 12px;font-size:12.5px;font-weight:700;text-align:center;
  border:1px solid var(--line);background:var(--paper);color:var(--slate);
  white-space:nowrap;cursor:pointer;transition:background .1s,color .1s,border-color .1s}
.pseg:first-child{border-radius:8px 0 0 8px}
.pseg:last-child{border-radius:0 8px 8px 0}
.pseg+.pseg{border-left:0}
.pseg:hover:not(.on){background:var(--sky-50);color:var(--ink)}
.pseg.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
body.big .pseg{min-height:38px;padding:0 12px;font-size:13.5px}
@media (min-width:881px) and (max-width:1024px){ .pseg{padding:0 9px} }   /* phiếu 360px: ba nút + KHÁCH TRẢ vẫn một hàng */
.chgline{display:flex;justify-content:flex-end;align-items:center;gap:7px;white-space:nowrap;
  font-size:12.5px;font-weight:600;color:var(--green);padding:2px 0}
.chgline.short{color:var(--red)}
.chgline b{font-size:15px}
.chgline .chgclr,.ck-hang .chgclr{width:24px;height:24px;border-radius:5px;display:grid;place-items:center;
  color:var(--slate-2);font-size:13px;font-weight:700;border:1px solid var(--line)}
.chgline .chgclr:hover,.ck-hang .chgclr:hover{background:var(--red-soft);color:var(--red);border-color:#E3B9B4}
.ck-hang .chgclr{margin-left:auto}
/* gợi ý mệnh giá khách hay đưa — bấm là điền, điền xong tự ẩn.
   b304 · đứng CÙNG hàng với ô Khách đưa: hàng cao đúng một nút, vừa bao nhiêu nút thì hiện bấy nhiêu
   (nút không vừa rớt xuống dòng hai — bị giấu), khỏi chiếm một hàng riêng như trước. */
.cashsug{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:6px;min-width:0;height:32px;overflow:hidden}
.cashsug button{height:32px;padding:0 5px;font-size:12px;font-weight:700;border-radius:6px;
  background:var(--paper);border:1px solid var(--line);color:var(--ink-2);white-space:nowrap}
.cashsug button:hover{border-color:var(--or);color:var(--or-6)}
.trow{display:flex;justify-content:space-between;align-items:center;font-size:13px;padding:2px 0;color:var(--slate);gap:8px}
/* dòng hàng vừa thêm: sáng lên một nhịp cho dễ thấy */
.item.fresh{
  /* KHÔNG kéo lề âm — khung cắt phần tràn làm mất chữ cái đầu ("Vòi" thành "òi") */
  background:linear-gradient(90deg,var(--or-50),transparent 70%);
  animation:freshIn 1.1s ease-out;
}
@keyframes freshIn{0%{background-color:#FFE3C6}100%{background-color:transparent}}
@media (prefers-reduced-motion:reduce){.item.fresh{animation:none}}

/* ============ nhận diện bằng ảnh ============ */
/* b254 · `.scan-eye` đã gỡ cùng cái nút của nó (xem `pos.js`). Khung camera
   `.campane` bên dưới VẪN DÙNG — nó là khung quét mã vạch. */
.campane{
  display:flex;flex-direction:column;gap:10px;min-height:0;overflow:auto;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);padding:11px 12px 12px;
}
.campane[hidden]{display:none}
.ph-cam{position:relative;background:#000;border-radius:var(--r);overflow:hidden;aspect-ratio:4/3;max-height:46vh}
.ph-cam video{width:100%;height:100%;object-fit:cover;display:block}
.ph-lb{font-size:12px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--slate);margin-bottom:7px}
.ph-list{display:grid;gap:5px;max-height:38vh;overflow:auto}
.ph-tog{
  display:inline-flex;align-items:center;gap:6px;padding:7px 10px;font-size:12px;border-radius:var(--r);
  border:1px solid var(--line);background:var(--paper);font-size:12.5px;font-weight:600;color:var(--ink-2);
}
.ph-tog input{width:auto;margin:0}
.ph-tog:hover{border-color:var(--sky-400);background:var(--sky-50)}

/* (b304) cảnh báo bán vượt tồn ngay trên dòng hàng → dòng chữ .vuot dưới tên (pos.css). Lớp .over cũ trùng tên
   với .tt.over (giá sửa tay) nên tô hồng cả số tiền — đã bỏ. */

/* b319 · nút "?" mọi màn → đúng mục huong-dan.html (bảng tra nhanh cũ đã gộp vào tệp hướng dẫn) */
.hd-nut strong{font-size:15px}

/* b248 · Bảng "Cột đọc được" trong hộp nhập Excel — kể ra cột nào thành trường
   nào, cột nào bị bỏ qua. Gấp lại mặc định: người nhập file của chính mình thì
   không cần xem, người nhập file KiotViet/MISA thì mở ra soi. */
.fold.khopcot{margin-bottom:var(--space-3)}
.khopbang{width:100%;border-collapse:collapse;font-size:12.5px}
.khopbang td{padding:4px 8px;border-bottom:1px solid var(--line);vertical-align:top}
.khopbang td:first-child{font-weight:600;color:var(--ink);width:50%}
.khopbang td:last-child{color:var(--slate-2)}
.khopbang i{color:var(--slate-2);font-style:normal;opacity:.75}
/* ---- phiếu cho thuê: đọc lại ngày + dòng tổng dính đáy (17/09) ---- */
/* Ô ngày của trình duyệt in mm/dd/yyyy, anh Đạt đọc dd/mm — dòng này đọc lại
   bằng dd/mm và nói luôn số ngày, vì số ngày CHÍNH LÀ số tiền. */
/* ---- form MỘT CỘT, bề rộng ô theo nội dung ----
   Lưới hai cột cho cả phiếu là thứ Baymard nói "never recommended" và NN/g nói
   "multiple columns interrupt the vertical momentum". Ngoại lệ duy nhất được
   phép: 2–3 ô cùng một khối khái niệm — ở đây là cặp ngày giao / ngày hẹn trả. */
.fgrid.mot-cot{grid-template-columns:1fr}
/* Trần chung cho ô chữ dài: modal mở ở chế độ focus rộng 960px, để ô địa chỉ
   kéo hết 924px thì một dòng chữ dài quá tầm mắt. Bảng thiết bị bên dưới vẫn
   dùng trọn bề rộng vì nó là BẢNG, không phải ô nhập. */
.fgrid.mot-cot .f>input,.fgrid.mot-cot .f>select{width:100%;max-width:560px}
.fgrid.mot-cot .f>.o-ngay-k{max-width:560px}   /* b324 · ô ngày (ngayVN) nằm trong khung — cùng trần với ô khác */
/* Bề rộng bằng độ dài chữ sẽ gõ vào (NN/g §6 · GOV.UK text input · Carbon). Các ô của phiếu
   cho thuê nay nằm ở styles/phieu-thue.css (b295); còn lại ô chọn của màn Báo lỗi. */
.fgrid.mot-cot .o-chon>select{max-width:290px}
/* Một cột thì hướng dẫn hiện thường xuyên, không đợi bấm vào ô mới hiện
   (Carbon: helper text "should remain visible"). Luật ẩn cũ chỉ dành cho
   lưới hai cột chật chỗ. */
.fgrid.mot-cot .f .hint{display:block}
/* Báo lỗi ngay cạnh ô: nhiều dấu hiệu cùng lúc — viền, màu, chữ (NN/g §10). */
.f.loi>input,.f.loi>select,.f.loi>.o-ngay-k>input.o-ngay-goc{border-color:var(--rd,#dc2626);background:var(--rose-50,#fef2f2)}
.f.loi>label{color:var(--rd,#dc2626)}
.f .loi-chu{margin-top:3px;font-size:12px;font-weight:600;color:var(--rd,#dc2626)}
@media (max-width:880px){
  .fgrid.mot-cot .f>input,.fgrid.mot-cot .f>select,.fgrid.mot-cot .f>.o-ngay-k{max-width:100%}
}
/* Phiếu cho thuê (dòng đọc ngày, chân phiếu, hai vùng máy tính) → styles/phieu-thue.css (b295). */

/* ---- màn Báo lỗi (b271) ----
   Chỉ còn một ô gõ + một ô chọn lúc. Bảng sáu dòng của b270 đã bỏ: anh Đạt
   *"Mn có đọc hết đâu"* — đúng, người đang gặp lỗi không đọc bảng. */
.fgrid.mot-cot textarea{width:100%;max-width:560px;font-family:inherit;font-size:14px;padding:9px 11px;
  border:1px solid var(--line);border-radius:var(--r-2,8px);background:var(--paper);color:var(--ink);resize:vertical}

.bl-khong{font-size:12px;color:var(--slate-2);line-height:1.5}

/* ═══ b276 · MÀN THIẾT BỊ CHO THUÊ: danh sách dòng, chi tiết, bảng giá đền ═══
   Dòng thay bảng nên KHÔNG có min-width — không thể tràn ngang ở 360px. */
.eqtabs{display:flex;gap:6px;margin-bottom:10px;border-bottom:1px solid var(--line);padding-bottom:8px}
.eqtab{flex:1;min-height:40px;border:1px solid var(--line);border-radius:9px;background:var(--paper);
  font:inherit;font-weight:700;font-size:13px;color:var(--slate);cursor:pointer}
.eqtab.on{background:var(--ink);color:#fff;border-color:var(--ink)}
.eqds{display:grid;gap:6px}
.eqds-ft{display:flex;justify-content:flex-end;margin-bottom:10px}
.eq-i{display:grid;grid-template-columns:1fr auto 18px;grid-template-areas:"nm gi ch" "ct gi ch";
  gap:2px 10px;align-items:center;width:100%;min-height:56px;padding:9px 11px;text-align:left;
  border:1px solid var(--line);border-radius:10px;background:var(--paper);font:inherit;color:var(--ink);cursor:pointer}
.eq-i:hover{border-color:var(--line-2);background:var(--sky-50)}
.eq-nm{grid-area:nm;font-weight:700;min-width:0}
.eq-nm small{color:var(--slate);font-weight:500}
.eq-ct{grid-area:ct;font-size:12px;color:var(--slate)}
.eq-gi{grid-area:gi;font-size:13px;font-weight:700;white-space:nowrap}
.eq-ch{grid-area:ch;justify-self:end;color:var(--slate-2)}
.eq-ch svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.4;transform:rotate(-90deg)}
.eqdt h3{margin:10px 0 8px;font-size:17px}
.eqdt-kv{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed var(--line)}
.eqdt-kv span{color:var(--slate);font-size:13px}
.eqdt-ct{display:grid;gap:5px}
.eqdt-ct-i{display:flex;justify-content:space-between;gap:12px;padding:8px 11px;border:1px solid var(--line);border-radius:9px}
.eqdt-ft{display:flex;gap:8px;justify-content:flex-end;margin-top:14px;flex-wrap:wrap}
.eqden{width:100%}
.eqden td,.eqden th{padding:7px 6px;border-bottom:1px solid var(--line);vertical-align:middle}
.eqpr{display:grid;grid-template-columns:1fr 84px 128px 34px;gap:8px;align-items:end;margin-bottom:8px}
.eqpr-o{display:flex;flex-direction:column;gap:3px;min-width:0}
.eqpr-o>span{font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--slate)}
.eqpr input{width:100%;padding:7px 9px;font-size:13px}
.eqpr input.num{text-align:right}
@media (max-width:560px){
  .eqpr{grid-template-columns:1fr 1fr 34px;grid-template-areas:"ten ten x" "sl den x";row-gap:6px}
  .eqpr-o.eqpr-o-ten{grid-area:ten}.eqpr-o.eqpr-o-sl{grid-area:sl}.eqpr-o.eqpr-o-den{grid-area:den}
  .eqpr>.icobtn{grid-area:x;align-self:center}
  .eqpr input{font-size:16px}
  .eq-i{grid-template-columns:1fr 18px;grid-template-areas:"nm ch" "gi ch" "ct ch"}
  .eq-gi{justify-self:start}
}

/* b277 · Xem thêm: danh sách đích đến thay lưới thẻ (xem managementBody) */
.mg-wrap{display:block}
.mg-ds{display:grid;gap:6px;margin-bottom:14px}
/* b229 · "gọn trong 1 trang, không phải cuộn": 12 dòng xếp một cột thì đáy tới
   955px, quá màn 1366×768 hay gặp nhất. Từ 860px trở lên xếp hai cột — vẫn là
   danh sách dòng, không phải lưới thẻ số như trước b277. */
@media (min-width:860px){ .mg-ds{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px} }
.mg-i{display:grid;grid-template-columns:34px 1fr auto 18px;align-items:center;gap:10px;width:100%;
  min-height:52px;padding:8px 12px;border:1px solid var(--line);border-radius:11px;background:var(--paper);
  font:inherit;color:var(--ink);cursor:pointer;text-align:left}
.mg-i:hover{border-color:var(--line-2);background:var(--sky-50)}
.mg-i-ic{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
  border-radius:9px;background:var(--sky-50);color:var(--sky-700)}
.mg-i-ic svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2}
.mg-i-ic.am{background:var(--or-50);color:var(--or-safe)}.mg-i-ic.rd{background:var(--red-soft);color:var(--red)}
.mg-i-t{font-weight:650;min-width:0}
.mg-i-n{min-width:26px;text-align:center;padding:2px 8px;border-radius:99px;font-size:12.5px;font-weight:800;
  background:var(--sky-100);color:var(--sky-800)}
.mg-i-n.am{background:var(--or-50);color:var(--or-safe)}.mg-i-n.rd{background:var(--red-soft);color:var(--red)}
.mg-i-ch{justify-self:end;color:var(--slate-2)}
.mg-i-ch svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.4;transform:rotate(-90deg)}
.mg-phu .mg-i{background:transparent}
.mg-xau{border:1px solid var(--line);border-radius:10px;padding:8px 12px;background:var(--or-50)}
/* ══ b278 · CHO THUÊ TRÊN ĐIỆN THOẠI — luật "chữ đều" (anh Đạt 21/09) ══
   Ô cao cố định · cột cố định · chữ một dòng, dài thì cắt … · một hàng một đơn vị. */
.kpis.kpi3{grid-template-columns:repeat(3,1fr);gap:8px}
.kpis.kpi3 .kpi{height:60px;padding:8px 6px;text-align:center;display:flex;flex-direction:column;justify-content:center}
.kpis.kpi3 .kpi .k{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:12px}
.kpis.kpi3 .kpi .v{font-size:18px;margin:2px 0 0;white-space:nowrap}
.rt-the{display:grid;grid-template-columns:minmax(0,1fr) 84px;gap:2px 10px;align-items:center;width:100%;height:72px;
  margin-bottom:8px;padding:9px 12px;border:1px solid var(--line);border-radius:10px;background:var(--paper);
  font:inherit;color:var(--ink);text-align:left;cursor:pointer}
.rt-the:active{background:var(--sky-50)}
.rt-l1{grid-column:1;min-width:0;display:flex;gap:8px;align-items:baseline;white-space:nowrap;overflow:hidden}
.rt-so{flex:none;font-size:12px;font-weight:700;color:var(--slate)}
.rt-ten{font-weight:700;font-size:14px;overflow:hidden;text-overflow:ellipsis}
.rt-l2{grid-column:1;min-width:0;font-size:12.5px;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rt-r{grid-column:2;grid-row:1/3;text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:4px}
.rt-r b{font-size:12.5px;font-weight:700;white-space:nowrap}
.rt-r .tag{width:84px;box-sizing:border-box;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:12.5px;padding:3px 0}
.rt-chan{margin:12px 2px 0;font-size:12px;color:var(--slate)}
.rt-chan b{color:var(--ink)}
.rt-trong{padding:26px 14px}
.rt-plus{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:6px;background:var(--or);color:var(--ink);font-weight:800}

/* ===== SOURCE: styles/large-ui.css ===== */
/* ============================================================
   CỠ CHỮ LỚN — bấm nút "A" ở góc phải để bật
   Ưu tiên: chữ trên phiếu > nút bấm > thẻ hàng > ô nhập
   ============================================================ */
.bigbtn strong{font-size:16px;font-weight:800}
.bigbtn.on{background:var(--or-safe);border-color:var(--or-safe);color:#fff}
.bigbtn.on:hover{background:var(--or-safe-hover);border-color:var(--or-safe-hover);color:#fff}

/* ---- 1. Chữ và số tiền trên phiếu bán hàng ---- */
/* b307 · phiếu dễ nhìn cho người lớn tuổi: TO THÊM MỘT BẬC so với cỡ LỚN cũ (nm 14,5→18 · tt 18→21 — thang t5/t6
   TO-NHAN-DIEN.md, t6 "số tiền, tiêu đề vừa" đúng nghĩa cho .tt). Bỏ luôn số lẻ ,5 (dấu hiệu nhích bằng mắt —
   tờ nhận diện mục 3 nhắc). Tên và tiền giữ đúng quan hệ cũ (tên kém tiền một bậc) ở cả cỡ thường lẫn cỡ LỚN. */
body.big .item .nm{font-size:18px;font-weight:700}
body.big .item .ghi{font-size:13px}
body.big .item .tt{font-size:21px;font-weight:800}
body.big .trow{font-size:14.5px;padding:3px 0}
body.big .chgline{font-size:14px}
body.big .chgline b{font-size:17px}
body.big .trow.tot{font-size:14px;letter-spacing:.06em}
body.big .trow.tot .num{font-size:25px}
body.big .cust-row input{font-size:14.5px;padding:7px 10px}
body.big .kh-the b{font-size:15.5px}
body.big .kh-so{font-size:13.5px}
/* b304 · đầu phiếu một dòng + hàng Khách đưa — chỉ máy tính (.tape-bar, .dua-hang); điện thoại giữ 44px ở mobile-runtime */
body.big .tape-bar .tape-td b{font-size:15.5px}
body.big .tape-bar .tape-phu{font-size:14px}
body.big .tape-bar .tape-tg{height:34px;font-size:13.5px}
body.big .dua-o input{height:36px;font-size:14px}
body.big .dua-hang .cashsug{height:36px}
body.big .dua-hang .cashsug button{height:36px;font-size:12.5px}
body.big .dua-no{font-size:13.5px}
body.big .ck-thieu{height:30px;font-size:13px}

/* ---- 2. Nút bấm ---- */
body.big .btn{font-size:15px;padding:11px 18px}
body.big .btn.sm{font-size:13.5px;padding:8px 13px}
body.big .btn.big{padding:12px 18px;font-size:17px}
body.big .icobtn{width:32px;height:32px}
body.big .icobtn svg{width:19px;height:19px}

/* ---- 3. Thẻ hàng bán chạy → styles/the-hang.css (b298) ---- */

/* ---- 4. Ô số lượng (b304: ô gõ trên dòng, đơn vị nhỏ dưới đáy ô) và đơn giá ---- */
body.big .slo{height:44px}
body.big .slo input{padding-bottom:14px;font-size:17px}
body.big .dvi{bottom:5px;font-size:12px}
body.big .item .ttx{font-size:12px;line-height:16px}
body.big input,body.big select{font-size:15px}

/* ---- các phần khác vừa phải ---- */
body.big{font-size:15px}
body.big .scan-field input{font-size:19px}
body.big .head h1{font-size:17.5px}
body.big .navbtn{font-size:12px;padding:12px 4px}
body.big .navbtn svg{width:23px;height:23px}
body.big .tab{font-size:15.5px;min-height:46px;padding:11px 16px}
body.big .tab.add{font-size:15px}
body.big table{font-size:14.5px}
body.big thead th{font-size:12.5px}
body.big .kpi .v{font-size:26px}
body.big .kpi .k{font-size:12.5px}
body.big .m-hd h3{font-size:17px}
body.big .empty h3{font-size:17px}
body.big .empty p{font-size:14.5px}
body.big .res-title{font-size:14px;padding:8px 13px}
body.big .res-count{min-width:23px;height:23px;font-size:14px}
body.big .hint,body.big .note{font-size:13.5px}
body.big .pill{font-size:12.5px}

/* cột phiếu rộng thêm khi chữ to, để tên hàng không bị cắt */
body.big .tape{border-width:3px}
body.big .item{--dong1:24px}   /* b307 · theo cỡ chữ mới (tên 18 / tiền 21px) */
/* chữ to trên máy tính (phiếu 420–520px): cột SL và tiền nở theo cỡ chữ — 54/116px (b307) chỉ vừa chữ thường */
@media (min-width:881px){ body.big .item{grid-template-columns:minmax(0,1fr) 60px 136px var(--cot-but)} }
body.big .slo.dai input{font-size:14px}
body.big .item .tt.dai b{font-size:15px}
/* b306 · chỉ máy tính: trước đây luật 420px lọt xuống điện thoại / máy tính bảng dọc (≤ 880px) — body.big thắng luật một cột
   của responsive-core, cột tìm hàng co về 0px, ô quét biến mất (đo 320 · 390 chữ to, có từ b305) */
@media (min-width:881px){
  body.big .pos3{grid-template-columns:minmax(0,1fr) 520px}
}
@media (min-width:881px) and (max-width:1500px){ body.big .pos3{grid-template-columns:minmax(0,1fr) 470px} }
@media (min-width:881px) and (max-width:1200px){ body.big .pos3{grid-template-columns:minmax(0,1fr) 420px} }

/* ============ đo & đếm bằng camera ============ */
.mz-wrap{display:grid;grid-template-columns:1fr 300px;gap:14px}
.mz-stage{position:relative;background:#0b1b26;border-radius:var(--r-lg);overflow:hidden;aspect-ratio:4/3}
.mz-stage video,.mz-stage canvas{width:100%;height:100%;object-fit:contain;display:block}
.mz-stage canvas{display:none}
.mz-stage.shot video{display:none}
.mz-stage.shot canvas{display:block}
.mz-stage.shot .mz-hint-live{display:none}
.mz-hint-live{
  position:absolute;left:0;right:0;bottom:10px;text-align:center;
  font-size:12.5px;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,.7);pointer-events:none;
}
.mz-acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.mz-side{min-width:0}
.mz-range{width:100%;margin:2px 0 4px}
.mz-count{
  font-family:var(--f-mono);font-size:34px;font-weight:800;color:var(--or-7);line-height:1;
}
.mz-count span{display:block;font-family:var(--f-ui);font-size:12px;font-weight:600;color:var(--slate-2);margin-top:3px}
.mz-tab{width:100%;font-size:12.5px}
.mz-tab td{padding:4px 6px 4px 0;border-bottom:1px solid var(--line-2)}
.mz-tab tr:hover{background:transparent}
@media (max-width:900px){ .mz-wrap{grid-template-columns:1fr} }

/* ---------- ảnh sản phẩm ---------- */
/* (ảnh TRONG thẻ hàng, màu độ dày data-ly và khối ≥1600px → styles/the-hang.css, b298) */
.pimg-prog{height:8px;border-radius:8px;background:var(--sky-100);overflow:hidden;margin:6px 0}
.pimg-prog>div{height:100%;background:var(--sky-600);transition:width .2s}

/* ===== SOURCE: styles/management.css ===== */
/* ---------- THẺ CHUYỂN MỤC kiểu mới (b121) — có biểu tượng, tương phản mạnh ----------
   Dùng ở: Sản phẩm, Công nợ, Báo cáo. Thẻ đang chọn nền THAN chữ trắng;
   bên nào có khoản quá hạn thì nền ĐỎ SẪM + huy hiệu. */
.tabs2{display:flex;gap:9px;margin-bottom:16px;flex-wrap:wrap}
.tb{flex:1;min-width:210px;display:flex;align-items:center;gap:11px;cursor:pointer;text-align:left;
  border:1.5px solid var(--line);background:#fff;border-radius:13px;padding:11px 14px;font:inherit;color:var(--ink)}
.tb-ic{width:36px;height:36px;flex:0 0 36px;border-radius:10px;background:var(--sky-50);
  display:flex;align-items:center;justify-content:center}
.tb-ic svg{width:19px;height:19px;stroke:var(--slate);fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.tb-tx{display:flex;flex-direction:column;min-width:0}
.tb .t{font-size:14.5px;font-weight:800;line-height:1.25}
.tb .n{font-size:12px;font-weight:600;color:var(--slate);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb:hover:not(.on){border-color:var(--sky-300);background:var(--sky-50)}
.tb.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
.tb.on .tb-ic{background:rgba(255,255,255,.14)}
.tb.on .tb-ic svg{stroke:#fff}
.tb.on .n{color:#C5CBD4}
.tb.on.warn{background:#6E1E19;border-color:#6E1E19}
.tb-bg{margin-left:auto;flex:0 0 auto;background:var(--red);color:#fff;font-size:12px;font-weight:800;
  border-radius:99px;padding:2px 9px;white-space:nowrap}
@media (max-width:820px){ .tb{min-width:100%} }

/* Trung tâm Quản lý b157: số cần quyết định trước, lối vào công cụ sau.
   b229 · anh Đạt 11/09: "chỉ có 8 mục cho gọn trong 1 trang k phải cuộn" — ba tầng: dòng trạng thái · việc chờ chủ
   (chỉ khi có) · số hôm nay + công cụ 4 × 2. Khối chữ giới thiệu đầu màn (~100px) bỏ: tiêu đề màn đã nói điều đó. */
.mg-top{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);margin:0 2px var(--space-3)}
.mg-status{margin:0;font-size:12.5px;color:var(--slate);display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}
.mg-viec{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2);margin:0 0 var(--space-3);
  padding:var(--space-2) var(--space-3);background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg)}
.mg-viec-t{font-size:12.5px;font-weight:700;margin-right:var(--space-1)}
.viec-chip{display:inline-flex;align-items:center;gap:var(--space-1);min-height:40px;padding:0 var(--space-3);border-radius:999px;
  border:1px solid var(--line);background:var(--sky-50);color:var(--ink);font:inherit;font-size:12.5px;font-weight:600;
  cursor:pointer;transition:border-color var(--motion-fast),box-shadow var(--motion-fast)}
.viec-chip b{font-size:14px;font-weight:800}
.viec-chip.rd{background:var(--red-soft);border-color:transparent;color:var(--red)}
.viec-chip.am{background:var(--or-50);border-color:transparent;color:var(--or-safe)}
.viec-chip:hover{border-color:currentColor;box-shadow:var(--shadow)}
.mg-h{margin:0 2px var(--space-2);font-size:12.5px;font-weight:700}
@media (max-width:760px){
  .mg-top{align-items:flex-start}.viec-chip{min-height:44px}
}

/* ---------- bảng hóa đơn gọn + nút hành động nằm ngang (b121) ---------- */
/* Dòng phụ là chữ nhỏ nhất màn hình — --slate-2 chỉ đạt tương phản 3.35:1,
   đổi sang --slate cho đạt 5.51:1 (WCAG 4.5:1, sổ tay mục 1). */
.cell-sub{font-size:12.5px;color:var(--slate);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rowacts{display:flex;gap:5px;justify-content:flex-end;flex-wrap:nowrap}
/* Cao ~40px cho đạt vùng bấm (padding dọc 10px, sổ tay mục 1) */
.actbtn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:#fff;
  border-radius:9px;padding:10px 12px;font:inherit;font-size:12.5px;font-weight:600;color:var(--ink);cursor:pointer;white-space:nowrap}
.actbtn svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.actbtn:hover{background:var(--sky-50);border-color:var(--sky-300)}
/* chữ #A34A05 thay --or-7: qua mốc tương phản 4.5:1 trên nền cam nhạt */
.actbtn.key{background:var(--or-50);border-color:#F5C89A;color:#A34A05}
.actbtn.key:hover{background:#FFE7CE}
.actbtn.dg{color:var(--red);border-color:#F0D2D0}
.actbtn.dg:hover{background:#FDF2F2}
.inv-tbl td, .prod-tbl td{vertical-align:middle}
/* Dòng hóa đơn / phiếu giao để THOÁNG hơn — mỗi trang chỉ 8 dòng, dưới còn
   trống nhiều mà chữ lại nhỏ, nhìn mỏi mắt (b125). */
.inv-tbl td{padding:18px 12px;font-size:14px}
.inv-tbl thead th{padding-top:12px;padding-bottom:12px;font-size:12.5px}
.inv-tbl td strong{font-size:14.5px}
.inv-tbl .cell-sub{font-size:12.5px;margin-top:4px}
.inv-tbl .tag{font-size:12.5px;padding:4px 9px}
.inv-tbl .actbtn{padding:10px 12px;font-size:13px;border-radius:10px}
.inv-tbl .actbtn svg{width:16px;height:16px}
.inv-tbl .rowacts{gap:6px}
.prod-tbl td strong{font-size:13.5px}
.prod-tbl .cell-sub{max-width:340px}
/* Ảnh thu nhỏ 28px trước tên hàng (đối chiếu KiotViet, sổ tay mục 1b) —
   hàng VLXD tên na ná nhau, cái ảnh nhận ra nhanh hơn đọc chữ. */
.pcell{display:flex;align-items:center;gap:10px;min-width:0}
.pcell>div{min-width:0}
/* b290 · ảnh hàng chuyển sang 4:3 — ô thu nhỏ theo cho khỏi bị cắt hai bên */
.ptimg{width:37px;height:28px;flex:0 0 37px;object-fit:cover;border-radius:6px;
  border:1px solid var(--line-2);background:#fff}
/* b284 · ô ảnh trống: hiện CHỮ CÁI ĐẦU của tên hàng như bản điện thoại (b248) — ô xám
   trống trơn không nói được gì, mà hai bản lại khác nhau. */
.ptimg.none{background:var(--sky-50);border-style:dashed;display:flex;align-items:center;
  justify-content:center;font-weight:800;font-size:13px;color:var(--slate-2)}

/* ---------- dòng TỔNG tách hẳn khỏi dòng cuối (b122) ----------
   Trước đây dòng tổng chỉ khác nền một chút nên nhìn như một dòng dữ liệu nữa. */
tfoot.tf-sum tr td{
  border-top:2px solid var(--sky-300);
  background:var(--sky-50);
  padding-top:13px;padding-bottom:13px;
  font-weight:800;font-size:12px;letter-spacing:.4px;color:var(--sky-600);
}
tfoot.tf-sum tr td.big{font-size:15.5px;letter-spacing:-.3px;color:var(--ink)}
tfoot.tf-sum tr td.num{font-family:var(--f-mono)}

/* ---------- chuyển trang (b122) ---------- */
.pgbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;justify-content:space-between;
  padding:11px 14px;border-top:1px solid var(--line)}
.pgi{font-size:12.5px;color:var(--slate)}
.pgi strong{color:var(--ink);font-family:var(--f-mono)}
.pgn-wrap{display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.pgn{min-width:40px;height:40px;padding:0 9px;border:1px solid var(--line);background:#fff;border-radius:8px;
  font:inherit;font-size:13px;font-weight:700;color:var(--ink);cursor:pointer;font-family:var(--f-mono)}
.pgn.nav{font-family:var(--f-ui);font-size:12.5px;font-weight:600;color:var(--slate)}
.pgn:hover:not(:disabled){background:var(--sky-50);border-color:var(--sky-300)}
.pgn.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
.pgn:disabled{opacity:.38;cursor:default}
.pgd{color:var(--slate-2);padding:0 2px}

/* ---------- chip lọc nhanh (b122) ---------- */
.fchips{display:flex;gap:6px;flex-wrap:wrap}
.fchip{border:1px solid var(--line);background:#fff;border-radius:999px;padding:5px 12px;
  font:inherit;font-size:12.5px;font-weight:600;color:var(--slate);cursor:pointer}
.fchip:hover{background:var(--sky-50);border-color:var(--sky-300);color:var(--ink)}
.fchip.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
.fchip .fn{font-family:var(--f-mono);font-weight:700;margin-left:2px}   /* b323 · bỏ mờ .75 — số đếm tương phản ≥ 4,5 */
.actbtn.done{background:var(--green-soft);border-color:#A9D8C6;color:var(--green)}
/* ô tick trong form (b123) */
.chk{display:flex;align-items:center;gap:8px;min-height:40px;font-size:13px;cursor:pointer}
.chk input{width:17px;height:17px;flex:none;accent-color:var(--or-6);cursor:pointer}

/* Trả hàng trong màn Sửa hóa đơn */

/* ---------- thẻ chuyển mục cũ (Dữ liệu) ---------- */
.dtabs{display:flex;gap:4px;background:var(--sky-100);border-radius:12px;padding:4px;margin-bottom:16px;flex-wrap:wrap}
.dtab{flex:1;min-width:150px;border:0;background:transparent;border-radius:9px;padding:9px 12px;cursor:pointer;
  font:inherit;font-size:14px;font-weight:700;color:var(--sky-500);text-align:center;line-height:1.25}
/* b284 · câu phụ trên thanh mục: sky-400 trên sky-100 chỉ 2,64:1 → slate (4,9:1). */
.dtab small{display:block;font-size:12px;font-weight:600;color:var(--slate);margin-top:2px}
.dtab.on{background:#fff;color:var(--sky-900);box-shadow:0 1px 3px rgba(0,0,0,.12)}
.dtab.on small{color:var(--or-safe)}   /* b284 · or-6 trên trắng 3,20:1 → or-safe 5,85:1 */
.dtab:hover:not(.on){background:rgba(255,255,255,.55)}

/* ---------- BÁO CÁO: biểu đồ cột, thanh ngang, dòng tiền, tuổi nợ (b120) ---------- */
.rgrid2{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
@media (max-width:1100px){ .rgrid2{grid-template-columns:1fr} }
.delta{display:inline-block;font-size:12px;font-weight:800;border-radius:99px;padding:1px 7px;margin-left:6px}
.delta.up{background:#E7F6EC;color:#177245}
.delta.dn{background:#FDECEC;color:#B3261E}

/* Kiểu A (anh Đạt chọn 17/09): cột ngày + đường trung bình 7 ngày phủ lên.
   `.rchart` thành khung định vị; SVG nằm đúng chồng lên vùng cột (cao 180px như
   `.rcols`), không chiếm chỗ nên hàng cột và nhãn ngày không xê dịch một pixel. */
.rchart{padding:2px 0 0;position:relative;--ax-w:0px}
/* b286 · `--ax-w` chừa cho thang, `--ax-r` chừa khí bên phải: cột và hàng ngày lùi bằng margin, còn
   SVG (định vị theo HỘP ĐỆM, không theo padding) phải tự dời `left` và co `width` — để ở biến.
   🔴 b288 · anh Đạt *"bên trái rộng hơn bên phải… bí bách, không cân"*: gutter cứng 46px mà nhãn rộng
   nhất chỉ 21,5px. Nay reports.js tính `--ax-w` theo nhãn dài nhất; số dưới chỉ là đường lùi. */
.rchart.co-truc{--ax-w:38px;--ax-r:6px}
.rlvl{position:absolute;left:var(--ax-w);right:var(--ax-r,0px);top:2px;height:180px;pointer-events:none;overflow:visible;z-index:0}
.rlvl span{position:absolute;left:0;right:0;height:0;border-top:1px dashed var(--line)}.rlvl span:first-child{border-top-style:solid}
/* b287 · C4 · kỳ ngắn: mọi cột đã có nhãn số ⇒ bỏ vạch ngang, chỉ còn thang số và đường đáy. */
.rlvl.khong-vach span{border-top:0}.rlvl.khong-vach span:first-child{border-top:1px solid var(--line)}
/* 🔴 b288 · nhãn căn GIỮA vạch nên nhãn trên cùng thò 8px khỏi vùng vẽ — nhìn như biểu đồ lệch lên.
   Nhãn trên nép XUỐNG, nhãn "0" nép LÊN; mức giữa vẫn căn giữa. */
.rlvl span:last-child u{top:0}.rlvl span:first-child u{top:-15px}
.rlvl u{position:absolute;right:calc(100% + 6px);top:-8px;text-decoration:none;font-size:12px;line-height:16px;
  font-weight:600;color:var(--slate);white-space:nowrap;font-variant-numeric:tabular-nums}
.rtb{
  /* 🔴 PHẢI KHAI `width` CHO SVG. `left:0;right:0` là đủ cho thẻ thường, nhưng
     SVG là phần tử THAY THẾ: có tỉ lệ nội tại từ `viewBox`. viewBox 100×100 +
     `height:180px` ⇒ trình duyệt tự tính bề rộng 180px, và đường trung bình chỉ
     vẽ trên 1/6 bề ngang rồi dừng. Đo mới thấy: svg rộng 180 trong khi có 28 cột.
     Nhìn ảnh thì tưởng vẽ hụt số liệu — thật ra khung vẽ bị bóp. */
  position:absolute;left:var(--ax-w,0px);top:2px;width:calc(100% - var(--ax-w,0px) - var(--ax-r,0px));height:180px;
  pointer-events:none;overflow:visible;
  /* 🔴 PHẢI NẰM TRÊN CỘT. Bản đầu không khai z-index: đường trung bình bị CỘT
     che mất, nên nó chỉ hiện ở đoạn đầu kỳ — chỗ cột thấp hơn đường — rồi biến
     mất. Nhìn ảnh thì tưởng đường vẽ hụt, thật ra nó nằm dưới. */
  /* 🔴 b286 · ba lớp, ba mức: vạch mức 0 · cột 1 · đường trung bình 2. Trước b286 cột KHÔNG định vị
     nên luôn nằm dưới; nay cột phải nổi lên trên vạch mức, mà đường trung bình vẫn phải trên cột —
     để cả hai cùng z-index 1 thì cột (đứng sau trong DOM) lại đè mất đường, đúng lỗi b229 lần đầu. */
  z-index:2;
}
.rtb polyline{fill:none;stroke:var(--sky-700);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
/* 🔴 b288 · KHÔNG khai z-index ở đây: khai vào là .rcols tự tạo NGỮ CẢNH XẾP LỚP, nhốt cả cột lẫn
   nhãn xuống dưới .rtb (3/7 nhãn bị đường kẻ ngang chữ). Bỏ đi mới xếp được bốn lớp: vạch 0 · CỘT 1
   · đường 2 · NHÃN SỐ 3. */
.rcols{display:flex;align-items:flex-end;gap:3px;height:180px;margin-left:var(--ax-w,0px);margin-right:var(--ax-r,0px);position:relative;touch-action:pan-y}
.rcol{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;height:100%;min-width:6px}
/* b280 · *"biểu đồ bị trùng màu khó nhìn"* — cột xám xanh · cột cao nhất cam · đường xanh đậm. */
/* 🔴 b287 · C1 · WCAG 1.4.11 đòi HÌNH CẦN THIẾT đạt 3:1 với nền. Cột LÀ dữ liệu. `--sky-300`
   #BBC2CC trên nền trắng chỉ 1,79:1 — thiếu 40%. `--sky-400` #8791A0 = 3,19:1. Nặng hơn vì
   màn quầy nhìn từ 80cm dưới đèn sáng (sổ tay ch.1: tương phản phải DƯ chuẩn). */
.rcol i{display:block;width:100%;background:var(--sky-400);border-radius:4px 4px 0 0;transition:background .12s;position:relative;z-index:1}
.rcol.hi i{background:var(--or)}
/* b323 · chú thích biểu đồ doanh thu (cột · ngày cao nhất · đường trung bình) — cùng kiểu chú thích màn Quản lý */
.rchu{display:flex;flex-wrap:wrap;gap:4px 16px;margin:8px 4px 0;font-size:12.5px;color:var(--slate)}
.rchu i{display:inline-block;width:12px;height:10px;border-radius:2px;margin-right:6px;vertical-align:-1px}
.rchu .rchu-cot{background:var(--sky-400)}
.rchu .rchu-hi{background:var(--or)}
.rchu .rchu-tb{height:0;border-top:2px solid var(--sky-700);border-radius:0;vertical-align:3px;width:16px}
@media (hover:hover){ .rcol:hover i{background:var(--sky-600)} }
/* 🔴 b287 · C6 · cột đang chạm/rê đánh dấu bằng VIỀN, KHÔNG đổi màu nền: biểu đồ có đúng ba màu
   mang nghĩa (luật b280), đổi nền là lén thêm màu thứ tư. Viền còn là kênh KHÔNG PHẢI MÀU. */
.rcol.dang i{box-shadow:0 0 0 2px var(--sky-700)}
/* 🔴 b288 · nhãn phải CẮT HẲN đường: z-index chưa đủ (đường 2px chui qua khe giữa các nét chữ vẫn
   đọc ra như gạch ngang), text-shadow thì mờ dần — phải NỀN GIẤY ĐẶC. */
.rcol b{font-size:12px;font-weight:800;color:var(--slate);margin-bottom:3px;white-space:nowrap;
  /* 🔴 KHÔNG bo góc: bo là bốn góc trong suốt, đường lòi qua đúng mấy điểm ảnh đó. */
  position:relative;z-index:3;background:var(--paper);padding:0 4px;line-height:14px}
/* b287 · C3 · cột nhấn chỉ khác nhau bằng MÀU là không đủ (WCAG 1.4.1). Kênh thứ hai: nhãn số
   của cột nhấn luôn hiện và tô màu cam đậm --or-safe (5,85:1) — đọc được cả khi in đen trắng. */
.rcol.hi b{color:var(--or-safe)}
/* b288b · cột chưa tới lượt giữ chỗ nhưng không hiện; chạm vào mới bật — số nằm ngay trên đầu cột
   đang chỉ, thay cho dòng chữ đọc số dưới biểu đồ (đã bỏ hẳn). */
.rcol b.cho{visibility:hidden}.rcol.dang b.cho{visibility:visible}
.rxax{display:flex;gap:3px;margin-top:6px;margin-left:var(--ax-w,0px);margin-right:var(--ax-r,0px)}
/* b287 · C5 · sàn 11px cho mọi chữ cần đọc để làm việc (sổ tay ch.4); màu --slate 5,51:1,
   KHÔNG dùng --slate-2 (3,35:1 — dưới chuẩn chữ 4,5:1). */
.rxax span{flex:1;text-align:center;font-size:12px;line-height:14px;height:14px;color:var(--slate);min-width:6px;overflow:hidden;position:relative}
.rxax u{text-decoration:none}

.hbar{display:grid;grid-template-columns:130px 1fr 96px;align-items:center;gap:10px;margin-bottom:8px}
.hbar .hb-n{font-size:13px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hbar .hb-t{height:15px;background:var(--sky-100);border-radius:5px;overflow:hidden}
.hbar .hb-t i{display:block;height:100%;background:#FDBA74;border-radius:5px}
.hbar.top .hb-t i{background:var(--or-7)}
.hbar .hb-v{font-size:13px;font-weight:700;text-align:right;font-variant-numeric:tabular-nums}

.stkbar{display:flex;height:36px;border-radius:9px;overflow:hidden;gap:2px}
.stkbar div{display:flex;align-items:center;justify-content:center;color:#fff;font-size:12.5px;font-weight:700;white-space:nowrap;overflow:hidden}
.stkbar .s1{background:var(--or-7)}
.stkbar .s2{background:#8791A0}
.stklg{display:flex;gap:18px;flex-wrap:wrap;font-size:12.5px;color:var(--slate);font-weight:600;margin-top:8px}
.stklg i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:6px;vertical-align:-1px}
.stklg i.c1{background:var(--or-7)} .stklg i.c2{background:#8791A0}
.cashline{display:flex;gap:26px;flex-wrap:wrap;margin-top:12px;padding-top:12px;border-top:1px solid var(--line);font-size:13px}

.ages{display:grid;grid-template-columns:repeat(3,1fr);gap:9px}
.agec{border:1px solid var(--line);border-radius:10px;padding:10px 12px}
.agec .t{font-size:12px;font-weight:700;color:var(--ink)}
.agec .m{font-size:19px;font-weight:800;margin-top:3px;font-variant-numeric:tabular-nums}
.agec .c{font-size:12px;color:var(--slate);margin-top:2px}
.agec.gn{background:#F1FAF4;border-color:#CBE9D6} .agec.gn .m{color:#177245}
.agec.am{background:#FFF8EC;border-color:#F5E0B8} .agec.am .m{color:#9A6200}
.agec.rd{background:#FDF2F2;border-color:#F3CFCC} .agec.rd .m{color:#B3261E}

.minibar{height:5px;background:var(--sky-100);border-radius:3px;margin:4px 0 2px;max-width:280px}
.minibar i{display:block;height:100%;background:#FDBA74;border-radius:3px}
@media print{ .rchart,.hbar,.stkbar,.ages{break-inside:avoid} }

/* chấm cam đánh dấu tab khách đang mở (b121 — tab không còn hiện số món/tiền) */
.tab .tdot{width:7px;height:7px;border-radius:99px;background:var(--or);flex:0 0 7px}
/* KPI có viền màu bên trái cho dễ phân biệt (b121) — viền 4px khai ở .kpi (components.css) */
.kpi.gn{border-left-color:#2E9E63} .kpi.rd{border-left-color:#D8524A}
.kpi.am{border-left-color:#E3A008} .kpi.bp{border-left-color:#5A7BA6}
.kpi.or,.kpis .kpi:first-child{border-left-color:var(--or)}

/* ---------- Khóa khi app mở ở cửa sổ khác (b127) ---------- */
#tablock{position:fixed;inset:0;z-index:9000;background:rgba(24,27,32,.72);
  display:grid;place-items:center;padding:24px;backdrop-filter:blur(3px)}
#tablock .tl-box{background:#fff;border-radius:16px;max-width:460px;width:100%;
  padding:26px 26px 22px;text-align:center;box-shadow:var(--shadow-lg)}
#tablock .tl-ic{width:52px;height:52px;margin:0 auto 12px;border-radius:14px;
  background:var(--or-50);display:grid;place-items:center}
#tablock .tl-ic svg{width:28px;height:28px;stroke:var(--or-7);fill:none;stroke-width:1.9}
#tablock h2{font-size:18px;margin:0 0 10px;color:var(--ink)}
#tablock p{font-size:13.5px;color:var(--slate);margin:0 0 10px;line-height:1.55}
#tablock .tl-sub{font-size:12.5px;color:var(--slate-2)}
#tablock .btn{margin-top:6px;padding:11px 20px;font-size:14px}

/* ---------- Dòng phiếu bán ----------
   b304 · nổi lên khi rê (b127: viền + bóng đổ), ô ghi chú (b229/b296: ẩn/hiện bằng độ mờ ngay trong hàng số lượng)
   đã dời về pos.css cùng cả dòng phiếu mới — dòng phẳng có vạch ngăn, ghi chú đọc ở dòng nghiêng dưới tên (.ghi),
   sửa ở ô mở từ ⋯ → Ghi chú. Ở đây còn hàng PHA MÀU của dòng sơn. */
/* b222 · hàng PHA MÀU của dòng sơn — b224 dựng lại theo ba ý anh Đạt 10/09:
   ô màu TO như ảnh sản phẩm · chỗ tiền chỉ có SỐ, không chữ thừa · không được
   tràn ra rìa (ảnh anh gửi: ô màu đè lên viền trái, "/lon" bị cắt).
   Chống tràn bằng ba thứ: cột giữa `min-width:0` (mặc định của flex là auto,
   chính nó làm hàng phình ra), `flex-wrap`, và ô nhập co được. */
/* b225 · Hàng màu là MỘT PHẦN của dòng sơn, không phải một dòng hàng nữa.
   Vạch đứt cũ trông y hệt vạch ngăn giữa hai món, nên trên ảnh 10/09 hàng màu
   như đang thuộc về món kế tiếp. Nay: nền xanh nhạt bo góc, thụt vào — mắt
   thấy ngay nó dính với dòng bên trên.
   `padding-right` chừa đúng cột nút ⋯ + khe cột (--cot-but + --khe, pos.css .item) để tiền màu THẲNG CỘT
   với thành tiền của dòng. b304: hàng màu nằm trong .son (cạnh ô "? lít") ngay dưới dòng, bề ngang trọn dòng. */
.item .maurow{
  flex:1 1 auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap;row-gap:4px;
  padding:5px calc(var(--cot-but) + var(--khe)) 5px 6px;border-radius:8px;
  background:var(--sky-50);min-width:0;
}
/* Ô màu bằng đúng cỡ ảnh sản phẩm ở thẻ hàng (39px) — anh Đạt: "muốn màu nhìn
   to như ảnh sản phẩm luôn, không phải chỉ nhỏ như vậy". Rê vào phóng 2,4× và
   NỔI LÊN TRÊN (z-index) chứ không đẩy chữ, vì transform không chiếm chỗ. */
.item .mauo{
  width:39px;height:39px;flex:0 0 39px;border-radius:7px;border:1px solid #AEBFCB;
  background:var(--mau,#fff);cursor:zoom-in;
  transition:transform .12s cubic-bezier(.2,.7,.3,1), box-shadow .12s;
  transform-origin:left center;
}
.item .mauo:hover{transform:scale(2.4);box-shadow:0 6px 22px rgba(24,27,32,.3);position:relative;z-index:6}
/* Chưa có mẫu màu thì GẠCH CHÉO — không tô một màu đoán. Ô trắng trơn dễ bị
   hiểu là "màu trắng"; vạch chéo nói rõ "chưa biết". */
.item .mauo.trong{background:repeating-linear-gradient(45deg,#fff 0 5px,var(--line) 5px 6px);cursor:default}
.item .mauo.trong:hover{transform:none;box-shadow:none}
/* Cột giữa: ô gõ mã + tên màu + danh sách gợi ý. `min-width:0` là chốt chống
   tràn — thiếu nó là cả hàng đẩy ra ngoài khung phiếu. */
.item .maugiua{flex:1 1 130px;min-width:0;display:flex;flex-direction:column;gap:1px}
.item .mauin{
  width:100%;min-width:0;border:0;border-bottom:1px dashed var(--line);border-radius:0;
  background:transparent;font:inherit;font-size:12px;font-weight:700;letter-spacing:.02em;
  text-transform:uppercase;color:var(--ink);padding:2px 0;
}
.item .mauin::placeholder{color:var(--slate-2);font-weight:400;font-style:italic;text-transform:none}
.item .mauin:focus{border-bottom-color:var(--or);box-shadow:none;background:var(--or-50)}
/* b227 · Dòng dưới mã màu: [Base C] + tên màu. Base phải NỔI hơn tên, vì tên
   là để đối chiếu với khách còn base là để người bán đi lấy đúng thùng. */
.item .maudb{display:flex;align-items:center;gap:5px;min-width:0}
.item .maubase{
  flex:0 0 auto;font-size:12px;font-weight:800;letter-spacing:.02em;
  padding:1px 5px;border-radius:4px;white-space:nowrap;
  background:var(--sky-100);color:var(--sky-700);border:1px solid var(--sky-300);
}
.item .mauten{font-size:12px;color:var(--slate);line-height:1.25;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Ba gợi ý — chọn bằng mắt: ô màu thật đứng trước mã và tên. */
.item .maugoi{display:flex;flex-direction:column;gap:2px;margin-top:3px}
.item .maugoi button{
  display:flex;align-items:center;gap:6px;width:100%;min-width:0;padding:3px 5px;
  border:1px solid var(--line);border-radius:6px;background:var(--paper);text-align:left;
}
.item .maugoi button:hover{border-color:var(--sky-400);background:var(--sky-50)}
.item .maugoi b{font-size:12px;font-weight:700;font-family:var(--f-mono);color:var(--ink);white-space:nowrap}
/* b228 · Mỗi dòng gợi ý phải đủ để CHỌN BẰNG MẮT: ô màu + mã + BASE + tên.
   Anh Đạt 10/09: "bằng tên ghi chưa đủ" — nhiều mã hãng không đặt tên, chỉ
   thấy mỗi mã thì không biết dòng nào là dòng mình cần. */
.item .maugoi .maugb{
  flex:0 0 auto;font-style:normal;font-size:12px;font-weight:800;
  padding:0 4px;border-radius:3px;white-space:nowrap;
  background:var(--sky-100);color:var(--sky-700);
}
.item .maugoi span{font-size:12px;color:var(--slate);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.item .mauog{width:18px;height:18px;flex:0 0 18px;border-radius:4px;border:1px solid #AEBFCB;background:var(--mau,#fff)}
.item .mauog.trong{background:repeating-linear-gradient(45deg,#fff 0 4px,var(--line) 4px 5px)}
/* b225b · Hàng màu chỉ còn ĐÚNG MỘT con số. Anh Đạt 10/09, hai lần: "chỗ tiền
   chỉ hiện số, không ghi thêm gì" rồi "phần giá/lít bỏ". Ô "lít/lon" đã bỏ ở
   b225 (dung tích chọn trên dòng hàng), ô "số màu/lít" bỏ nốt ở đây.
   Con số này CHÍNH LÀ chỗ sửa — trông như chữ thường, rê vào mới hiện viền. */
.item .mautt{display:flex;align-items:center;gap:2px;flex:0 0 auto;margin-left:auto;
  font-size:12.5px;color:var(--ink);white-space:nowrap}
.item .mautti{
  width:84px;min-width:84px;padding:2px 4px;text-align:right;border:1px solid transparent;
  border-radius:5px;background:transparent;font-family:var(--f-num);font-size:12.5px;
  font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;
}
.item:hover .mautti,.item:focus-within .mautti{border-color:var(--sky-300);background:var(--paper)}
.item .mautti:focus{border-color:var(--sky-400);background:#fff;box-shadow:none}
/* Sửa tay rồi thì nổi cam — để người bán biết con số này không còn là công thức. */
.item .mautt.sua .mautti{color:var(--or-7);border-color:#F3C9A2;background:var(--or-50)}
.item .mautra{display:grid;place-items:center;width:18px;height:18px;flex:0 0 18px;
  border-radius:4px;color:var(--or-7);font-size:12px;line-height:1}
.item .mautra:hover{background:var(--or-50)}
.item .mauwarn{flex:0 0 auto;margin-left:auto;font-size:12px;color:var(--or-safe);font-style:italic}
/* b296 · nút ✕ bỏ dòng (b229) đã thôi — bỏ dòng qua menu ⋯ (pos.css .dmenu). Máy cảm ứng không có "rê"
   nên ⋯ đậm thường trực: nút mờ trên điện thoại là nút người ta không thấy. */
@media (hover:none){ .item .dmenu{opacity:1} }
/* b186 · ô ảnh trong thẻ sản phẩm: ảnh hiện tại + nút chọn tệp / xóa */
.pimg-pick{display:flex;align-items:center;gap:var(--space-3)}
.pimg-cur{width:96px;height:72px;flex:0 0 96px;object-fit:cover;border:1px solid var(--line);border-radius:var(--r);background:#fff}
.pimg-act{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2)}
.pimg-act .hint{margin:0;flex-basis:100%}

/* b192 · đáy bảng Sản phẩm: đang xem bao nhiêu trong bao nhiêu + nút nạp thêm */
.p-more{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:14px 16px;border-top:1px solid var(--line)}
.p-more strong{color:var(--ink)}
/* b273: one bounded table scroller; paging remains visible outside it. */
.view.products-list{display:flex;flex-direction:column;min-height:0;overflow:hidden}
.products-list>*,.products-list #ptbl>*{flex-shrink:0}
.products-list #ptbl{display:flex;flex-direction:column;flex:1;min-height:0}
.products-list #p_fpanel{max-height:38vh;overflow:auto}
.products-list #ptbl .p-list-panel{display:flex;flex-direction:column;flex:1;min-height:0}
.products-list .p-table-scroll{flex:1;min-height:0;max-height:none;overscroll-behavior:contain}
#p_pager{background:var(--paper);border:1px solid var(--line);border-radius:12px;margin-top:8px}
.p-page-actions{display:flex;align-items:center;gap:8px;margin-left:auto}
.p-page-actions select{width:auto;min-width:84px}
.p-page-label{color:var(--slate);font-size:12px}

/* ===== SOURCE: styles/quan-ly-dieu-khien.css ===== */
/* ============================================================
   quan-ly-dieu-khien.css · b298 (làm sạch mã, Phần 6 đợt lớn 24/09/2026)
   Tách NGUYÊN VĂN từ đuôi styles/management.css (dòng 395–640 của b297) vì tệp
   đó chạm trần 650 dòng (640/650). Tệp này đứng NGAY SAU management.css trong
   styles/manifest.json nên thứ tự cascade y hệt lúc chưa tách — đã so ảnh A/B
   mọi màn, không đổi một pixel.
   Chứa bộ điều khiển của các màn quản lý: bảng tick Nhóm quyền, form sản phẩm,
   bộ chọn kỳ + tab, "Cần để ý", hàng đầu Báo cáo, thanh công cụ và ngăn lọc
   màn Sản phẩm. Bảng, dashboard, biểu đồ và dòng phiếu vẫn ở management.css.
   ============================================================ */
/* ============================================================
   b231 · BẢNG TICK NHÓM QUYỀN
   Bảng này dài (37 quyền) nên nó tự cuộn trong khung của mình, không kéo dài cả hộp thoại.
   Ô tick cao 24px cho ngón tay, và mỗi nhóm việc có đường viền riêng để mắt bám được hàng.
   ============================================================ */
.ap-bang { max-height: 46vh; overflow-y: auto; margin-top: 12px;
  border: 1px solid var(--line); border-radius: 8px; padding: 12px; background: var(--bg); }
.ap-nhom { border: 0; border-top: 1px solid var(--line); margin: 0; padding: 8px 0 4px; }
.ap-nhom:first-child { border-top: 0; padding-top: 0; }
.ap-nhom legend { padding: 0; font-size: 12px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--slate); }
.ap-q { display: flex; align-items: center; gap: 8px; min-height: 24px;
  padding: 2px 0; font-size: 12.5px; cursor: pointer; }
.ap-q input { width: 16px; height: 16px; flex: 0 0 auto; margin: 0; }
@media (max-width: 880px) {
  .ap-bang { max-height: 40vh; }
  .ap-q { font-size: 14px; min-height: 32px; }
}

/* ═══ b248 · FORM SẢN PHẨM — KHUÔN A (anh Đạt chọn 17/09) ═══
   ĐO ở b247: 21 ô · 22 nhãn · 15 dòng chú thích trong một form. Cái nặng nhất
   là 15 dòng chú thích — ô thì mắt lướt qua được, chú thích thì buộc phải đọc
   rồi mới biết là không cần. Nên: chữ nghĩa GIỮ NGUYÊN, chỉ thôi nói cùng lúc.
   Tầng một (tên · đơn vị · giá bán · giá nhập · tồn · ảnh) nằm ngoài; phần còn
   lại trong <details> của trình duyệt — không tốn tay xử lý nội tuyến nào. */

/* Chú thích chỉ hiện ở ô ĐANG GÕ. Không dùng `display:none` cho phần đọc màn
   hình — `.hint` vẫn ở trong DOM và vẫn đọc được khi con trỏ vào ô. */
.fgrid .f .hint{display:none}
.fgrid .f:focus-within .hint{display:block}
/* Chú thích của khối KHÔNG có ô nhập (nút chi nhánh, nút xóa, dòng nhắc giữ
   hãng) thì luôn hiện — `:focus-within` không bao giờ đúng với chúng. */
.fgrid .f:not(:has(input)) .hint{display:block}

.fold{border:1px solid var(--line);border-radius:var(--r);background:var(--paper);
  grid-column:1/-1;overflow:hidden}
.fold+.fold{margin-top:calc(var(--space-2)*-1 + 2px)}
.fold>summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  justify-content:space-between;gap:var(--space-3);min-height:var(--control-h);
  padding:0 var(--space-3);font-weight:700;color:var(--sky-700);white-space:nowrap}
.fold>summary::-webkit-details-marker{display:none}
.fold>summary::after{content:'⌄';color:var(--slate-2);font-weight:400;
  transition:transform var(--motion-fast)}
.fold[open]>summary::after{transform:rotate(180deg)}
.fold>summary:hover{background:var(--sky-50)}
.fold>summary:focus-visible{outline:2.5px solid var(--or);outline-offset:-2px}
/* b284 · nhãn "Nâng cao" xuống hai dòng ở 390px vì câu phụ đẩy nó co lại (soi ảnh 21/09):
   nhãn giữ một dòng, câu phụ mới là thứ được cắt "…". */
.fold .fsum{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;font-size:12.5px;color:var(--slate-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;text-align:right}
.fold>.fgrid{padding:var(--space-3);border-top:1px solid var(--line);background:var(--sky-50)}

/* Tiêu đề nhóm màu cảnh báo — thay cho style viết thẳng trong products.js */
.sect.dg{color:var(--red);border-bottom-color:#F0D2D0}

/* Ô giá: số tiền là thứ người ta nhìn, cho nó đậm hơn một nấc */
.fgrid .f.money input{font-weight:800;font-size:16px}
.fgrid .f.money input::placeholder{font-weight:400}   /* b296 · chữ mờ "VD: 95.000" in ĐẬM trông như giá thật (soát Phần 3, mục 11) */

/* Chữ cái đầu khi món chưa có ảnh — học từ cách KiotViet làm (soi 17/09):
   mấy trăm khung xám giống hệt nhau thì mắt không bám vào đâu được. */
.pimg-cur.none{display:flex;align-items:center;justify-content:center;
  font-weight:800;font-size:21px;color:var(--slate-2);background:var(--sky-50);border-style:dashed}

/* Nút CHỤP ẢNH chỉ có nghĩa ở máy có camera sau — tức điện thoại.
   Trên máy tính `capture` không làm gì, để nút đó chỉ tổ thừa một lựa chọn. */
.pimg-act .chup{display:none}
@media (max-width:880px){
  .pimg-act .chup{display:inline-flex}
  .fold>summary{min-height:48px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   b257 · BA LOẠI ĐIỀU KHIỂN, BA BỘ ĐỒ KHÁC NHAU
   Anh Đạt 17/09 chụp màn Báo cáo: bộ lọc kỳ, tab chuyển màn và nút "Làm mới"
   đều là `.btn`, xếp hai hàng giống hệt nhau. Mắt không phân được bấm cái nào
   đổi SỐ, cái nào đổi MÀN, cái nào CHẠY LẠI.
     · chọn một trong mấy cái  → `.segbar/.seg`  (khối liền, ô đang chọn nổi lên)
     · chuyển màn              → `.tabline/.tabl` (chữ trên đường kẻ, vạch cam)
     · hành động               → `.text-action`   (nút chữ, tách hẳn sang phải)
   🔴 Cam chỉ TÔ, không VIẾT (tờ nhận diện §2): vạch dưới tab dùng `--or`, còn
   chữ thì dùng `--ink`. Không có chữ cam nào ở đây.
   ═══════════════════════════════════════════════════════════════════════════ */
.segbar{
  display:inline-flex;gap:var(--space-1);flex:0 0 auto;
  background:var(--sky-50);border:1px solid var(--line);
  border-radius:var(--r);padding:var(--space-1);
}
.seg{
  border:0;background:none;cursor:pointer;white-space:nowrap;
  height:calc(var(--control-h) - var(--space-2));
  padding:0 var(--space-3);border-radius:var(--r-sm);
  font-family:var(--f-ui);font-size:12.5px;font-weight:600;color:var(--slate);
  transition:background var(--motion-fast),color var(--motion-fast);
}
.seg:hover{color:var(--ink)}
.seg.on{background:var(--paper);color:var(--ink);font-weight:700;box-shadow:var(--shadow)}

.tabline{
  display:flex;align-items:center;gap:var(--space-5);
  border-bottom:1px solid var(--line);margin-bottom:var(--space-4);
  /* Khai CẢ HAI trục: một trục không phải `visible` thì trục kia tự thành `auto`
     (bẫy đã vấp ở Sổ lỗi #149). Ở đây không có gì nhô ra nên `hidden` là đúng. */
  overflow-x:auto;overflow-y:hidden;
}
.tabl{
  position:relative;flex:0 0 auto;border:0;background:none;cursor:pointer;
  white-space:nowrap;padding:var(--space-3) 0;
  font-family:var(--f-ui);font-size:14px;font-weight:700;color:var(--slate);
  transition:color var(--motion-fast);
}
.tabl:hover{color:var(--ink)}
.tabl.on{color:var(--ink)}
.tabl.on::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:3px;background:var(--or);
}

@media (max-width:880px){
  /* Điện thoại: khối kỳ trải hết bề ngang (.segbar ở mobile.css), mỗi ô chia đều — ngón tay bấm dễ.
     Ô cao lên đúng `--control-h` cho đủ 40px chạm. */
  .seg{flex:1 1 0;min-width:0;height:var(--control-h);padding:0 var(--space-2)}
  .tabline{gap:var(--space-4)}
}

/* b259 · "Cần để ý" — mỗi dòng MỘT VIỆC, có đường sang đúng màn đã lọc sẵn.
   Đây là chỗ thay cho 14 cái bảng: báo cáo nói ra việc, không chép lại sổ. */
.dey{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.dey li{
  display:flex;align-items:center;gap:var(--space-4);
  padding:var(--space-3) 0;border-bottom:1px solid var(--line-2);
  font-size:14px;color:var(--ink-2);line-height:1.5;
}
.dey li:last-child{border-bottom:0;padding-bottom:0}
.dey li:first-child{padding-top:0}
.dey li>span{flex:1 1 auto;min-width:0}
.dey li>button{flex:0 0 auto;white-space:nowrap}
@media (max-width:880px){
  .dey li{flex-direction:column;align-items:flex-start;gap:var(--space-2)}
}

/* b261 · Hàng trên cùng màn Báo cáo: bên trái là giờ lấy số, bên phải là ô chọn
   mục chi tiết — đúng chỗ nút "Làm mới" cũ đứng, ngay TRÊN hàng bốn ô số.
   Anh Đạt: *"Ý t ô chọn mục cần xem nằm trên phần khách còn nợ mà"*. */
.rep-top{
  display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);
  flex-wrap:wrap;margin-bottom:var(--space-3);
}
/* b302 · ⑥ dòng phụ dưới ô số (Tiền mặt · CK, phần bán còn chưa thu): chữ nhỏ, số đậm cùng phông số */
.kpi .rep-phu{margin-top:2px}
.kpi .rep-phu b{font-weight:700;color:var(--ink-2)}
.rdt-so{margin:-4px 0 10px;font-size:12px}
/* Ô chọn phải trông như MỘT điều khiển, không phải chữ rời đứng cạnh hộp rời.
   Nhãn nằm trong cùng một khung, ngăn bằng một nét mảnh. */
.rep-chon{
  display:inline-flex;align-items:center;flex:0 0 auto;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;transition:border-color var(--motion-fast),box-shadow var(--motion-fast);
}
.rep-chon:focus-within{border-color:var(--sky-500);box-shadow:0 0 0 3px var(--sky-100)}
.rep-chon>span{
  padding:0 var(--space-3);align-self:stretch;display:flex;align-items:center;
  background:var(--sky-50);border-right:1px solid var(--line);
  font-size:12px;font-weight:700;color:var(--slate);white-space:nowrap;
}
.rep-chon>select{
  width:auto;min-width:190px;border:0;border-radius:0;background:none;
  height:calc(var(--control-h) - var(--space-1));padding:0 var(--space-3);
  font-size:12.5px;font-weight:600;
}
.rep-chon>select:focus{box-shadow:none}
@media (max-width:880px){
  .rep-top{gap:var(--space-2)}
  .rep-chon{width:100%}
  .rep-chon>select{flex:1 1 auto;min-width:0;height:var(--control-h);font-size:16px}
}

/* b262 · Con số tổng mã nằm trong tab "Danh sách hàng" — chip bên dưới không có số này. */
.tabn{
  margin-left:var(--space-2);padding:1px var(--space-2);border-radius:var(--r-pill,999px);
  background:var(--sky-50);color:var(--slate);font-size:12px;font-weight:700;
}
.tabl.on .tabn{background:var(--or-50);color:var(--or-safe)}

/* 🔴 NÚT "SỬA" THÔI TÔ CAM CẢ CỘT (tờ nhận diện §2: cam để TÔ MỘT chỗ).
   Nút đứng im lặng, đậm lên khi con trỏ vào chính DÒNG đó — thứ người ta sắp
   bấm thì nổi, chín dòng còn lại thì thôi. Trên màn chạm không có `:hover` nên
   nút vẫn hiện đủ viền, chỉ là không cam. */
.prod-tbl tr:hover .actbtn{border-color:var(--sky-300);background:var(--sky-50);color:var(--ink)}

/* ═══ b264 · THANH CÔNG CỤ MÀN SẢN PHẨM: ô tìm là trọng điểm ═══
   Anh Đạt: *"Các ô chức năng phải là trọng điểm, phải là nội dung chính."*
   Đo bản cũ: ô tìm chiếm 19% bề ngang, nhỏ hơn cả nút "Chọn từng món". */
/* 🔴 Ô ĐỆM PHẢI TẮT, KHÔNG THÌ Ô TÌM KHÔNG NỞ RA ĐƯỢC. `.toolbar-sp{flex:1}` là
   chỗ trống co giãn dùng để đẩy nhóm bên phải ra mép — nó GIÀNH hết phần dư với
   ô tìm, nên ô tìm khai `flex:1` cũng đứng yên và giữa thanh hở một mảng trống.
   Thanh này không cần ô đệm: ô tìm nở ra là tự đẩy "Xếp theo" và phễu ra mép. */
.ptool .toolbar-sp{display:none}
.ptool .search-in{flex:1 1 auto;max-width:none}
/* 🔴 KHUNG RỘNG KHÔNG CÓ NGHĨA LÀ Ô NHẬP RỘNG. `.toolbar input{width:auto}` ở
   `components.css` đè lên `input{width:100%}` của nền, nên ô nhập co theo CHỮ:
   đo được khung 981px mà ô nhập chỉ 243px — ảnh chụp trông y như chưa sửa gì.
   Lại đúng họ lỗi "phần bị xén vẫn có toạ độ": đo nhầm cái vỏ, tưởng đã xong. */
.ptool .search-in input{
  width:100%;height:44px;font-size:15px;font-weight:600;padding-left:38px;
}
.ptool .search-in svg{width:19px;height:19px}
.ptool select{flex:0 0 auto;width:auto;min-width:max-content}

/* Nút lọc chỉ còn cái phễu. Có mục đang lọc thì nó tự mang màu cam + con số —
   cam ở ĐÚNG MỘT chỗ trên màn, và chỉ khi có chuyện (tờ nhận diện §2). */
.icoloc{
  display:inline-flex;align-items:center;gap:var(--space-1);
  width:auto;min-width:40px;height:40px;padding:0 var(--space-2);justify-content:center;
}
.icoloc svg{width:18px;height:18px;stroke-width:2}
.icoloc.on{background:var(--or-50);border-color:#F5C89A;color:var(--or-safe)}
.icoloc .fn{font-size:12px;font-weight:800}

/* Chân ngăn lọc: "Hiển thị" và nút xóa — KHÔNG phải bộ lọc nên tách hẳn,
   có nhãn riêng và một nét kẻ ngăn. */
.fpanel-ft{
  display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;
  margin-top:var(--space-3);padding-top:var(--space-3);border-top:1px solid var(--line);
}

/* ═══ b265 · NGĂN LỌC CÓ BƯỚC: bốn dòng, mở đúng một tầng ═══
   Anh Đạt: *"Khi chọn từ tầng 1… sau khi chọn tự hiện tầng 2 (có khép tầng 1 lại
   và hiện mục đã chọn), tiếp tục đến kết quả cuối."* */
.lgdong{
  display:flex;align-items:center;gap:var(--space-3);width:100%;
  padding:var(--space-3) var(--space-1);
  border:0;border-bottom:1px solid var(--line-2);background:none;text-align:left;
  transition:color var(--motion-fast);
}
.lgdong + .chiprow:not([hidden]){padding-bottom:var(--space-3);border-bottom:1px solid var(--line-2)}
.lgdong:hover .lgten{color:var(--ink)}
.lgcaret{width:12px;font-size:12px;color:var(--slate)}
.lgten{font-size:13.5px;font-weight:700;color:var(--ink-2)}
.lgso{
  margin-left:auto;font-size:12px;color:var(--slate);
  max-width:52%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Tầng đang có mục chọn: nói ra mục đó bằng màu cam an toàn — người dùng không
   phải mở lại mới biết mình đang lọc gì. Cam ở đây là CHỮ nên dùng --or-safe,
   không dùng --or (tờ nhận diện §2: cam sáng chỉ để tô nền). */
.lgdong.dachon .lgten{color:var(--ink)}
.lgdong.dachon .lgso{color:var(--or-safe);font-weight:700}
.lgdong.mo{border-bottom:0;padding-bottom:var(--space-1)}
.lgdong.mo .lgten{color:var(--ink)}

/* ===== SOURCE: styles/mobile.css ===== */
/* ============================================================
   BẢN CHO ĐIỆN THOẠI (b128) — chỉ bán 1 khách + tra giá
   ============================================================ */
.paybar{display:none}
@media (max-width:880px){
  /* thẻ hàng trên điện thoại → styles/the-hang.css (b298) */
  /* 15/09 · anh Đạt: "phần sản phẩm nhanh bị che". Đo lại bằng DOM thật thì
     thanh thanh toán KHÔNG che nó (cuộn hết còn dư 79px) — cái sai là VỊ TRÍ:
     kệ nằm SAU danh sách bán chạy, nên muốn bấm một nhóm phải cuộn hết danh
     sách, và trên đường cuộn nó cứ ló nửa người dưới mép thanh tiền.
     Đúng luật màn bán kiểu LAI anh chốt 02/09 — chưa gõ thì KỆ trước, bán chạy
     sau. .pos3-main là flex cột, nên chỉ cần đẩy .pane xuống sau; KHÔNG đụng
     thứ tự trong pos.js, nên máy tính giữ nguyên kệ ở đáy cột trái. */
  .pos3-main>.pane{order:1}
  .pos-quick{padding:0}
  .pos-qcats{gap:8px;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:thin}.pos-qcat{flex:0 0 150px;min-height:56px}
  .posq-manager{grid-template-columns:1fr;min-height:0}.posq-catlist{max-height:170px}
  .posq-products{grid-template-columns:1fr;max-height:290px}

  /* đầu trang gọn */
  .head h1{font-size:17px}

  /* ══ b278 · MỌI THANH DÍNH ĐÁY DÙNG CHUNG MỘT MỐC ══
     Anh Đạt 21/09: *"Phiếu thanh toán dính taskbar công cụ. Thiếu tương phản dễ nhầm"*
     và *"số trang đang xem cũng nên để gần xuống taskbar… bằng với phần phiếu thanh
     toán để đồng bộ, k xê dịch"*. Trước b278: thanh giỏ bottom:60px trong khi thanh
     điều hướng cao 68px → hai thanh tối ĐÈ lên nhau 8px thành một khối đen; thanh
     trang thì sticky với lề 8px hai bên nên không cùng bề ngang.
     Nay ba con số ở :root (--h-rail · --h-bar) là MỐC DUY NHẤT: thanh điều hướng,
     thanh giỏ (Bán hàng), thanh trang (Sản phẩm) đều đọc từ đó. Đổi một chỗ, cả
     ba đổi theo — không còn cảnh mỗi thanh một con số riêng.
     Phương án A anh chọn sau khi xem demo: thanh điều hướng GIỮ TỐI, thanh giỏ
     TRẮNG có viền trên 2px + bóng hắt lên; nút Thanh toán cam chữ đen (6,35:1).
     Thân màn chừa đúng chỗ nên dòng hàng cuối không bao giờ nằm dưới thanh. */
  .paybar{display:none}
  .paybar.on{display:flex;position:fixed;left:0;right:0;
    height:var(--h-bar);z-index:55;align-items:center;gap:10px;background:var(--paper);color:var(--ink);
    border-top:2px solid var(--line);padding:0 10px 0 14px;box-shadow:0 -6px 14px rgba(20,24,30,.10)}
  /* nửa trái thanh là NÚT mở phiếu (b165) — bỏ dáng nút, canh trái */
  .paybar .pb-l{display:flex;flex-direction:column;min-width:0;flex:1;
    text-align:left;padding:0;background:none;border:0;color:inherit;align-items:flex-start}
  .paybar .pb-n{font-size:12px;color:var(--slate);letter-spacing:.3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    display:flex;align-items:center;gap:5px}
  .paybar .pb-t{font-size:19px;font-weight:800;font-family:var(--f-mono);letter-spacing:-.5px;white-space:nowrap}
  .paybar .pb-go{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;
    background:var(--or-safe);color:#fff;border:0;border-color:var(--or-safe);border-radius:10px;
    padding:10px 14px;font:inherit;font-size:14.5px;font-weight:800;cursor:pointer;white-space:nowrap}
  /* anh Đạt 21/09: "Chữ thanh toán hơi chìm. Chữ trắng đi" — chữ trắng trên cam --or chỉ
     đạt 2,80:1 (tờ nhận diện §2 cấm), nên nền đổi sang --or-safe #A94704: trắng trên đó
     đạt 5,85:1, vẫn là cam của tiệm, chữ nổi hẳn. */
  .paybar .pb-go svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:2.4}
  .paybar .pb-go:active{background:var(--or-safe-hover);border-color:var(--or-safe-hover)}
  /* chừa chỗ cho thanh đó khỏi che nút cuối phiếu */
  .tape{min-height:300px;padding-bottom:calc(var(--h-bar) + 8px)}

  /* ---- màn Tra giá ---- */
  .ph-search{display:flex;align-items:center;gap:8px;background:var(--paper);
    border:1px solid var(--line);border-radius:12px;padding:0 10px;margin-bottom:10px}
  .ph-search svg{width:18px;height:18px;stroke:var(--slate-2);fill:none;stroke-width:2;flex:none}
  .ph-search input{flex:1;min-width:0;border:0;background:transparent;padding:13px 0;font-size:16px}
  .ph-search input:focus{box-shadow:none}
  /* 🔴 b243 · anh Đạt 16/09: "khung tìm tra giá bị lỗi UI".
     Ô nhập ở đây KHÔNG phải cái hộp người ta nhìn thấy — nó trong suốt, không
     viền, nằm lọt giữa hộp trắng `.ph-search`, bắt đầu SAU cái kính lúp và
     dừng TRƯỚC nút máy ảnh. Mà luật chung `:focus-visible{outline:2.5px solid
     var(--or)}` lại vẽ viền cam quanh CHÍNH Ô NHẬP ⇒ viền cam thò ra trên dưới
     (ô cao hơn hộp vì `padding:13px 0`) và thụt vào bên trái (bắt đầu sau kính
     lúp) — nhìn như hai khung lệch nhau.
     Vá: chuyển viền báo-đang-gõ sang HỘP NHÌN THẤY. KHÔNG bỏ viền đi —
     `:focus-within` vẫn là một dấu báo đầy đủ, chỉ là vẽ đúng chỗ. */
  .ph-search:focus-within{outline:2.5px solid var(--or);outline-offset:2px;border-color:var(--sky-500)}
  .ph-search input:focus-visible{outline:none}
  .ph-search .phcam{flex:none;border:0;background:var(--or-50);border-radius:9px;
    padding:8px;display:grid;place-items:center;cursor:pointer}
  .ph-search .phcam svg{width:20px;height:20px;stroke:var(--or-7)}
  /* 🔴 SỔ LỖI #144 · `commerce.css` khai `.ph-list{max-height:38vh;overflow:auto}`
     cho màn rộng. Khối mobile vẽ lại `.ph-list` nhưng KHÔNG gỡ trần đó, nên trên
     điện thoại danh sách tra giá bị nhốt trong 38% chiều cao màn: cắt cụt giữa
     dòng rồi bỏ trống hơn nửa màn hình. Không ai báo vì nó không đổ vỡ — nó chỉ
     nhỏ đi. Vẽ lại một lớp thì phải gỡ CẢ những thuộc tính lớp cũ đặt, không chỉ
     đặt lại mấy cái mình quan tâm. */
  .ph-list{display:flex;flex-direction:column;gap:7px;max-height:none;overflow:visible}
  .ph-row{display:grid;   /* b320 · cột / khoảng / đệm của dòng: san-pham.css (tên trọn bề ngang, giá xuống hàng dưới) */
    background:var(--paper);border:1px solid var(--line);border-radius:12px}
  /* Tên dài thì xuống tối đa HAI dòng rồi cắt bằng dấu ba chấm — anh Đạt chốt
     16/09 cho thẻ hóa đơn, cùng lý do: *"ai muốn xem chi tiết cũng phải bấm vào"*.
     Không chặn thì một cái tên bốn dòng làm dòng đó cao gấp đôi mấy dòng kia. */
  .ph-nm{font-size:14px;font-weight:700;line-height:1.3;min-width:0;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .ph-nm .ph-sub{-webkit-line-clamp:1}
  .ph-sub{font-size:12.5px;color:var(--slate-2);font-weight:400;margin-top:3px}
  .ph-pr{text-align:right;white-space:nowrap;display:flex;flex-direction:column;align-items:flex-end;gap:3px}
  .ph-p{font-size:16px;font-weight:800;font-family:var(--f-mono);letter-spacing:-.3px}
  .ph-p span{font-size:12px;font-weight:600;color:var(--slate-2);margin-left:2px;font-family:var(--f-ui)}
  .ph-w{font-size:12.5px;color:var(--slate)}
}

@media (max-width:880px){
  /* Ô đếm: 2 cột, nén lại — xếp dọc 4 ô là hết cả màn hình trước khi thấy nội dung */
  .kpis{grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px}
  .kpi{padding:10px 11px}
  .kpi .k{font-size:12px;letter-spacing:.3px}
  .kpi .v{font-size:17px}
  .kpi .n{font-size:12px;margin-top:2px;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  /* mấy dòng nhắc trên thanh công cụ không cần trên màn nhỏ */
  .toolbar .pill{display:none}
  .toolbar{gap:8px}
  .panel-hd h2{font-size:14.5px}
}

/* ---------- Thẻ thay bảng trên điện thoại (b130) ----------
   Bảng 7 cột không nhét vừa màn 390px, cuộn ngang thì mất nửa thông tin.
   Mỗi bản ghi thành một thẻ, đọc trọn trong một khung hình. */
.mcards{display:flex;flex-direction:column;gap:9px}
.mcard{background:var(--paper);border:1px solid var(--line);border-radius:13px;
  padding:12px 13px 11px;display:flex;flex-direction:column;gap:5px}
.mcard:active{background:var(--sky-50)}
.mc-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.mc-id{display:flex;flex-direction:column;min-width:0}
.mc-id strong{font-size:16px;letter-spacing:-.3px}
.mc-id span{font-size:12px;color:var(--slate)}
.mc-money{font-size:17px;font-weight:800;letter-spacing:-.4px;white-space:nowrap}
.mc-cust{font-size:14px;font-weight:700;line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mc-cust span{font-weight:400;color:var(--slate);font-size:12.5px}
.mc-meta{font-size:12.5px;color:var(--slate);line-height:1.35;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.mc-cod{font-size:12.5px;color:var(--red);background:var(--red-soft);
  border-radius:7px;padding:5px 9px}
.mc-cod.ok{color:var(--green);background:var(--green-soft)}
.mc-acts{display:flex;gap:6px;margin-top:4px;flex-wrap:wrap}
.mc-acts .actbtn{flex:1;justify-content:center;padding:11px 8px;font-size:13px;min-height:42px}
.mc-acts .actbtn.wide{flex:1 0 100%}
@media (max-width:880px){
  .pgbar{flex-direction:column;align-items:stretch;gap:9px;border-top:0;padding:12px 2px 0}
  .pgn-wrap{justify-content:center}
  .pgi{text-align:center}
}


@media (max-width:880px){
  /* Thẻ đã có khung riêng rồi — bỏ khung panel bọc ngoài cho đỡ hai lớp viền */
  .panel:has(.mcards){background:transparent;border:0;box-shadow:none;padding:0;margin-bottom:14px}
  .panel:has(.mcards) .panel-hd{padding:0 2px 9px;border:0;background:transparent;
    display:flex;align-items:center;gap:8px;flex-wrap:nowrap}
  .panel:has(.mcards) .panel-hd h2{font-size:14px;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis}
  .panel:has(.mcards) .panel-hd .tag{flex:0 0 auto}
  .panel:has(.mcards) .head-sp{flex:1}
  /* chip lọc phiếu giao: cho cuộn ngang thay vì xuống 2 hàng */
  .fchips{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px}
  .fchips::-webkit-scrollbar{display:none}
  .fchip{flex:0 0 auto}
}

/* ---------- b133: thẻ "Sao lưu & phục hồi" — MỘT tấm 4 dòng ----------
   Anh Đạt duyệt qua mockup 10/08: mỗi dòng = icon + tên + 1 dòng tình
   trạng + huy hiệu màu + 1 nút. Chi tiết (bảng bản lưu) giấu sau nút. */
.bkrow{display:flex;align-items:center;gap:14px;padding:15px 16px;border-bottom:1px solid var(--line-2)}
.bkrow:last-child{border-bottom:0}
.bkic{width:38px;height:38px;flex:0 0 38px;border-radius:10px;background:var(--sky-50);
  display:grid;place-items:center;color:var(--slate)}
.bkic svg{width:19px;height:19px;stroke-width:1.9;fill:none;stroke:currentColor;
  stroke-linecap:round;stroke-linejoin:round}
.bktx{flex:1;min-width:0}
.bkt{font-size:14px;font-weight:700;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.bkt .tag{border-radius:99px;padding:2px 9px}
.bks{font-size:12.5px;color:var(--slate);margin-top:3px;overflow-wrap:anywhere}
.bkrow .btn{flex:0 0 auto}
#snaplist{border-bottom:1px solid var(--line-2)}
#snaplist .tbl-wrap{max-height:300px}
@media (max-width:880px){
  .bkrow{flex-wrap:wrap;padding:13px 12px;gap:10px}
  .bkrow .btn{flex:1;min-width:110px}
  .bkic{display:none}
}

/* b248 · NÚT CHỤP ẢNH NGAY TRÊN DÒNG TRA GIÁ (điện thoại, chỉ Chủ).
   Trên điện thoại màn Sản phẩm đổi thành Tra giá nên không có form để vào —
   đây là cửa duy nhất để chụp ảnh hàng khi đang đứng ở kho.

   🔴 SỔ LỖI #143 · THÊM PHẦN TỬ THỨ BA VÀO MỘT HÀNG CHỈ TÍNH CHO HAI.
   `.ph-row` là lưới `minmax(0,1fr) auto` — ĐÚNG HAI cột. Bản đầu của b248 nhét
   ô ảnh vào làm con thứ ba mà không sửa luật xếp ⇒ nó rơi xuống hàng ngầm phía
   dưới, cả dòng vỡ thành hình zigzag: tên một nơi, giá một nẻo, chip tồn trôi
   giữa. Và `flex:0 0 44px` viết trên con của LƯỚI thì không có tác dụng gì.
   Bài đo của tôi chỉ hỏi "có nút chụp ảnh không → CÓ" nên báo ĐẠT trong lúc
   dòng đang vỡ — đúng #40 · #50: đo được con số, không đo được cái xấu.
   → Nay khai đủ BA cột, và chỉ khi dòng thật sự có ô ảnh. */
/* 🔴 b290 · anh Đạt: *"nguyên khung ảnh bên trái tab sản phẩm. Viền trái bo cong. Nguyên 25% của ô
   tab sản phẩm đó"*. Ô 44px quá nhỏ để nhìn ra món hàng. Nay ô ảnh chiếm 25% bề ngang hàng, tràn
   sát mép trái, bo cong theo thẻ, tỉ lệ 4:3 — BẰNG ĐÚNG khung ngắm lúc chụp, nên chụp sao thấy vậy.
   Hàng bỏ đệm trái để ảnh chạm mép; đệm phải giữ nguyên. */
.ph-row:has(.ph-cam){grid-template-columns:25% minmax(0,1fr) auto;padding:0 13px 0 0;gap:11px;overflow:hidden}
.ph-row .ph-cam{width:100%;height:auto;aspect-ratio:4/3;border:0;border-radius:11px 0 0 11px;
  background:var(--sky-50);color:var(--slate-2);
  display:flex;align-items:center;justify-content:center;cursor:pointer;overflow:hidden}
.ph-row .ph-cam.co{background:var(--paper)}
.ph-row .ph-cam{position:relative}
.ph-row .ph-cam img{width:100%;height:100%;object-fit:cover}
/* Chữ cái đầu thay cho sáu ô máy ảnh giống hệt nhau đè cạnh trái — học từ cách
   KiotViet làm. Huy hiệu máy ảnh nhỏ ở góc vẫn nói cho biết ô này BẤM ĐƯỢC. */
.ph-row .ph-cam b{font-weight:800;font-size:26px;color:var(--slate-2)}
.ph-row .ph-cam-hh{position:absolute;right:4px;bottom:4px;width:18px;height:18px;
  border-radius:999px;background:var(--sky-700);display:flex;align-items:center;justify-content:center}
.ph-row .ph-cam-hh svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:2.2}
.ph-row .ph-cam.co .ph-cam-hh{background:var(--slate-2)}
.ph-row .ph-cam:active{background:var(--or-50)}

/* ═══ b251 · THANH DƯỚI ĐIỆN THOẠI — DỰNG LẠI CHO CÂN ═══
   Anh Đạt 17/09 nhìn máy thật: *"Bán hàng nhìn rõ ràng k cân. B xem lại cách sắp
   xếp, thao tác nhấn cũng hài hoà."* Ông đúng. Ba chỗ sai của bản b250:

   ① 🔴 NĂM NÚT KHÔNG BẰNG NHAU. `.navbtn{flex:1 0 auto;min-width:68px}` cho mỗi
      nút rộng theo ĐỘ DÀI CHỮ ("Cho thuê" ngắn hơn "Bán hàng"), nên nút thứ ba
      không nằm ở TÂM thanh. Và bài đo của tôi báo "✅ chính giữa" vì nó đếm THỨ
      TỰ (3/5), không đo TÂM HÌNH HỌC — đo nhầm thứ, lại một lần nữa (#30 · #49).
      → `flex:1 1 0` + `min-width:0`: năm cột bằng nhau tuyệt đối, cột giữa nằm
      đúng tâm dù chữ dài ngắn thế nào.

   ② 🔴 NHÃN KHÔNG CÙNG MỘT ĐƯỜNG. b250 nhấc cả CÁI NÚT lên, nên chữ "Bán hàng"
      cao hơn bốn chữ kia — mắt đọc ra một hàng gãy. → Chỉ nhấc BIỂU TƯỢNG lên
      (huy hiệu cam), còn NHÃN đứng nguyên hàng với bốn nhãn kia. `transform`
      không chiếm chỗ nên nhãn không xê dịch một pixel nào.

   ③ 🔴 HAI THỨ CÙNG ĐÒI CHÚ Ý. Nút đang mở có nền sáng + vạch cam, đứng cạnh ô
      cam thì thành hai điểm nhấn cạnh nhau. → Nút thường: bỏ nền, chỉ đổi màu
      chữ/biểu tượng và một vạch cam mảnh trên đầu. Ô giữa: cam. Mỗi thứ một vai.

   Chạm: mỗi cột cao 56px (≥44px theo chuẩn), `:active` cùng một kiểu cho cả năm
   — "thao tác nhấn hài hoà" như anh nói. */
@media (max-width:880px){
  /* 🔴 PHẢI MỞ CẢ HAI TRỤC. `foundation.css` đặt `overflow-y` cho thanh DỌC ở máy
     quầy; ở đây chỉ mở `overflow-x:visible` thì CSS **bắt buộc** biến nó thành
     `auto` — luật: một trục không phải `visible` thì trục `visible` kia tự thành
     `auto`. Kết quả: thanh vẫn xén, huy hiệu cam bị cắt mất nửa trên, mà mọi phép
     đo toạ độ vẫn báo đúng vì phần bị cắt VẪN CÓ TOẠ ĐỘ — nó chỉ không được vẽ.
     Đo bằng `getComputedStyle(.rail).overflow` mới thấy: `auto / x:auto / y:auto`. */
  /* b278 · MỐC CHUNG cho mọi thanh dính đáy · --rail 0: thanh bên thành thanh dưới · --h-trang: thanh trang Sản phẩm
     cao riêng (b296, cách tính ở cham-dien-thoai.css chỗ #p_pager) */
  :root{--rail:0px;--h-rail:60px;--h-bar:56px}
  .rail{
    position:fixed;left:0;right:0;z-index:60;flex-direction:row;box-shadow:0 -2px 14px rgba(8,51,79,.2);
    overflow:visible;align-items:stretch;gap:0;
    height:calc(var(--h-rail) + env(safe-area-inset-bottom));
    padding:4px 4px calc(4px + env(safe-area-inset-bottom));
  }
  /* b284 · nhãn 9,5px nhỏ hơn mức iOS/Android khuyên (>=10pt) — đọc bằng đuôi mắt thì hụt.
     11px vẫn vừa MỘT dòng cho cả năm nhãn ở 360px (cột 72px, nhãn dài nhất ~52px). */
  /* min-width 68px — đo cho máy hẹp nhất hay gặp, iPhone SE 375px: 5 nút × 68 = 340 < 375, còn dư 35px. */
  .navbtn{
    flex:1 1 0;gap:3px;padding:4px 2px;border-radius:var(--r);font-size:12px;
    min-height:52px;justify-content:center;min-width:68px;
  }
  .navbtn span{
    max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  /* Nút thường đang mở: KHÔNG nền, chỉ sáng chữ + vạch cam mảnh trên đầu. */
  .navbtn.on,.navbtn:hover{background:none}
  .navbtn.on{color:#fff}
  /* Vạch báo màn đang mở: ngắn lại và bo tròn cho cân với huy hiệu tròn ở giữa. */
  .navbtn.on::before{
    left:50%;right:auto;transform:translateX(-50%);
    top:0;bottom:auto;width:26px;height:3px;border-radius:0 0 3px 3px;
  }
  .navbtn:active{background:rgba(255,255,255,.10)}

  /* b278 · anh Đạt 21/09: *"bỏ ô bán hàng cao hơn thanh taskbar, làm quay lại như cũ,
     vì khi cao hơn ảnh hưởng cách nhìn của các trang khác"*. Toàn bộ khối huy hiệu
     nhô 38px (b250–b251) gỡ hẳn — năm nút phẳng, bằng nhau, Bán hàng đứng đầu. */
}

/* b273: product pages on narrow screens. */
@media(max-width:880px){
  /* b276 · thanh chọn trang DÍNH ĐÁY màn: đổi trang xong danh sách về đầu mà
     ngón tay vẫn ở ngay chỗ chọn trang, không phải cuộn xuống lại. 60px là
     khoảng chừa cho thanh điều hướng dưới — cùng con số .paybar đang dùng. */
  /* b278 · cùng mốc với thanh giỏ: bottom = --h-rail, cao = --h-bar, sát hai mép.
     Anh Đạt: *"nếu trang có số lớn sẽ lại bị tràn hoặc dãn"* → hai nút ‹ › chỉ còn
     biểu tượng cố định 44px, ô chọn trang ở giữa co giãn, dòng đếm "1–60 / 5.407"
     xuống hàng phụ nhỏ ngay dưới ô chọn — không thứ nào tranh bề ngang với nhau,
     số 5 chữ số hay 6 chữ số đều cùng một khuôn. */
  /* fixed chứ không sticky: sticky không bao giờ trượt QUÁ chỗ đứng tĩnh của nó, mà chỗ
     đứng tĩnh nằm trên phần đệm đáy của .view → cuộn hết vẫn hở 68px so với thanh điều
     hướng (ĐÃ ĐO). Thanh giỏ đã fixed, thanh trang fixed theo — cùng một cách, cùng một mốc. */
  /* b323 · anh Đạt 28/09: "Đang xem 1–31 / 31 mã" là một dòng nhỏ CUỐI danh sách, không dính đáy màn (thôi che một dòng hàng) */
  #p_pager{margin:6px 0 0;padding:4px 0;border:0;border-radius:0;background:none;box-shadow:none;
    display:grid;grid-template-columns:44px minmax(0,1fr) 44px;grid-template-rows:auto auto;gap:0 8px;align-items:center;align-content:center}
  /* b284 · chữ ô chọn trang 15px → 16px: dưới 16px iPhone tự phóng to cả trang khi chạm
     vào ô — đúng lỗi đã vá ở ô tìm thiết bị (b281). */
  #p_pager .p-stat{grid-column:2;grid-row:2;text-align:center;font-size:12.5px;line-height:1.2;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}
  #p_pager .p-page-actions{display:contents}
  #p_pager .p-page-actions[hidden]{display:none}
  #p_pager .p-page-actions .btn{grid-row:1/3;width:44px;height:44px;min-height:0;padding:0;font-size:0}
  #p_pager .p-page-actions .btn::before{font-size:22px;line-height:1}
  #p_pager #p_prev::before{content:"‹"}
  #p_pager #p_next::before{content:"›"}
  #p_pager .p-page-label{display:none}
  #p_pager select{grid-column:2;grid-row:1;width:100%;padding:0 8px;text-align:center;text-align-last:center;
    font:700 16px/1 var(--f-mono);font-variant-numeric:tabular-nums}   /* b284 · 15px → 16px: dưới 16px iPhone tự phóng to cả trang khi chạm vào ô */

  /* b277 · MÀN BÁO CÁO TRÊN ĐIỆN THOẠI (trước b277 màn này bị chặn hẳn).
     Bốn ô số xếp 2×2 (quy tắc .kpis ở trên đã lo), thanh kỳ chiếm trọn một
     hàng, hai ô ngày chia đôi hàng dưới — không nhét năm thứ vào một hàng. */
  .view #rbody .tbl-wrap{max-height:none}
  .toolbar:has(.segbar){flex-wrap:wrap;gap:8px}
  .segbar{display:flex;width:100%}   /* khối kỳ trải hết bề ngang (quan-ly-dieu-khien.css khai .segbar gốc) */
  .segbar .seg{flex:1;min-height:40px;font-size:12.5px}
  .toolbar #r_from,.toolbar #r_to{flex:1 1 40%;min-width:0;min-height:40px}
  .toolbar #r_cn_sel{flex:1 1 100%}
}
/* 🔴 b296 · sáu dòng b277 ở trên từng nằm NGOÀI @media (dấu } đóng khối #p_pager đặt sớm một đoạn) ⇒
   chạy cả trên MÁY TÍNH từ 21/09: thanh kỳ Báo cáo 1366px kéo dài hết bề ngang, hai ô ngày mỗi ô 600px.
   Soát 24/09 mục 12. Nay về lại trong khối điện thoại; máy tính trở lại đúng "thanh cũ" b279 hứa giữ. */

/* ══ b279 · BÁO CÁO TRÊN ĐIỆN THOẠI — thanh kỳ một dòng · chip mục · bốn ô thẳng cột · dòng thay bảng ══ */
@media (max-width:880px){
  .rky{display:flex;align-items:center;gap:4px;height:48px;padding:4px;margin-bottom:8px;
    background:var(--paper);border:1px solid var(--line);border-radius:999px}
  .rky-b{flex:none;border:0;border-radius:999px;background:transparent;color:var(--slate);
    font:400 22px/1 inherit;cursor:pointer}
  .rky-b:disabled{color:var(--line-2);cursor:default}
  .rky-b:active:not(:disabled){background:var(--sky-50)}
  .rky-now{flex:1;min-width:0;border:0;background:transparent;font:inherit;color:var(--ink);text-align:center;line-height:1.2;padding:0}
  .rky-now b{display:block;font-size:14px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .rky-now span{display:block;font-size:12px;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .rchips{display:flex;gap:6px;overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -12px 10px;padding:0 12px 2px;scrollbar-width:none}
  .rchips::-webkit-scrollbar{display:none}
  .rchip{flex:none;height:36px;padding:0 14px;border:1px solid var(--line);border-radius:999px;background:var(--paper);
    font:inherit;font-size:12.5px;font-weight:700;color:var(--slate);white-space:nowrap;cursor:pointer}
  .rchip.on{background:var(--or-50);border-color:var(--or);color:var(--or-safe)}
  /* bốn ô: hai lớn trên, hai nhỏ dưới — cùng cột, cùng đơn vị, số đủ, không rớt dòng */
  .kpis.rdt-2{grid-template-columns:1fr 1fr;gap:8px;margin-bottom:8px}
  .kpis.rdt-2.rdt-mot{grid-template-columns:1fr}   /* b325 · V12: người không phải chủ không có ô Lợi nhuận — ô Doanh thu rộng hết hàng */
  .kpi.rdt-lon{padding:10px 12px;min-height:84px}
  .kpi.rdt-lon .k{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kpi.rdt-lon .v{font-size:21px;letter-spacing:-.5px;white-space:nowrap;font-variant-numeric:tabular-nums}
  .kpi.rdt-lon .n{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kpi.rdt-nho{padding:8px 12px;min-height:58px;display:flex;flex-direction:column;justify-content:center}
  .kpi.rdt-nho .k{font-size:12px;white-space:nowrap}
  .kpi.rdt-nho .v{font-size:16px;letter-spacing:-.3px;white-space:nowrap;font-variant-numeric:tabular-nums;margin-top:2px}
  .kpis.rdt-nho2{margin-bottom:10px}
  .kpis.rdt-2 .kpi:first-child{border-left-color:var(--or)}
  .kpis.rdt-nho2 .kpi:first-child{border-left-color:var(--line)}
  /* biểu đồ: không tiêu đề, không khung panel; dòng chữ dưới đổi khi chạm cột */
  /* b288b · đệm trên/dưới cân nhau: bỏ dòng chữ đọc số rồi thì đáy thẻ là hàng ngày, đo ra trên
     13px dưới 7px — lệch. 6px trên + 8px dưới cho ra 9px/9px. */
  .rdt-chart{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);padding:6px 12px 8px;margin-bottom:10px}
  /* 🔴 b288 · anh Đạt: *"font số không đều nhau (20 to hơn 15)"*. Không phải cỡ chữ — đo ra cả 5
     nhãn đều 11px/600. Thủ phạm là CHIỀU CAO KHUNG 110px: số mức có thể là 3, 4 hay 5, mà 110 không
     chia hết cho cái nào, nên mỗi vạch rơi vào một phần lẻ pixel khác nhau (đo: 0,81 · 0,16 · 0,48 ·
     0,81) ⇒ trình duyệt khử răng cưa mỗi chữ một kiểu ⇒ chữ nọ trông đậm/to hơn chữ kia.
     120 chia hết cho 3 (40), 4 (30) và 5 (24) ⇒ mọi vạch cùng một phần lẻ ⇒ năm chữ khử răng cưa
     giống hệt nhau. Máy tính 180px vốn đã chia hết cho cả ba. */
  .rdt-chart .rcols{height:120px}
  .rdt-chart .rtb{height:120px}   /* SVG đường trung bình phải cao bằng hàng cột, kẻo vẽ lọt ra ngoài khung */
  .rdt-chart .rlvl{height:120px}  /* vạch mức cũng vậy — lệch một chút là số đọc sai một mức */
  .rdt-chart .rchart.co-truc{--ax-w:38px;--ax-r:6px}
  .rdt-chart .rlvl u{font-size:12px}
  /* 🔴 nhãn ngày phải được TRÀN RA khỏi ô của nó. Ô rộng ~14px, chữ "22/09" rộng ~28px: để
     `overflow:hidden` như bản máy tính thì cắt thành "2:" — số ngày đọc ra sai. Trên điện thoại
     nhãn đã thưa (mỗi `buoc` cột một nhãn) nên hai bên là ô RỖNG, tràn ra không đụng ai; hai đầu
     thì lọt vào phần đệm 12px của khung. */
  .rdt-chart .rxax span{overflow:visible}
  /* 🔴 `text-align:right` KHÔNG kéo được chữ vào: khi chữ RỘNG HƠN ô thì dòng chữ vẫn bắt đầu ở
     mép trái ô rồi trườn sang phải — đo ra nhãn cuối "22/09" lòi 23px ra ngoài thẻ, sát mép màn.
     Phải NEO chữ bằng định vị: giữa ô cho nhãn thường, sát trái cho nhãn đầu, sát phải cho nhãn cuối. */
  .rdt-chart .rxax u{position:absolute;bottom:0;left:50%;transform:translateX(-50%);white-space:nowrap}
  .rdt-chart .rxax span.x-dau u{left:0;transform:none}
  .rdt-chart .rxax span.x-cuoi u{left:auto;right:0;transform:none}
  .rdt-chart .rcol{cursor:pointer}
  /* khối dòng — thay bảng */
  .rdk{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;margin-bottom:10px}
  .rdk h5{margin:0;padding:9px 12px;font-size:12px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--slate);border-bottom:1px solid var(--line)}
  .rdk .dey{padding:8px 12px}
  .rdg{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:center;height:44px;padding:0 12px;border-bottom:1px solid var(--line);font-size:13px}
  .rdk .rdg:last-child{border-bottom:0}
  .rdg-t{min-width:0;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .rdg-s{display:block;font-style:normal;font-weight:400;font-size:12px;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .rdg-v{font-weight:800;white-space:nowrap;font-variant-numeric:tabular-nums}
  .rdg-v.rd{color:var(--red)}
  .rdk-trong{margin:0;padding:14px 12px;font-size:12.5px;color:var(--slate)}
  .rdt-chan{margin:4px 2px 0;font-size:12px;color:var(--slate);text-align:center}
  .rdt-chan .text-action{padding:0;font-size:12px}
  .rky-seg .seg{flex:1 1 auto}
  .hdchips{margin-bottom:8px}
  .rky-f{margin-top:12px}
}

/* ══ b280 · phiếu thuê trên điện thoại + màn chọn thiết bị → styles/phieu-thue.css (b295) ══ */
/* b283 · thanh "Đang nghe" của mic: bảy thứ một hàng tràn 28px ở 390px (máy quét bấm thấy "Tắt mic" ở 316→388).
   Điện thoại cho xuống hàng: dòng 1 chấm + Đang nghe + Đọc lại, dòng 2 ba nút. */
@media (max-width:880px){
  .vhead{flex-wrap:wrap;row-gap:6px}
  .vhead .btn.sm{min-height:36px}
}

/* ===== SOURCE: styles/workflows.css ===== */
/* ============================================================
   BẢO HÀNH (b136) — sổ hàng đang giữ của khách
   Anh Đạt 14/08/2026: bỏ hẳn màn tra + huy hiệu đếm ngược.
   Còn lại đúng một bảng: món của ai, lỗi gì, cầm bao lâu rồi.
   ============================================================ */
.bh-tbl{width:100%;border-collapse:collapse;font-size:13.5px}
.bh-tbl td{padding:13px 15px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.bh-tbl tbody tr:last-child td{border-bottom:0}
.bh-tbl .nm{font-weight:700;font-size:14px;line-height:1.35}
.bh-tbl .sub2{font-size:12px;color:var(--slate);margin-top:3px;font-family:var(--f-mono)}
.bh-tbl .bh-fault{font-size:12.5px;color:var(--ink-2);margin-top:4px;font-style:italic}
.bh-tbl td.c-who{width:210px}
.bh-tbl td.c-age{width:150px}
.bh-tbl td.a{width:190px;text-align:right}

/* Cầm hàng của khách bao lâu rồi. Quá 10 ngày tô cam — không phải cảnh báo
   hệ thống, mà là nhắc gọi cho khách trước khi khách gọi cho mình. */
.wbadge{display:inline-flex;align-items:center;border-radius:9px;padding:7px 12px;
  font-size:13px;font-weight:800;line-height:1.2;white-space:nowrap}
.wb-soon{background:#FFF3E0;color:#8A4B00}
.wb-non{background:#EEF0F3;color:var(--slate)}

/* bốn bước — bấm để lọc, con số là số món đang đứng ở bước đó */
/* 🔴 b276 · BỐN TAB CHIA ĐỀU MỘT KHỐI, KHÔNG CUỘN NGANG.
   Trước b276 khối mobile ép min-width:126px + overflow-x:auto ⇒ ĐO 20/09 ở
   khung 390: vùng thấy 366px, nội dung 504px — tab đầu và tab cuối bị cắt,
   phải vuốt mới thấy (ảnh anh Đạt gửi). Lưới 4 cột bằng nhau + min-width:0
   cho phép nhãn xuống hai dòng thay vì đẩy nhau ra ngoài. */
.stepbar{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin:0 0 14px}
.step{min-width:0;padding:9px 4px;text-align:center;font-size:12.5px;font-weight:700;
  border:1px solid var(--line);background:var(--paper);color:var(--slate);
  font-family:inherit;cursor:pointer;min-height:44px;overflow-wrap:anywhere;line-height:1.25}
.step:first-child{border-radius:9px 0 0 9px}
.step:last-child{border-radius:0 9px 9px 0}
.step+.step{border-left:0}
.step:hover:not(.on){background:var(--sky-50);color:var(--ink)}
.step.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
.step b{display:block;font-family:var(--f-mono);font-size:15px;margin-top:2px}

/* thẻ trên điện thoại — tên khách đứng trước, vì câu hỏi luôn là "của ai" */
.bcard{background:var(--paper);border:1px solid var(--line);border-radius:13px;padding:12px 13px;margin-bottom:9px}
.bcard .l1{display:flex;justify-content:space-between;gap:8px;align-items:baseline}
.bcard .l1 b{font-size:15px;line-height:1.3;min-width:0}
.bcard .l1 span{font-family:var(--f-mono);font-size:12px;color:var(--slate);flex:0 0 auto}
.bcard .l2{font-size:12.5px;color:var(--slate);font-family:var(--f-mono);margin:2px 0 7px}
.bcard .bh-item{font-size:13.5px;font-weight:700;line-height:1.35}
.bcard .bh-fault{font-size:12.5px;color:var(--ink-2);font-style:italic;margin:3px 0 8px}
.pill2{display:inline-flex;align-items:center;border-radius:100px;padding:5px 11px;font-size:12px;font-weight:700}

/* b284 · bốn ô bước bảo hành trên điện thoại: MỘT dòng, cao đều — nhãn ngắn đã lo ở warranties.js, đây
   chặn luôn trường hợp nhãn dài (tiệm khác đổi chữ) làm ô cao so le. (b299 · gộp từ mobile.css) */
@media (max-width:880px){
  .step{font-size:12px;padding:8px 3px;height:56px;white-space:nowrap;overflow:hidden;
    text-overflow:ellipsis;display:flex;flex-direction:column;
    align-items:center;justify-content:center;gap:1px}
  .step b{font-size:14px}
}

/* thanh gập trong Danh mục & hệ thống (b141) */
.acchd{cursor:pointer;user-select:none}
.acchd:hover h2{color:var(--sky-700)}
.acar{font-size:13px;color:var(--slate-2);width:18px;text-align:center}


/* ---- b145 → b147: Sổ màu sơn ----
   Bỏ bảng, đổi sang thẻ từng khách: câu hỏi ở quầy luôn là "màu của AI",
   nên tên khách phải là thứ to nhất, mã màu nằm bên trong.
   Đệm theo thang 4/8/12 của sổ tay mục 4; CAM vẫn chỉ dành cho hành động
   chính (nút Thêm màu), thẻ mã màu dùng cam NHẠT vì nó là thứ cần chú ý
   nhất trong khối, không phải nút hành động thứ hai. */
.smwrap{max-height:calc(100vh - 268px);overflow:auto}
.smlist{display:grid;gap:8px}
.smk{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--paper);overflow:hidden}
.smk.on{border-color:var(--sky-300);box-shadow:var(--shadow)}
.smhd{display:flex;align-items:center;gap:12px;width:100%;text-align:left;padding:8px 12px;background:none}
.smhd:hover{background:var(--sky-50)}
.smav{
  flex:0 0 auto;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  background:var(--sky-100);color:var(--sky-700);font-weight:700;font-size:14px;
}
.smnm{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.smnm b{font-size:14px;font-weight:700;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.smnm i{font-style:normal;font-size:12px;color:var(--slate-2)}
.smdt{flex:0 0 auto;font-size:12px;color:var(--slate-2)}
.smar{flex:0 0 auto;width:16px;text-align:center;color:var(--slate-2);font-size:12px}
.smbd{padding:0 12px 12px 58px;display:grid;gap:8px}
.smm{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  background:var(--sky-50);border:1px solid var(--line-2);border-radius:var(--r);padding:6px 8px 6px 10px;
}
.smmi{flex:1;min-width:140px;font-size:12px;color:var(--slate);line-height:1.5}
.smmi i{font-style:italic;color:var(--ink-2)}
.smact{flex:0 0 auto;display:flex;gap:2px;margin-left:auto}
.smadd{justify-self:start;margin-top:2px}
.smchip{display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  font-family:inherit;font-size:12.5px;font-weight:700;color:var(--or-7);
  background:#FFF4EC;border:1px solid #F3C9A6;border-radius:999px;padding:5px 11px;
  line-height:1.3;white-space:nowrap}
.smchip:hover{background:#FFE8D6;border-color:#E9A96F}
.smchip b{font-weight:800;color:var(--slate);font-size:12px}

/* Điện thoại: bỏ thụt lề theo vòng tròn tên khách cho rộng chỗ, và để màn
   tự cao — cuộn của cả trang lo, không cần khung cuộn riêng. */
@media (max-width:880px){
  .smwrap{max-height:none;overflow:visible}
  .smbd{padding-left:12px}
  .smm{gap:8px}
  .smmi{min-width:100%;order:3}
  .smact{order:2}
}

/* ================= b146 — CHỐNG IPHONE PHÓNG TO KHI CHẠM / LƯỚT =================
   Anh Đạt báo 19/08: "vào app bằng điện thoại, vẫn bị zoom khi lướt."
   Web đã trị hồi bản 34, app thì quên — hai bên hai bộ CSS khác nhau.
   Có BA nguyên nhân, phải trị đủ cả ba mới hết:

   1. Chạm đôi phóng trang. Trước đây chỉ đặt cho nút và thẻ, nên chạm trúng
      khoảng trống giữa chúng là lỗi quay lại. PHẢI đặt cho `*`.
      `manipulation` vẫn cho véo hai ngón phóng to — người lớn tuổi cần cái đó,
      chỉ tắt riêng phóng-bằng-chạm-đôi.
   2. Safari tự phóng khi con trỏ vào ô nhập có cỡ chữ dưới 16px, và KHÔNG tự
      thu lại. App đang có mấy ô 11,5–13px.
   3. Chữ tự phồng khi xoay ngang máy.
   Bài kiểm bắt buộc trước mỗi bản: xem `so-tay-web.md` mục A.
   b299 · cách trị (1) và (3) nay nằm ở luật gốc `*` và `html` trong foundation.css — mỗi
   selector một chỗ; ở đây còn (2): ô nhập 16px trên điện thoại. */
@media (max-width:880px){
  input,select,textarea{font-size:16px}
  .cust-row input,input[type=file]{font-size:16px}
  /* b304 · ô số lượng, ô Giảm giá / Khách đưa của phiếu bán tự đặt 16px ở mobile-runtime.css (khối b296 → b304) —
     ô nào có luật riêng đặt cỡ chữ nhỏ hơn thì phải nói rõ 16px ngay tại luật điện thoại của nó mới thắng. */
}

/* b299 · khối vá "tương phản WCAG 2.2 AA cho nút chữ trắng" (13 nút cam: nền --or-safe, rê chuột
   --or-safe-hover) đã về đúng luật gốc của từng nút — foundation · pos · responsive-core · commerce ·
   large-ui · mobile. Nút cam chữ trắng mới: dùng --or-safe ngay tại luật của nó, đừng vá chồng ở đây. */

/* ===== SOURCE: styles/hoa-don.css ===== */
/* ============================================================
   HÓA ĐƠN — hộp Sửa hóa đơn (thêm / bớt hàng, b149 · b150) và danh sách hóa đơn
   (mọi dòng cao bằng nhau, b150 · b152).
   b299: tách nguyên văn từ workflows.css (tệp chạm 97% trần 650 dòng); đứng ngay sau
   workflows.css — thứ tự cascade giữ y nguyên.
   ============================================================ */
/* ═══════════════════════════════════════════════════════════════════════════
   BẢN 149 — SỬA HÓA ĐƠN: THÊM / BỚT HÀNG
   ═══════════════════════════════════════════════════════════════════════════
   Băng nhắc "đang sửa hóa đơn" phải ĐẬP VÀO MẮT. Người bán quen bấm F2 rồi
   quét hàng liên tục; lỡ quét nhầm vào thẻ đang sửa thì hóa đơn cũ bị ghi đè
   mà không ai hay. Nên dùng nền đỏ nhạt + viền trái đỏ đậm, đứng ngay trên ô
   quét — chỗ mắt nhìn tới đầu tiên. */
.edbar{display:flex;align-items:center;gap:12px;margin:0 0 10px;
  padding:10px 12px;border-radius:8px;background:#FEF2F2;
  border:1px solid #FCA5A5;border-left:4px solid #DC2626}
.edbar .ed-ic{flex:0 0 auto;display:flex;color:#B91C1C}
.edbar .ed-tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;line-height:1.35}
.edbar .ed-tx strong{font-size:14px;color:#991B1B}
.edbar .ed-tx span{font-size:12.5px;color:var(--slate-2)}
.edbar .btn{flex:0 0 auto}
/* Nút thanh toán lúc đang sửa: đổi hẳn màu để không bấm theo quán tính. */
.pb-go.ed{background:#B91C1C;border-color:#B91C1C;color:#fff}
.pb-go.ed:hover{background:#991B1B;border-color:#991B1B}

/* Ô tìm hàng trong hộp Sửa hóa đơn. Cố ý chỉ 8 dòng và cao tối đa 210px —
   đây là hộp sửa chữa, cần danh sách dài thì mở ra màn Bán hàng. */
.ei-add>input{width:100%}
.ei-res{margin-top:6px;max-height:210px;overflow-y:auto;overscroll-behavior:contain}
.ei-res:empty{display:none}
.ei-r{display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:6px}
.ei-r+.ei-r{border-top:1px solid var(--line)}
.ei-r:hover{background:var(--sky-50)}   /* b248 · SỔ NHẬN DIỆN §1: `--sky-1` là biến của WEB, app không khai và ở đây KHÔNG có màu dự phòng ⇒ rê chuột vào dòng trong hộp Sửa hóa đơn không sáng lên, im lặng suốt nhiều bản. Đổi sang `--sky-50` là nền rê chuột app đang dùng. */
.ei-n{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.ei-n strong{font-size:13.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ei-n i{font-style:normal;font-size:12px;color:var(--slate-2)}
.ei-r .btn{flex:0 0 auto}
.ei-non{padding:12px 8px;font-size:13px;color:var(--slate-2);text-align:center}
/* b296 · ô chọn hàng của hộp Nhập / Xuất kho — cùng khuôn danh sách với ô tìm của hộp Sửa hóa đơn ở trên
   (thay ô xổ chứa mọi mã, soát Phần 3 mục 7). Chọn xong thành một dòng tên + mã + tồn, nút Đổi bên phải. */
.m-goi{margin-top:6px;max-height:300px;overflow-y:auto;overscroll-behavior:contain;border:1px solid var(--line);border-radius:var(--r)}
.m-goi-i{display:flex;flex-direction:column;align-items:flex-start;gap:1px;width:100%;min-height:44px;padding:6px 10px;
  border:0;background:var(--paper);text-align:left;font:inherit;color:var(--ink);cursor:pointer}
.m-goi-i+.m-goi-i{border-top:1px solid var(--line)}
@media (hover:hover){ .m-goi-i:hover{background:var(--sky-50)} }
.m-goi-i b,.m-chon-t b{font-size:13.5px;font-weight:600}
.m-goi-i span,.m-chon-t span{font-size:12px;color:var(--slate)}
.m-chon{display:flex;align-items:center;gap:var(--space-3);padding:6px 6px 6px 10px;border:1px solid var(--sky-400);border-radius:var(--r);background:var(--sky-50)}
.m-chon[hidden],.m-goi[hidden]{display:none}
.m-chon-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}

/* Dòng "BẢN SỬA LẦN N" trên phiếu in. In ra giấy nhiệt và giấy A4 đều phải
   thấy — đây là thứ để biết tờ nào mới khi hai tờ cùng một số hóa đơn. */
.ed-mark{font-weight:700}
@media print{ .ed-mark{display:block} }

@media (max-width:880px){
  .edbar{flex-wrap:wrap;gap:8px}
  .edbar .ed-tx{flex:1 1 100%;order:2}
  .edbar .btn{order:3;margin-left:auto;font-size:16px}
  .ei-res{max-height:240px}
  .ei-add>input{font-size:16px}     /* dưới 16px là iPhone tự phóng to cả trang */
}

/* Khung xem trước lúc đang sửa: đổi màu đầu phiếu để không nhìn nhầm
   thành phiếu bán mới. Nút chính cũng đổi sang đỏ — bấm theo quán tính vào
   nút cam quen thuộc là ghi đè hóa đơn cũ mà không kịp nghĩ.
   b304 · đầu phiếu thành dải sáng một dòng (pos.css .tape-bar) nên "đang sửa" là nền CAM nhạt + chữ cam có cây bút
   ("Sửa HĐ … · bán …") — cả máy tính lẫn đầu ngăn kéo điện thoại (.gio-top.ed); nút đỏ giữ nguyên. */
.tape-bar.ed{background:var(--or-50);border-bottom-color:#F3C9A2}
.tape-bar.ed .tape-td,.gio-top.ed .tape-td{color:var(--or-safe)}
.btn.acc.big.ed{background:#B91C1C;border-color:#B91C1C;color:#fff}
.btn.acc.big.ed:hover{background:#991B1B;border-color:#991B1B}

/* ── b149, vá kèm: hai chỗ nhỏ trên iPhone ──────────────────────────────────
   Cả hai đều CÓ SẴN từ trước, không phải do bản sửa hóa đơn đẻ ra. Nhưng bản
   sửa làm chúng lộ ra thường xuyên nên vá luôn — đúng Sổ lỗi #10: "vá một chỗ
   thì hỏi ngay, chỗ kia có dính không".

   1. Ô ghi chú từng món (.ntin) đang 11,5px. Safari tự phóng to CẢ TRANG khi
      con trỏ vào ô dưới 16px và KHÔNG tự thu lại — đúng con bệnh anh Đạt báo
      ở b146. Lần đó vá Thuế GTGT với Giảm giá mà sót ô này vì nó chỉ hiện khi
      rê chuột, trên máy tính không ai thấy.
   2. Nút ↺ "trả về giá gốc" đang 19×19px, dưới mức 24px sờ được. Lúc bán
      thường nó chỉ hiện khi tự gõ đè giá nên ít gặp; lúc SỬA hóa đơn thì mọi
      dòng đều mang giá đã bán, tức là dòng nào cũng hiện nút này. */
@media (max-width:880px){
  .item .ntin{font-size:16px}
  .item .ntrow svg{width:14px;height:14px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   BẢN 150 — HỘP SỬA HÓA ĐƠN GỌN LẠI
   ═══════════════════════════════════════════════════════════════════════════
   Anh Đạt xem mẫu 20/08 rồi chốt: bỏ ô Giảm giá, Thuế GTGT, Thanh toán; hai
   khối chữ dài gom thành hai nút.

   NGUYÊN TẮC CỦA HỘP NÀY SAU BẢN 150: hộp Sửa chỉ lo HÀNG và KHÁCH. Giảm giá,
   thuế, hình thức trả tiền đều làm ở màn Bán hàng. Đừng nhét mấy ô đó về lại —
   nhét về là hộp dài ra, mà việc thì đã có chỗ làm tử tế hơn.

   BA CON SỐ BỊ BỎ Ô NHẬP VẪN PHẢI HIỆN RA BẰNG CHỮ ở dòng tổng (.eis-2).
   Giấu một con số tiền đi là kiểu lỗi tệ nhất: người bán tưởng hóa đơn không
   giảm giá, thực ra đang giảm 200 nghìn nằm im. Xóa dòng đó là phạm luật này. */
/* ── LUẬT MÀU CỦA HỘP NÀY ───────────────────────────────────────────────
   Mỗi màu mang MỘT nghĩa, dùng đúng nghĩa đó, không tô cho đẹp:
     XANH LÁ  dòng MỚI thêm vào · hàng còn tồn
     CAM      dòng ĐÃ SỬA số · số tiền khách trả · hàng sắp hết
     ĐỎ       dòng ĐÃ BỎ · nút bỏ dòng · hàng hết
     XÁM THAN khung sườn, số thứ tự các phần
   Dòng KHÔNG đụng gì thì để trắng — mắt chỉ phải nhìn chỗ đã đổi.
   Đừng thêm màu thứ năm. Thêm là hết phân biệt được. */

/* nhãn đánh số từng phần — thứ giúp mắt bám nhanh nhất, rẻ nhất */
/* Lề TRÊN 20px là bắt buộc, không phải cho đẹp: nhãn phần 3 nằm ngay dưới ô
   tìm hàng, không có lề thì hai thứ dán vào nhau và vòng cam lúc gõ đè lên
   chữ. Lề trên của phần 1 và 2 sẽ tự gộp với lề dưới của khối phía trước
   (margin collapsing), nên không đẻ thêm khoảng trống thừa ở hai chỗ đó. */
.ei-sec{display:flex;align-items:center;gap:8px;margin:20px 0 8px;
  font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--sky-600)}
.ei-sec i{font-style:normal;font-size:12px;font-weight:600;letter-spacing:.04em;
  text-transform:none;color:var(--red);background:var(--red-soft);padding:2px 7px;border-radius:99px}
.ei-no{flex:0 0 auto;width:19px;height:19px;border-radius:50%;background:var(--sky-800);color:#fff;
  display:grid;place-items:center;font-size:12px;font-weight:700;letter-spacing:0}

/* hai nút lối tắt — chip màu bên trong nói nghĩa của nút */
.ei-jump{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.ei-jump .btn{justify-content:flex-start;gap:9px;padding-left:8px}
.ei-jc{flex:0 0 auto;width:28px;height:28px;border-radius:var(--r-sm);display:grid;place-items:center}
.ei-jc svg{width:15px;height:15px}
.ei-j1 .ei-jc{background:var(--red-soft);color:var(--red)}      /* hàng đi ngược về kho */
.ei-j2 .ei-jc{background:var(--or-50);color:var(--or-7)}        /* đi bán tiếp */
.ei-j1:hover{border-color:var(--red)} .ei-j2:hover{border-color:var(--or-6)}
/* b152: đã bỏ dòng nhắc .ei-jh. Nghĩa của hai nút nay nằm trong thuộc tính
   title — rê chuột vào là hiện. Cần nói lại thì để trong title, đừng đắp thêm
   một dòng chữ xám nữa: chữ xám mà lần nào cũng hiện thì không ai đọc. */
.ei-jump{margin-bottom:16px}

/* bảng dòng hàng */
#ei_rows .eir>td{padding:9px 8px;border-bottom:1px solid var(--line-2);vertical-align:middle}
#ei_rows .eir:hover>td{background:var(--sky-50)}
/* KHÔNG BAO GIỜ đặt display:flex thẳng lên thẻ <td>. Trình duyệt lôi nó ra
   khỏi bảng rồi bọc vào một ô vô danh — nền và đường kẻ đứt một khoảng ngay
   cạnh cột đó, nhìn như bảng bị vỡ. Flex phải nằm trong một <span> bên trong. */
.ei-tnc{max-width:0;width:38%}
.ei-tn{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.ei-tn .nm{font-weight:600}
.ei-dv{color:var(--slate-2);font-size:13px}
.ei-tt{font-weight:700;font-family:var(--f-mono);font-size:13.5px}
/* ô nhập được thì có nền — ô chỉ để đọc thì không. Nhìn là biết chỗ nào gõ được. */
.ei-in{width:76px;text-align:right;padding:5px 8px;background:var(--sky-50);
  border:1px solid var(--line);border-radius:var(--r-sm);font-family:var(--f-mono);font-size:13px}
.ei-in.wide{width:98px}
.ei-in:focus{background:#fff;border-color:var(--sky-500)}

/* ba trạng thái, ba màu — vạch dọc bên trái là thứ mắt bắt trước cả chữ */
.ei-tag{font-size:12px;font-weight:700;letter-spacing:.02em;padding:2px 7px;border-radius:99px;white-space:nowrap}
.ei-cu{font-size:12px;color:var(--slate-2);text-decoration:line-through;font-variant-numeric:tabular-nums}
#ei_rows .eir.moi>td:first-child{box-shadow:inset 3px 0 0 var(--green)}
#ei_rows .eir.moi>td{background:var(--green-soft)}
.ei-tag.moi{background:var(--green);color:#fff}
#ei_rows .eir.sua>td:first-child{box-shadow:inset 3px 0 0 var(--or-6)}
#ei_rows .eir.sua>td{background:var(--or-50)}
.ei-tag.sua{background:var(--or-safe);color:#fff}
#ei_rows .eir.bo>td:first-child{box-shadow:inset 3px 0 0 var(--red)}
#ei_rows .eir.bo>td{background:var(--red-soft)}
#ei_rows .eir.bo .nm,#ei_rows .eir.bo .ei-tt{text-decoration:line-through;color:var(--slate-2)}
.ei-tag.bo{background:var(--red);color:#fff}
.ei-del:hover{background:var(--red-soft);color:var(--red)}
.ei-undo{background:var(--red-soft);color:var(--red)}
.ei-undo:hover{background:var(--red);color:#fff}

/* ô tìm hàng */
.ei-add{margin-top:16px}
.ei-add>label{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:650;
  color:var(--sky-600);margin-bottom:6px}
.ei-add>label svg{width:14px;height:14px}
.ei-ton{font-weight:650;padding:1px 6px;border-radius:99px}
.ei-ton.con{background:var(--green-soft);color:var(--green)}
.ei-ton.sap{background:var(--or-50);color:var(--or-safe)}
.ei-ton.het{background:var(--red-soft);color:var(--red)}

/* thẻ tổng tiền — nền xám than, số cam. Giống hệt thanh KHÁCH TRẢ ở màn Bán
   hàng nên mắt quen sẵn; và cam trên xám than đo được 5,61:1, đạt chuẩn AA. */
.ei-sum{margin-top:14px;background:var(--sky-800);border-radius:var(--r);padding:12px 14px;color:#fff}
.eis-hd{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.eis-l{flex:1;min-width:0;font-size:12px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--sky-300)}
.eis-l b{color:#fff}
.eis-v{font-size:21px;font-weight:800;color:var(--or);font-family:var(--f-mono);letter-spacing:-.02em}
.eis-d{font-weight:700;font-size:12px;padding:2px 8px;border-radius:99px}
.eis-d.up{background:var(--or-50);color:var(--or-safe)}
.eis-d.dn{background:var(--green-soft);color:var(--green)}
/* KHÔNG dùng font mono cho dòng có CHỮ TIẾNG VIỆT. JetBrains Mono không dựng
   được dấu, "Tiền" ra "Tiêǹ", "sửa" ra "sưả" — nhìn như trang bị lỗi phông.
   Mono chỉ dành cho ô toàn số: .ei-in, .ei-tt, .eis-v. */
.eis-2{margin-top:7px;padding-top:7px;border-top:1px solid rgba(255,255,255,.14);
  font-size:12px;color:var(--sky-300);font-variant-numeric:tabular-nums}
.eis-3{margin-top:3px;font-size:12px;color:var(--sky-400);line-height:1.5}
.eis-3 i{font-style:normal;opacity:.9}

@media (max-width:880px){
  .ei-jump{grid-template-columns:1fr}
  .ei-in{width:70px;font-size:16px} .ei-in.wide{width:92px;font-size:16px}
  .eis-v{font-size:19px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   BẢN 150 — DANH SÁCH HÓA ĐƠN: MỌI DÒNG CAO BẰNG NHAU
   ═══════════════════════════════════════════════════════════════════════════
   Luật của khối này, đừng phá:

   1. MỖI DÒNG ĐÚNG HAI HÀNG CHỮ. Chiều cao ghim cứng 62px. Muốn thêm thông
      tin thì thay chữ trong hai hàng đó, TUYỆT ĐỐI không đẻ hàng thứ ba —
      một dòng cao lên là gãy nhịp cả danh sách, mắt phải rà lại từ đầu.
   2. BÁO CHUYỆN KHÁC THƯỜNG BẰNG MÀU CHỮ SẴN CÓ, không bằng thẻ mới.
      Còn nợ  -> chấm cam đầu dòng + dòng dưới cột tiền đổi sang đỏ.
      Đã sửa  -> dấu bút chì mờ cạnh số hóa đơn.
      Cả hai đều nằm lọt trong hai hàng, nên chiều cao không đổi.
   3. DÙNG LƯỚI, KHÔNG DÙNG <table>. Ô bảng cao theo nội dung dài nhất nên
      không ghim được; lưới thì ghim được. Tiện thể hết luôn cái bẫy
      display:flex trên thẻ <td>.
   4. HÀNG BÌNH THƯỜNG KHÔNG ĐEO GÌ CẢ. Chín trên mười hóa đơn là bình
      thường — tô hết thì màu mất nghĩa, mà đó mới đúng là lúc cần màu. */

.ipanel{padding:0;overflow:hidden}
.ilist{display:flex;flex-direction:column}
/* Một chỗ khai bề ngang cột cho CẢ đầu bảng lẫn mọi dòng — hai chỗ khai riêng
   là có ngày lệch nhau mà không ai để ý. */
.ilist .ihead,.ilist .irow{
  display:grid;align-items:center;
  grid-template-columns:22px 132px minmax(0,1fr) 156px 78px;
  gap:0 14px;padding:0 16px 0 4px}

.ilist .ihead{height:38px;border-bottom:1px solid var(--line);
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--slate-2)}
.ilist .ihead .r{text-align:right}

.ilist .irow{height:62px;border-bottom:1px solid var(--line-2);cursor:pointer;
  background:none;border-left:0;border-right:0;border-top:0;width:100%;text-align:left;
  font:inherit;color:inherit;transition:background .12s}
.ilist .irow:hover{background:var(--sky-50)}
.ilist .irow:focus-visible{outline:2.5px solid var(--or-safe);outline-offset:-3px}
.ilist .irow:last-of-type{border-bottom:0}

/* hai hàng chữ — cùng một khuôn cho cả ba cột, nên chúng thẳng hàng nhau */
.ic1,.ic2,.ic3{min-width:0;display:block;line-height:1.3}
.ic1 b,.ic2 b,.ic3 b{display:block;font-size:14px;font-weight:650;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* b262 · Dòng hóa đơn đổi vai: TÊN HÀNG lên dòng chính (thứ duy nhất phân biệt
   các dòng), tên khách xuống dòng phụ. "Khách lẻ" lặp ở mọi dòng nên để nhạt;
   khách CÓ TÊN thì đậm hơn một nấc — đó mới là thông tin. */
.ic2 i.kh{color:var(--ink-2);font-weight:600}
.ic1 i,.ic2 i,.ic3 i{display:block;font-style:normal;font-size:12px;color:var(--slate-2);
  margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-height:15px}
.ic3{text-align:right}
.ic3 b{font-size:14.5px;font-weight:700}

/* chấm báo còn nợ — 7px, nằm gọn trong hàng, không đẩy gì đi đâu */
.idot{width:7px;height:7px;border-radius:50%;background:transparent;margin-left:9px}
.irow.no .idot{background:var(--or)}
.ic3 i.no{color:var(--red);font-weight:650}

/* Dấu bút chì "đã sửa" — nhỏ, mờ, nằm NGAY TRONG dòng số hóa đơn.
   Đừng dùng position:absolute cho nó: bỏ absolute ra thì nó tự tìm chỗ, còn
   để absolute mà quên khai left/right là nó rơi xuống dòng dưới, mất tăm. */
.ic1 b{display:flex;align-items:center;gap:5px}
.ic1 b>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ic1 .ised{display:inline-flex;flex:0 0 auto;color:var(--slate-2);opacity:.8}
.ic1 .ised svg{width:11px;height:11px}

/* hai nút im lặng, chỉ đậm lên khi rê chuột. Cố ý KHÔNG ẩn hẳn: màn cảm ứng
   không có rê chuột, ẩn là nhân viên không tìm ra nút. */
.iact{display:flex;gap:2px;justify-content:flex-end}
/* Màu nghỉ phải là --sky-400 (3,2:1), KHÔNG được dùng --sky-300 (2,0:1) —
   dưới mốc 3:1 cho thành phần bấm được. Mờ là để nó im lặng, không phải để
   nó biến mất. */
.iact .icobtn{width:30px;height:30px;color:var(--sky-400)}
.irow:hover .iact .icobtn{color:var(--slate)}
.iact .icobtn:hover{background:var(--sky-100);color:var(--ink)}

.ifoot{display:flex;align-items:center;justify-content:space-between;gap:16px;
  height:48px;padding:0 16px 0 26px;border-top:1px solid var(--line);background:var(--sky-50);
  font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--slate-2)}
.ifoot strong{font-size:16px;letter-spacing:0;text-transform:none;color:var(--ink)}

/* thanh chọn ngày thay cho dãy 5 chip cũ */
.itool{gap:10px}
.idate{display:flex;align-items:center;gap:6px;margin-left:auto}
.ilb{font-size:12.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--slate-2)}
.idate input[type=date]{width:auto;padding:7px 9px;font-size:13px}
.idate .o-ngay-k>input.o-ngay{padding:7px 31px 7px 9px;font-size:13px}   /* b324 · chữ dd/mm/yyyy đè đúng chỗ chữ ô gốc b322 */
.idate .o-ngay-ic{right:9px}
.idate .o-ngay-k{width:auto}
/* b324 · anh Đạt 28/09: máy tính mỗi ngày một ô, cao BẰNG ô tìm cùng hàng (b322 lệch 1px, chữ LỚN lệch 3px).
   Ô tìm = dòng 1,45 × cỡ chữ ô nhập (14px · LỚN 15px) + đệm 16 + viền 2; ô ngày giữ chữ 13px nên đặt cao theo đúng số đó. */
@media (min-width:881px){
  .itool .idate input[type=date]{height:calc(14px * 1.45 + 18px)}
  body.big .itool .idate input[type=date]{height:calc(15px * 1.45 + 18px)}
}
/* b242 · mỗi ô ngày nay bọc trong <label class=idf> để ĐIỆN THOẠI có nhãn chữ.
   Máy tính giữ y nguyên: `display:contents` cho ô date vẫn là con trực tiếp của
   thanh flex, nhãn phụ ẩn đi. Không lệch một pixel nào so với b241. */
.idf{display:contents}
.idf>span:not(.o-ngay-k){display:none}
.idash{color:var(--slate-2)}
.ixoa{width:32px;height:32px;flex:0 0 auto;border:1px solid var(--line);background:var(--paper);
  border-radius:var(--r-sm);color:var(--slate-2);cursor:pointer;display:grid;place-items:center}
.ixoa:hover{border-color:var(--red);color:var(--red)}
.ixoa svg{width:13px;height:13px}

@media (max-width:880px){
  /* Điện thoại: thẻ ba cột không nhét vừa 390px — xếp thành thẻ, nhưng vẫn
     giữ đúng luật: mọi thẻ cao bằng nhau. */
  .ilist.ph{gap:var(--space-2);background:none}

  /* ══════ b242 · THẺ HÓA ĐƠN ĐIỆN THOẠI — DỰNG LẠI THEO ĐƯỜNG CHÂN CHỮ ══════
     Anh Đạt 16/09: "chữ cao chữ thấp nhìn k dễ chịu".
     Đo chân chữ bằng `<span>` RỖNG `inline-block;width:0;height:0;overflow:
     hidden` — ô như vậy lấy mép dưới làm chân chữ nên trình duyệt đặt nó đúng
     trên chân chữ của dòng. (Nhét chữ 'X' vào đo là SAI: ra mép hộp dòng.)
     b241 chưa vá — chỗ đáng lẽ MỘT hàng có tới BỐN chân chữ, trải 18,1px:
       HD-000003 14,5px/650/Mono y=229,3 · ngày 11,5/400/BVP y=228,3 ·
       62.000 15,5px/700/Mono y=220,8 · Tiền mặt 11,5/400 y=238,9.
     SAU KHI VÁ: cùng y=250,7 / y=274,5 — lệch 0,0px. Thẻ thấp lại 84→69px.
     Gốc: `.ic1 b` và `.ic1 i` canh `vertical-align:middle` — canh TÂM HỘP, hai
     hộp khác cỡ chữ thì tâm trùng mà chân chữ lệch; `.ic3` là khối riêng.
     VÁ: (1) `.ic3{display:contents}` để tiền lên đúng hàng số hóa đơn, hình
     thức trả xuống hàng tên khách; (2) `align-items:baseline`; (3) cỡ chữ về
     thang 11,5 · 12,5 · 14 · 16 — bỏ 13,5 · 14,5 · 15,5px và độ đậm 650. */
  .ilist.ph .irow{height:auto;min-height:0;display:grid;
    grid-template-columns:minmax(0,1fr) auto;
    align-items:baseline;gap:var(--space-1) var(--space-2);
    padding:var(--space-3);background:var(--paper);
    border:1px solid var(--line);border-radius:var(--r)}
  .ilist.ph .irow .idot{display:none}   /* b296 · cột chấm 10px+8px trống ở MỌI thẻ; nợ đã hiện bằng chữ "còn nợ" cột tiền */

  .ilist.ph .ic1{grid-column:1;grid-row:1;
    display:flex;align-items:baseline;gap:var(--space-2);min-width:0}
  .ilist.ph .ic1 b{display:block;font-size:14px;font-weight:700;flex:0 0 auto}
  .ilist.ph .ic1 i{display:block;font-size:12.5px;font-weight:400;margin:0;
    min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* `display:contents`: hai con của `.ic3` thành ô lưới; chữ vẫn nằm trong nó
     nên trình đọc màn hình đọc y cũ. */
  .ilist.ph .ic3{display:contents}
  .ilist.ph .ic3 b{grid-column:2;grid-row:1;font-size:16px;font-weight:800;
    text-align:right;white-space:nowrap}

  /* 🔴 b242 · "chữ trong ô sản phẩm vẫn dư chạy ra ngoài". Hóa đơn 6 món tên
     dài: thẻ rộng 364px mà RUỘT 599px (thẻ `<i>` tên hàng 493px chạy tới x=613,
     mép phải thẻ ở 377) ⇒ cuộn ngang, kéo một cái là số hóa đơn và ngày biến
     mất. Anh Đạt chốt: "gần hết chỗ thì để dấu ...". `min-width:0` bắt buộc —
     ô lưới mặc định `min-width:auto`, thiếu nó `overflow:hidden` vô nghĩa. */
  .ilist.ph .ic2{grid-column:1;grid-row:2;text-align:left;
    display:flex;align-items:baseline;gap:var(--space-2);
    min-width:0;white-space:nowrap;overflow:hidden}
  .ilist.ph .ic2 b{display:block;font-size:14px;font-weight:700;flex:0 1 auto;min-width:0}   /* b296: co lại + "…" (trước bị cắt cụt giữa chữ) */
  .ilist.ph .ic2 i{display:block;font-size:12.5px;font-weight:400;margin:0;flex:0 0 auto;max-width:45%;
    min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}   /* tên khách giữ tới 45% — trước còn "Kh…" */
  .ilist.ph .ic3 i{grid-column:2;grid-row:2;font-size:12px;font-weight:600;
    text-align:right;white-space:nowrap}
  .ilist.ph .irow:last-of-type{border-bottom:1px solid var(--line)}
  .ifoot{border-radius:var(--r);border:1px solid var(--line);margin-top:10px;padding:0 14px}
  .itool{flex-wrap:wrap}
  /* b231+ · 15/09: hàng NGÀY TRÀN 43px trên máy 390px. Ô date có bề rộng nội tại
     150px, mà flex item mặc định là min-width:auto nên `flex:1` KHÔNG co được —
     đo trên Chromium 390x844: ruột 415px nhét trong khung 366px, nút xóa văng
     hẳn ra ngoài và kéo lệch cả trang, nên thẻ hóa đơn bên dưới bị cắt mất chữ
     đầu. Hai triệu chứng, một lỗi.
     Vá: xuống hai hàng — nhãn một hàng, hai ô chia đôi hàng dưới, bỏ dấu gạch
     ngang (hai ô cạnh nhau đã tự nói lên là một khoảng). Ô rộng 155px.
     Chỉ thêm min-width:0 mà giữ một hàng thì ô còn 128,6px — vẫn hết tràn,
     nhưng chữ dd/mm/yyyy ở cỡ 16px bắt buộc sẽ rất sát. */
  .idate{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    column-gap:var(--space-2);row-gap:var(--space-1);
    width:100%;margin-left:0}
  /* Hàng 1: nhãn NGÀY bên trái, nút bỏ chọn bên phải — nút không còn là cột thứ
     ba của hàng ô, nên không cách nào đẩy ô ngày tràn ra ngoài được nữa.
     Hàng 2: hai ô chia đôi, mỗi ô có nhãn chữ riêng. */
  .ilb{grid-column:1;grid-row:1;align-self:center}
  .ixoa{grid-column:2;grid-row:1;justify-self:end}
  .idash{display:none}
  /* 🔴 b242 · anh Đạt 16/09: "ô ngày quá xấu, k hề có tính chất UI, chữ bị đẩy
     ra ngoài". Lỗi gốc: iPhone vẽ input[type=date] RỖNG là một hộp TRẮNG TRƠN —
     không chữ gợi ý, không dd/mm/yyyy, không gì cả. Hai hộp trắng cạnh nhau
     dưới chữ NGÀY thì không ai đoán được hộp nào là "từ", hộp nào là "đến".
     Vá: mỗi ô thành một trường có nhãn chữ riêng, nhãn nằm TRONG khung cùng ô,
     nên hộp rỗng vẫn tự nói ra nó là gì. */
  .idf{display:grid;grid-row:2;grid-template-columns:minmax(0,1fr);gap:3px;min-width:0;
    border:1px solid var(--line);border-radius:var(--r-sm);
    background:var(--paper);padding:5px 10px 6px}
  .idf.idf-tu{grid-column:1}
  .idf.idf-den{grid-column:2}
  .idf>span:not(.o-ngay-k){display:block;font-size:12px;font-weight:700;letter-spacing:.06em;
    text-transform:uppercase;color:var(--slate-2);line-height:1}
  .idate input[type=date]{min-width:0;width:100%;font-size:16px;
    border:0;background:none;padding:0;height:22px;line-height:22px}
  /* b324 · anh Đạt 28/09: trả dáng b322 — nhãn TỪ NGÀY / ĐẾN NGÀY + ngày + biểu tượng lịch nhỏ cùng MỘT khung (~50px, không hộp nút 44px
     riêng như b323). Ô chữ dd/mm/yyyy của ngayVN phủ đúng ô gốc cao 22px; chạm chỗ nào trong khung (cả chữ nhãn) cũng mở lịch. */
  .idate .idf .o-ngay-k>input.o-ngay,.idate .idf .o-ngay-k>input.o-ngay:focus{border:0;padding:0 26px 0 0;font-size:16px;box-shadow:none;outline:none}
  .idf .o-ngay-ic{right:0}
  .idate .o-ngay-k{width:100%}
  .idate input[type=date]:focus{outline:none}
  .idf:focus-within{border-color:var(--sky-600)}
}

/* ── b152: danh sách hóa đơn giãn ra lấp đầy trang ──────────────────────────
   Anh Đạt: "phóng to phần hóa đơn cho fix với trang, giữ 8 hóa đơn là được."

   Trước: mỗi dòng cao cứng 62px, 8 dòng hết ~700px, màn 1080 còn dư một mảng
   trắng to ở dưới. Chữ thì nhỏ mà chỗ thì thừa.

   Nay: DÙNG FLEX CHO NÓ TỰ CHIA, không đoán số pixel. Chuỗi co giãn chạy từ
   .view xuống tận từng dòng, mỗi khâu đều phải có min-height:0 — thiếu một
   chỗ là cả chuỗi đứt, flex item không co nhỏ hơn nội dung được.
     .view  ->  #itbl  ->  .ipanel  ->  .ilist  ->  .irow

   Chặn hai đầu: KHÔNG dưới 62px (màn thấp thì cho cuộn, đừng bóp chữ dính
   nhau) và KHÔNG quá 104px (màn 2K mà mỗi dòng cao bằng bàn tay thì trống
   huếch, đọc còn mệt hơn).

   Vẫn ĐÚNG 8 hóa đơn mỗi trang — IPP không đổi. */
.view:has(.ilist){display:flex;flex-direction:column}
.view:has(.ilist) .itool{flex:0 0 auto}
.view:has(.ilist) #itbl{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}
#itbl .ipanel{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}
#itbl .ipanel .ilist{flex:1 1 auto;min-height:0;overflow:auto}
#itbl .ipanel .ihead,#itbl .ipanel .ifoot{flex:0 0 auto}
#itbl .ipanel .irow{flex:1 1 0;min-height:62px;max-height:104px}
#itbl .pgbar{flex:0 0 auto;margin-top:12px}
/* Dòng cao lên thì chữ cũng nở theo một chút cho cân — nhưng KHÔNG đụng tới
   cỡ chữ chung của app (luật b147/b148: không đổi font, cỡ chữ, kích thước). */
#itbl .ipanel .ic1 b,#itbl .ipanel .ic2 b{font-size:14.5px}
#itbl .ipanel .ic3 b{font-size:15.5px}

@media (max-width:880px){
  /* Điện thoại: thẻ xếp dọc và cuộn bình thường, đừng ép giãn. */
  .view:has(.ilist){display:block}
  #itbl .ilist.ph .irow{flex:0 0 auto;min-height:0;max-height:none}
  /* 🔴 Hai dòng `#itbl .ipanel .icN b` ở trên nới cỡ chữ cho dòng giãn theo
     chiều cao màn — CHỈ đúng trên máy tính. Chúng mang ID nên đặc tả 1,2,1,
     đè cả `.ilist.ph .ic1 b` (0,3,1) của khối điện thoại, nên đo ra 14,5px và
     15,5px trong khi khối kia viết 14px và 16px. Điện thoại không có chuyện
     dòng giãn theo màn, nên trả cỡ chữ về đúng thang nhận diện.
     Bài học lặp lại lần thứ ba trong b242: đặc tả cao hơn thì đứng trước vẫn
     thắng — phải đi tìm kẻ đang thắng, đừng viết thêm một dòng nữa rồi mong. */
  #itbl .ipanel .ic1 b,#itbl .ipanel .ic2 b{font-size:14px}
  #itbl .ipanel .ic3 b{font-size:16px}
}

/* ===== SOURCE: styles/trang-thai.css ===== */
/* ============================================================
   TRẠNG THÁI MÁY CHỦ · GIẢM CHUYỂN ĐỘNG — huy hiệu Online/Offline ở chân thanh bên, chấm
   đường truyền (b240 · b284), và luật giảm chuyển động của hệ điều hành cho toàn app.
   b299: tách nguyên văn đuôi workflows.css; đứng sau hoa-don.css để thứ tự cascade giữ y nguyên.
   ============================================================ */
/* Trạng thái nguồn dữ liệu máy chủ; không thay đổi font hoặc thang chữ của app. Bố cục chân thanh .rail-ft ở foundation.css. */
.server-mode{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:800;letter-spacing:.06em;border-radius:999px;padding:3px 5px;background:#E8EDF2;color:#52606D}
.server-mode.online{background:#DDF4E7;color:#167348}
.server-mode.offline{background:#FCE4DE;color:#A52C24}
.server-mode.local{background:#EEF0F3;color:#626A75}
/* b240 · CHẤM ĐƯỜNG TRUYỀN — anh Đạt 14/09: "chỉ cần xanh lá, cam, đỏ là được".
   Chấm nói CHẤT LƯỢNG ĐƯỜNG, nền huy hiệu vẫn nói TRẠNG THÁI MÁY CHỦ như cũ —
   hai thứ khác nhau, đừng gộp: máy chủ online mà đường chậm là có thật.
   Màu lấy đúng thang nhận diện: xanh #167348 · cam #B4690E · đỏ #A52C24.
   Không dùng MÌNH màu để báo (người mù màu đỏ–lục không phân biệt được):
   kèm aria-label và title bằng chữ, và chấm đỏ có viền trong cho khác hình. */
.sm-cham{width:6px;height:6px;border-radius:50%;flex:0 0 auto;background:currentColor}
.server-mode.dt-tot .sm-cham{background:#167348}
.server-mode.dt-cham .sm-cham{background:#B4690E}
.server-mode.dt-mat .sm-cham{background:#A52C24;box-shadow:inset 0 0 0 1.5px #FCE4DE}
.server-mode.dt-local .sm-cham{background:#8A94A0}
.sm-ms{font-style:normal;font-weight:600;opacity:.72;letter-spacing:0;font-variant-numeric:tabular-nums}
/* b284 · chân thanh bên rộng 52px: "Online 1" + "7ms" xếp thành HAI dòng, tràn khỏi cột
   (soi ảnh 21/09). Số mili giây vẫn còn trong tooltip và ở màn Quản lý — chỗ người ta thật
   sự đi tra. Ở thanh bên chỉ cần biết CÒN NỐI hay KHÔNG. */
.rail-ft .sm-ms{display:none}
@media (prefers-reduced-motion:no-preference){.sm-cham{transition:background .2s ease}}

/* Tôn trọng thiết lập giảm chuyển động của hệ điều hành trên toàn app. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{scroll-behavior:auto!important;animation-duration:.01ms!important;
    animation-iteration-count:1!important;transition-duration:.01ms!important}
}

/* ===== SOURCE: styles/khach-hang.css ===== */
/* ═══════════════════════════════════════════════════════════════════════════
   DẢI KHÁCH HÀNG Ở MÀN BÁN — tách khỏi workflows.css ngày 16/09/2026 (b244)
   ═══════════════════════════════════════════════════════════════════════════
   Tách ra vì hai lẽ, không phải để lách trần dòng:
     · `workflows.css` đã thành cái rổ đựng chung (hóa đơn, công nợ, ngày tháng,
       khách hàng…) — sửa một chỗ phải đọc cả tệp;
     · phần khách hàng vừa đổi luật gốc (b243–b244: SỐ ĐIỆN THOẠI là chìa, TÊN
       chỉ để tìm), sẽ còn được đụng tới, nên cho nó chỗ riêng có tên.
   Nạp NGAY SAU `workflows.css` trong `styles/manifest.json` để giữ nguyên thứ
   tự đè như trước khi tách.

   LUẬT của dải này (b247, anh Đạt chốt 17/09: *"CÓ số thì k trùng"* — đúng luật
   KiotViet):
     · SỐ ĐIỆN THOẠI là chìa nhận diện khách — KHÔNG bắt buộc, nhưng đã điền thì
       không được trùng ai;
     · TÊN chỉ để TÌM, KHÔNG để GÁN. App không bao giờ tự gán khách theo tên;
       gõ tên ra gợi ý, người bán bấm mới gán.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── b151: tự lưu khách khi bán ─────────────────────────────────────────
   Ô tích CHỈ hiện khi nó thật sự sắp làm gì đó — có đủ tên và số mà chưa gán
   khách. Hiện lúc nào cũng thấy thì thành thứ trang trí, người bán nhìn quen
   rồi thôi không đọc nữa. */
.kh-luu{display:flex;align-items:center;gap:8px;margin-top:7px;padding:6px 8px;
  border-radius:var(--r-sm);background:var(--sky-50);cursor:pointer;
  font-size:12px;color:var(--slate);line-height:1.4}
.kh-luu input{width:16px;height:16px;flex:0 0 auto;accent-color:var(--or-6);margin:0}
.kh-luu b{color:var(--ink);font-weight:650}
.kh-luu:hover{background:var(--sky-100)}

/* ── b304 · THẺ KHÁCH trên phiếu ──────────────────────────────────────────
   Đã gán khách thì hai ô gõ (tên + số, 44px trên điện thoại) nhường chỗ cho MỘT THẺ: tên · hạng giá / số · nợ.
   Bấm thẻ = gõ lại tên / số ngay tại chỗ (pos.js khachSuaMo — mọi luật b243/b244 ở chỗ gõ đó), ✎ = sửa khách trong
   sổ, ✕ = bỏ chọn. Cùng nền + vạch trái với dải hai ô (.cust-band, pos.css) — nhìn là biết cùng một chỗ. */
.custline{display:flex;align-items:center;gap:4px;min-height:46px;padding:5px 4px 5px 10px;
  background:#EEF5F8;border-left:3px solid #315C73;border-radius:8px}
.kh-the{flex:1 1 auto;align-self:stretch;min-width:0;display:flex;align-items:center;gap:8px;padding:0;
  text-align:left;font-size:13px;color:var(--ink)}
.kh-av{flex:0 0 auto;width:28px;height:28px;display:grid;place-items:center;border-radius:50%;background:#fff;color:#315C73}
.kh-av svg{width:15px;height:15px}
.kh-chu{flex:1 1 auto;min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:1px 6px}
.kh-the b{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:700}
.kh-the:hover b{color:var(--sky-700)}
.kh-the .tag{flex:0 0 auto;padding:1px 7px;font-size:12.5px}
.kh-the [hidden]{display:none}   /* nợ đang hỏi máy chủ: .tag là inline-block, không có dòng này thì hiện ô rỗng */
.kh-so{flex:1 0 100%;display:flex;align-items:center;gap:6px;font-size:12.5px;font-weight:500;color:var(--slate)}
.kh-sua,.kh-bo{flex:0 0 auto;width:30px;height:30px;display:grid;place-items:center;border-radius:7px;color:var(--slate)}
.kh-sua:hover,.kh-bo:hover{background:#fff;color:var(--ink)}
.kh-sua svg,.kh-bo svg{width:15px;height:15px}

/* Tên vừa gõ khác tên trong sổ — mời đổi bằng một cú bấm, KHÔNG tự đổi.
   Gõ tắt "Ba" một lần là ghi đè mất "Anh Ba Thợ Hồ" đã lưu công phu. */
/* b243 · HAI ĐƯỜNG cho cảnh "tên gõ khác tên trong sổ" — trước chỉ có đường đổi
   tên khách cũ, nên gặp khách mới trùng một phần tên là kẹt. Hai nút này ĐỔI DỮ
   LIỆU KHÁCH nên phải bấm có chủ ý: nút thật, đủ `--control-h` trên điện thoại
   và mỗi nút một hàng — hai chữ gạch chân 11,5px dính nhau ở 390px là đúng cảnh
   bấm nhầm, mà bấm nhầm ở đây là đổi tên nhầm một khách. Màu bỏ
   `var(--blue-2,#1C5A8F)`: `--blue-2` là biến CỦA WEB, app không khai, chỉ chạy
   nhờ màu dự phòng (tờ nhận diện mục 1) — dùng `--sky-700`, 12,67:1 trên trắng.
   Nút "người khác" là đường an toàn (không đụng khách cũ) nên cho nổi hơn. */
.kh-doi{margin-top:var(--space-2);font-size:12.5px;color:var(--slate-2);line-height:1.45;
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2)}
.kh-doi b{color:var(--ink);font-weight:700}
.kh-doi button{flex:0 0 auto;min-height:32px;padding:6px 12px;cursor:pointer;
  font:inherit;font-weight:700;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--paper);color:var(--sky-700)}
.kh-doi button:hover{border-color:var(--sky-500);background:var(--sky-50)}
/* b244 · DÒNG GỢI Ý khách quen. Tên chỉ để TÌM, không để GÁN (luật KiotViet)
   nên đây là LỜI MỜI, bấm mới gán. Cùng kiểu nút với `.kh-doi`. */
.kh-goi{margin-top:var(--space-2);font-size:12.5px;color:var(--slate-2);
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-2)}
.kh-goi button{flex:0 0 auto;min-height:32px;padding:6px 12px;cursor:pointer;
  font:inherit;font-weight:700;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--paper);color:var(--sky-700)}
.kh-goi button:hover{border-color:var(--sky-500);background:var(--sky-50)}
/* b304 · điện thoại: chỗ bấm 44px như mọi nút khác của phiếu (trước 40px = --control-h) */
@media (max-width:880px){ .kh-goi button{min-height:44px} }
@media (max-width:880px){
  .kh-doi{flex-direction:column;align-items:stretch}
  .kh-doi button{min-height:44px;width:100%}
}

@media (max-width:880px){ .kh-luu{font-size:13px} .kh-luu input{width:20px;height:20px} }

/* ===== SOURCE: styles/mobile-runtime.css ===== */
/* ═══════════════ b164 — ĐIỆN THOẠI: LỀ AN TOÀN + BÀN PHÍM ═══════════════
   Anh Đạt báo 25/08: "bàn phím của điện thoại ảnh hưởng tầm nhìn app, khi tắt
   bàn phím xuống thì tạm ổn." Anh dùng kiểu ĐÃ THÊM VÀO MÀN HÌNH CHÍNH — không
   còn thanh địa chỉ che, nên cả hai lỗi dưới đây lộ rõ nhất ở kiểu đó.

   HAI nguyên nhân, phải trị đủ cả hai:

   1. LỀ AN TOÀN. index.html bật `viewport-fit=cover` và status bar
      `black-translucent` — tức đã bảo iOS cho nội dung tràn ra tận mép máy.
      Nhưng CSS chưa dùng env(safe-area-inset-*) một lần nào (đếm được 0 trong
      cả cây 81 file), nên thanh 5 nút nằm đè lên vạch home — dải iOS giữ riêng
      cho cử chỉ vuốt, bấm hay không ăn — và đầu trang chui lên dưới đồng hồ.

   2. BÀN PHÍM. Bàn phím iOS làm màn hình NHÌN THẤY co lại, nhưng khung layout
      thì KHÔNG. Nên `height:100vh` và `position:fixed;bottom:0` vẫn tính theo
      cả màn hình: thanh 5 nút, thanh đơn-đang-theo-dõi và dòng thông báo rơi
      ra sau lưng bàn phím, còn vùng cuộn `.view` thì kéo dài xuống dưới bàn
      phím nên ô đang gõ trôi khỏi tầm nhìn.
      ⚠️ `100dvh` KHÔNG chữa được — iOS cố ý loại bàn phím khỏi mọi đơn vị
      viewport. Chỉ `visualViewport` đo được, app.js đặt --vvh và --kb.
      Máy nào không có visualViewport thì hai biến đó vắng mặt và mọi dòng
      dưới đây rơi về đúng giá trị cũ — không hỏng gì.

   ĐỪNG hạ cỡ chữ ô nhập xuống dưới 16px: chuyện iPhone tự phóng to đã trị từ
   b146, khối ở trên. Hai chuyện khác nhau, đừng gộp.
   Bài kiểm bắt buộc trên MÁY THẬT (Sổ lỗi #27): trang "Thước đo iPhone". */

@media (max-width:880px){
  /* ---- 1 · lề an toàn ---- */
  .app{padding-top:env(safe-area-inset-top)}
  html.co-ban-thu .app{padding-top:calc(24px + env(safe-area-inset-top))}
  html.co-ban-thu .ban-thu{top:env(safe-area-inset-top)}
  html.co-dai-thu .app{padding-top:calc(24px + env(safe-area-inset-top))}
  html.co-dai-thu .dai-thu{top:env(safe-area-inset-top)}
  /* b278 · thân màn chừa đúng thanh điều hướng (+8px); màn Bán hàng chừa thêm thanh giỏ.
     Thanh trang màn Sản phẩm là sticky TRONG vùng cuộn nên tự chiếm chỗ, không cần chừa. */
  .view{padding-bottom:calc(var(--h-rail) + 8px + env(safe-area-inset-bottom))}
  .view.pos{padding-bottom:calc(var(--h-rail) + var(--h-bar) + 8px + env(safe-area-inset-bottom))}
  .pos3{padding-bottom:calc(var(--h-rail) + var(--h-bar) + 8px + env(safe-area-inset-bottom))}

  /* ---- 2 · bàn phím ---- */
  .app{height:var(--vvh,100dvh)}
  .rail{bottom:var(--kb,0px)}
  /* b278 · thông báo và dải "phiếu đang gửi" đứng TRÊN hai thanh dính đáy, không đè lên. */
  .sale-follow{bottom:calc(var(--h-rail) + var(--h-bar) + 6px + var(--kb,0px) + env(safe-area-inset-bottom))}
  .toasts{bottom:calc(var(--h-rail) + var(--h-bar) + 10px + var(--kb,0px) + env(safe-area-inset-bottom))}
  .sale-follow:not([hidden]) + .toasts{bottom:calc(var(--h-rail) + var(--h-bar) + 82px + var(--kb,0px) + env(safe-area-inset-bottom))}

  /* ⚠️ TÊN LỚP: phải là `banphim`, KHÔNG được đặt `kbd`.
     App đã có sẵn `.kbd` từ trước — đó là cái phím giả in chữ F2/F9, và nó
     khai `font-family:var(--f-mono)` cùng viền, nền, padding. Đặt `body.kbd`
     là biến CẢ CÁI APP thành một phím bấm: toàn bộ chữ nhảy sang phông máy
     chữ. Ba bộ kiểm (17/17 · 271/271 · 63/63) và 23 phép đo trong trình duyệt
     đều XANH HẾT khi đang dính lỗi này — chỉ chụp màn hình ra nhìn mới thấy.
     Sổ lỗi #40. Đặt tên lớp mới thì grep xem tên đó có ai dùng chưa.

     Bàn phím lên thì giấu thanh điều hướng: lúc đang gõ không ai bấm nó, mà
     giấu đi thì phần màn hình còn lại dành hết cho kết quả tìm hàng. Bỏ luôn
     78px chừa cho nó, không thì đáy vùng cuộn thừa một mảng trống. */
  body.banphim .rail{display:none}
  body.banphim .view{padding-bottom:12px}
  body.banphim .sale-follow{bottom:calc(10px + var(--kb,0px))}
  body.banphim .toasts{bottom:calc(10px + var(--kb,0px))}
  body.banphim .sale-follow:not([hidden]) + .toasts{bottom:calc(80px + var(--kb,0px))}
}

/* ═══════════════ b165 — ĐIỆN THOẠI: PHIẾU BÁN HÀNG THÀNH NGĂN KÉO ═══════════════
   Anh Đạt 26/08, sau khi thử b164 trên iPhone thật:
   *"Phần chính là phiếu bán hàng nằm tận dưới đáy, việc theo dõi k tiện vì thêm
   sản phẩm kéo xuống càng dài. Bạn có thể làm 1 nút gọn (như kiểu xem giỏ hàng),
   khi mình chọn sản phẩm thì Số lượng sẽ hiển thị nhỏ bên trên, nhấn vào thì là
   phiếu bán hàng."*

   ⚠️ ĐỌC TRƯỚC KHI SỬA: một nửa việc này ĐÃ CÓ SẴN từ trước — khối
   `@media(max-width:880px){.paybar.on{...}}` ở trên đã là thanh dính đáy có số
   mặt hàng và tổng tiền. Anh Đạt không thấy nó vì `renderPaybar()` giấu thanh
   khi giỏ TRỐNG, mà lúc anh thử thì sổ chưa có mặt hàng nào.
   → b165 KHÔNG dựng lại thanh đó. Chỉ làm hai việc: cho nó luôn hiện trên điện
   thoại, và cho nửa trái bấm được để kéo phiếu lên.

   🔴 VÀ VÁ NỐT MỘT CHỖ b164 BỎ SÓT: b164 kéo `.rail`, `.sale-follow`, `.toasts`
   lên theo bàn phím nhưng QUÊN `.paybar` — nó vẫn đóng đinh `bottom:60px`, nên
   bàn phím lên là thanh tổng tiền nằm sau lưng bàn phím, đúng cái lỗi b164 sinh
   ra để chữa. Đếm sót vì lúc đó giỏ trống nên thanh không hiện, không ai thấy.
   → Bài học: liệt kê MỌI thứ `position:fixed` rồi mới vá, đừng vá thứ đang nhìn thấy. */

@media (max-width:880px){

  /* ---- 1 · vá chỗ b164 bỏ sót ---- */
  .paybar.on{
    bottom:calc(var(--h-rail) + var(--kb,0px) + env(safe-area-inset-bottom));   /* b299 · 60px → mốc chung --h-rail (b278) */
  }
  body.banphim .paybar.on{ bottom:calc(8px + var(--kb,0px)); }
  /* bàn phím lên thì thanh nút đã giấu, nhưng thanh tổng tiền vẫn còn —
     chừa chỗ cho nó, không thì dòng cuối chui xuống dưới nó */
  body.banphim .pos3{ padding-bottom:70px; }

  /* ---- 2 · nửa trái thanh = nút mở phiếu (luật .pb-l · .pb-n ở mobile.css) ---- */
  .paybar .pb-n svg{
    width:13px; height:13px; stroke:currentColor; fill:none; stroke-width:2.2; opacity:.85;
  }
  .paybar.trong .pb-t{ font-size:15px; font-weight:700; opacity:.82; font-family:var(--f-ui); letter-spacing:0; }
  /* 🔴 b284 · CHỮ TRẮNG TRÊN NỀN TRẮNG — ĐO ĐƯỢC 1,00:1, nút "Mở phiếu" VÔ HÌNH.
     Rule này viết khi thanh phiếu còn nền TỐI (trước b278): mảng trắng mờ .16 làm nút phụ
     sáng nhẹ hơn thanh. b278 anh Đạt chốt thanh phiếu sang nền GIẤY (trắng) — mảng trắng
     mờ trên trắng thành trắng, mà `color:#fff` của .pb-go vẫn còn đó. Nay nút phụ dùng cam
     nhạt + chữ --or-safe: 5,31:1, vẫn nhẹ hơn nút chính. */
  .paybar .pb-nhe{
    background:var(--or-50); border:1px solid var(--or-safe); color:var(--or-safe);
  }
  .paybar .pb-nhe:active{ background:#FFE3C7; }

  /* ---- 3 · phiếu bán hàng thành ngăn kéo ---- */
  .gio-nen{
    position:fixed; inset:0; z-index:75; background:rgba(8,32,52,.44);
    opacity:0; pointer-events:none; transition:opacity .2s ease-out;
  }
  body.gio .gio-nen{ opacity:1; pointer-events:auto; }

  .tape-col{
    position:fixed; left:0; right:0; bottom:0; z-index:80;
    grid-template-rows:auto 1fr;
    /* ⚠️ CHIỀU CAO PHẢI XÁC ĐỊNH. Thử `height:auto; max-height:...` thì hỏng:
       chiều cao không xác định nên `1fr` của lưới bên trong chia theo NỘI DUNG
       chứ không theo khung, rồi khung mới bị kéo tới trần — dư ra 85px trắng
       nằm dưới nút Thanh toán (đo được 26/08: .tape cao 719 mà tổng hàng 639).
       Đặt chiều cao xác định rồi cho cả chuỗi co giãn bằng flex. */
    height:min(92vh, calc(var(--vvh,100dvh) - 44px));
    background:var(--bg);
    border-top:1px solid var(--line);border-left:0;
    border-radius:18px 18px 0 0;
    box-shadow:0 -12px 40px rgba(8,51,79,.30);
    /* Bề ngang phải bằng đúng lúc phiếu nằm trong dòng, không thì ruột phiếu
       (ô Giảm giá, hàng tiền gợi ý, dòng KHÁCH TRẢ) bị cắt mất mép phải.
       b304 · ruột phiếu thôi đệm ngang (pos.css .tape-in) — mỗi khối tự đệm 8–10px:
       ở 390px khung phiếu 382 − viền 4 = 378px cho mỗi dòng hàng. */
    padding:0 4px calc(6px + env(safe-area-inset-bottom));
    overflow:hidden; min-height:0;
    transform:translateY(102%);
    transition:transform .22s ease-out;
    display:flex; flex-direction:column;   /* mắt đầu của chuỗi co giãn — xem ghi chú ngay dưới */
  }
  body.gio .tape-col{ transform:translateY(0); }
  /* Chuỗi co giãn từ ngăn kéo xuống tới danh sách hàng: mỗi mắt phải min-height:0
     thì con mới co được, không thì phần thừa dồn xuống đáy thành mảng trắng. */
  .tape-col .tape{ flex:1 1 0%; min-height:0; display:flex; flex-direction:column; }
  /* Cơ sở phải là 0%, KHÔNG phải auto. Với `flex-basis:auto` trình duyệt lấy
     chiều cao nội dung làm mốc rồi mới chia phần dư — đo 26/08 thì nó không
     chia, để lại đúng 85px trắng dưới nút Thanh toán. `0%` buộc chia theo khung. */
  .tape-col .tape-in{ flex:1 1 0%; min-height:0; display:flex; flex-direction:column; }
  .tape-col .tape-in > .items{ flex:1 1 0%; min-height:0; overflow-y:auto; }
  .tape-col .tape-in > .tape-hd,
  .tape-col .tape-in > .tape-ft{ flex:0 0 auto; }
  /* Hai dải răng cưa trang trí: trong ngăn kéo chúng chỉ làm rối phép chia
     chiều cao. Giấu đi, rồi cho ruột phiếu chiếm trọn khung. */
  .tape-col .zig{ display:none; }
  .tape-col .tape-in{ height:100%; }
  /* 🔴 CHỖ THẬT SỰ GÂY RA 85px TRẮNG: `.tape` có padding-bottom 76px, chừa sẵn
     cho thanh thanh toán hồi nó còn nằm TRONG dòng. Nay phiếu là ngăn kéo và
     thanh thanh toán nằm ngoài, khoảng chừa đó thành mảng trắng dưới nút.
     Mất gần một tiếng đi tìm trong flex/grid, hoá ra chỉ là một dòng padding —
     Sổ lỗi #43: đọc padding và margin TRƯỚC khi nghi ngờ cách chia khung. */
  .tape-col .tape{ padding-bottom:0; }

  /* b304 · đầu ngăn kéo = đầu phiếu một dòng: HĐ · số món · Thuế · giảm giá · ⋯ · ✕ (lớp như .tape-bar máy tính,
     pos.css). Trước là hai tầng: "Phiếu bán hàng" + nút, rồi thanh tên tiệm của phiếu. Bốn chỗ bấm đều 44px. */
  .gio-top{
    display:flex; align-items:center; gap:4px; padding:12px 4px 4px 14px;
    position:relative; flex:0 0 auto;
  }
  .gio-keo{
    position:absolute; top:4px; left:50%; transform:translateX(-50%);
    width:42px; height:4px; border-radius:99px; background:var(--sky-400);   /* b307 · đầu ngăn kéo nền xanh than — var(--line) cũ gần như mất trên nền tối */
  }
  .gio-top.ed .gio-keo{ background:var(--line); }   /* sửa hóa đơn cũ: nền vẫn sáng (.ed không đổi nền) — trả về vạch xám cũ */
  .gio-top .tape-td{ flex:1 1 0; }
  .gio-top .tape-td b{ font-size:15px; }
  .gio-top .tape-phu{ font-size:14px; }
  .gio-top .tape-tg{ height:44px; padding:0 14px; font-size:13px; }
  .gio-top .tape-dots,.gio-x{ flex:0 0 44px; width:44px; height:44px; }
  .gio-top .tape-dots svg{ width:20px; height:20px; }
  .gio-x{
    border-radius:9px; display:grid; place-items:center;
    background:var(--sky-50); border:1px solid var(--line); color:var(--slate);
  }
  .gio-x svg{ width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:2.2; }

  /* ---- 4 · dòng thông báo phải tránh thanh giỏ ----
     .toasts nằm NGOÀI .view nên không có quan hệ anh em với .paybar — chọn
     bằng lớp trên body (app.js đặt trong renderPaybar). Không có khối này thì
     toast "Đã thêm ..." đè thẳng lên tổng tiền. */
  body.cogio .toasts{
    bottom:calc(126px + var(--kb,0px) + env(safe-area-inset-bottom));
  }
  /* Ngăn kéo mở thì đáy màn hình là dòng KHÁCH TRẢ và nút Thanh toán — hai thứ
     KHÔNG được để bất cứ gì đè lên. Đẩy dòng thông báo lên đầu màn hình.
     Ảnh chụp 26/08 cho thấy toast "Đã thêm ..." nằm chồng đúng lên tổng tiền. */
  body.gio .toasts{
    top:calc(env(safe-area-inset-top) + 12px);
    bottom:auto;
  }
  body.cogio.banphim .toasts{ bottom:calc(74px + var(--kb,0px)); }
  body.cogio .sale-follow{
    bottom:calc(126px + var(--kb,0px) + env(safe-area-inset-bottom));
  }
  body.cogio .sale-follow:not([hidden]) + .toasts{
    bottom:calc(200px + var(--kb,0px) + env(safe-area-inset-bottom));
  }
  .toasts .toast{ max-width:min(300px, calc(100vw - 40px)); }

  /* ---- 5 · (b299 · đã bỏ) huy hiệu + số bản từng nằm ở góc phải thanh nút (26/08). Nay huy hiệu ở
     thanh tiêu đề (mục "2 · huy hiệu máy chủ" bên dưới) và .rail-ft ẩn hẳn trên điện thoại (responsive-core),
     nên luật vẽ nó trong thanh dưới không còn tác dụng — đã xóa. */
}

/* ═══ b165 · NGĂN KÉO PHIẾU: ƯU TIÊN DANH SÁCH HÀNG ═══
   Anh Đạt 26/08: *"màn hình phải nhìn được ít nhất 4 sản phẩm"*. Đo 26/08 ở 390×844: ngăn kéo 709px chia
   `.gio-top` 58 · `.tape-hd` 116 · `.items` 124 · `.tape-ft` 274 — mỗi dòng 117px, thấy MỘT sản phẩm. b165 gấp khối
   Thuế · Giảm giá · Khách đưa sau nút "Thuế · giảm giá"; b296 giấu thêm thanh tên tiệm.
   b304 · phiếu mỗi món MỘT dòng (~58px) nên không còn gì phải gấp bằng CSS ở đây nữa: bảng Thuế · giảm giá chỉ
   được VẼ khi mở (pos-phieu.js), đầu phiếu là đầu ngăn kéo. Đo b304 ở 390×844, 6 món: thấy trọn 6/6.
   Ngưỡng ≥ 4 dòng vẫn là luật: tests/browser/hoi-quy-ban-hang.js (PHẦN b304) đo ở 320 · 360 · 390 · 428. */

/* ═══════ b166 · 🔴 MÀN BÁN HÀNG TRÊN ĐIỆN THOẠI KHÔNG CUỘN ĐƯỢC ═══════
   Anh Đạt 26/08: *"Gợi ý 12 sản phẩm nhưng lướt xem k được. Giữ lướt thì app
   nhận diện chọn sản phẩm luôn. Cái này quan trọng vì nó sẽ làm việc chọn nhầm
   hàng xảy ra thường xuyên."*

   NGUYÊN NHÂN — có sẵn từ b163, không phải do b164/b165 (đã so ba bản):

     app.css:190  .view.pos{ overflow:hidden }        ← màn Bán hàng khoá cuộn
     app.css:268  .results{ overflow:auto }           ← máy tính: DANH SÁCH tự cuộn
     app.css:849  @media(<=880px){ .results{overflow:visible} }
                                                      ← điện thoại: bỏ luôn cuộn đó

   Máy tính: `.view` khoá nhưng `.results` cuộn → đúng.
   Điện thoại: `.view` khoá, `.results` cũng bỏ cuộn → **KHÔNG CÒN AI CUỘN.**

   Trước đây không ai thấy vì danh mục rỗng, chẳng có gì để cuộn. Nạp 20 mặt
   hàng vào sổ thử là lộ ngay.

   ⚠️ VÌ SAO PHÉP ĐO CỦA CLAUDE BÁO "CUỘN ĐƯỢC": nó kiểm
   `scrollHeight > clientHeight` — **đúng cả khi overflow:hidden**, và
   `element.scrollTop = 120` bằng mã **cũng chạy** trên khung overflow:hidden.
   Hai phép đo đều trả về giá trị hợp lệ mà sai — Sổ lỗi #35, #44.
   Muốn biết có cuộn được bằng NGÓN TAY thì phải đọc `getComputedStyle().overflowY`,
   hoặc vuốt thật rồi đo. */
@media (max-width:880px){
  .view.pos{ overflow-y:auto; -webkit-overflow-scrolling:touch; }
}

/* ═══════════════════════════════════════════════════════════════════════
   b169 · THANH TÌM HÀNG DÍNH LẠI · HUY HIỆU MÁY CHỦ LÊN THANH TIÊU ĐỀ
   Anh Đạt 26/08: "khi cuộn xuống xem hàng là thanh tìm hàng bị trôi luôn.
   Và ô Online + phiên bản để trên cùng bên phải, sát tài khoản đang dùng."
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width:880px){

  /* ---- 1 · thanh tìm hàng dính lại ----------------------------------
     b166 mở cuộn cho .view.pos để vuốt xem 12 gợi ý (Sổ lỗi #44). Hệ quả
     KHÔNG AI LƯỜNG: cả .pos3 cuộn theo, nên THANH TÌM trôi khỏi màn hình.
     Một bản vá đẻ ra một lỗi mới, và ba tuần sau không ai nối được hai
     chuyện với nhau nếu không ghi ở đây.

     ⚠️ Vì sao phải mở .pos3-main ra trước: nó đang overflow:hidden, mà một
     phần tử overflow khác visible thì TỰ NÓ thành khung cuộn. position:sticky
     dính vào khung cuộn GẦN NHẤT — tức dính vào .pos3-main chứ không phải
     .view.pos. Mà .pos3-main không cuộn, nên sticky nằm im không làm gì cả,
     KHÔNG báo lỗi, KHÔNG hiện ra trong bộ kiểm. Đúng họ Sổ lỗi #44:
     thứ trông như đã bật mà thật ra chưa bao giờ chạy. */
  .pos3-main{ overflow:visible; }

  .scanner{
    position:sticky; top:0;
    z-index:3;                 /* trên .res-head (2), dưới .paybar (55),
                                  thanh dưới (60), ngăn kéo phiếu (80).
                                  Đo thật trong app.css, không đoán. */
    /* .scanner đã có background:var(--paper) từ đầu — sticky mà nền trong
       suốt thì hàng cuộn lên sẽ hiện xuyên qua chữ. Ghi lại đây để ai gỡ
       nền ở trên biết là nó đang gánh thêm việc này. */

    /* DẢI NỀN NỐI THÊM DƯỚI ĐÁY — đo được rồi mới thêm, không phải cho đẹp:
       chụp màn hình lúc cuộn 400px thấy một thẻ hàng trắng thò ra ngay sát
       dưới viền đáy thanh tìm, lộ cả góc bo và viền, trông như thanh tìm bị
       dán thêm một thẻ ma. Bộ kiểm không thấy — nó chỉ đếm toạ độ, mà toạ độ
       thì đúng (Sổ lỗi #40: bộ kiểm đo số, không đo xấu — mở ra nhìn).
       Nguyên do: dính rồi thì hàng cuộn lên chạm ĐÚNG mép đáy thanh tìm,
       không còn khoảng thở như lúc nằm yên.
       Cách chữa: bóng thứ hai, không nhoè, nở 10px và dời xuống 10px — thành
       một dải var(--bg) đặc dài đúng 20px dưới đáy, hàng cuộn chui sau nó.
       Vì sao đúng 20px: đo trong trình duyệt — .pos3-main gap 10px và có một
       div rỗng chen giữa ăn thêm một gap nữa, nên lúc nằm yên đáy thanh tìm
       ở y=151 mà khối hàng bắt đầu ở y=171. Lấy đúng 20 thì lúc nằm yên dải
       này phủ vừa khít khoảng trống sẵn có, KHÔNG che mất mép thẻ đầu tiên.
       Đổi gap thì phải đổi số này — không thì nó ăn vào thẻ.

       ⚠️ LẦN ĐẦU LÀM BẰNG box-shadow LỚP HAI — KHÔNG ĂN, và không báo gì.
       Vì `.scanner:focus-within` (dòng 300) cũng đặt box-shadow, mà nó nặng
       ký hơn (0,2,0 so với 0,1,0) nên đè mất. Ô tìm hàng thì gần như LÚC NÀO
       CŨNG đang được chọn — focusScan() gọi sau mỗi lần thêm/bớt hàng — nên
       lớp bóng mới không bao giờ được vẽ. Đo pixel ra vẫn trắng y như cũ.
       Dùng ::after thì không ai đè được, và cũng không đụng vào bóng sẵn có. */
  }
  .scanner::after{
    /* Nới ra -10px cho bằng ĐÚNG padding hai bên của .pos3 trên màn nhỏ
       (10px), để dải chạm mép màn hình. Để -2px thì cái đuôi bóng mờ của
       thanh tìm còn thò ra hai bên rồi bị cắt ngang, thành hai vệt xám nhỏ.
       Đổi padding .pos3 thì đổi luôn số này. Không nới quá 10 — quá thì
       .view.pos sinh thanh cuộn ngang. */
    content:''; position:absolute; left:-10px; right:-10px;
    top:calc(100% + 1.5px);      /* 100% là đáy hộp ĐỆM, cộng 1.5px cho hết viền */
    height:20px; background:var(--bg); pointer-events:none;
  }

  /* .res-head ("HÀNG BÁN CHẠY 12") cũng sticky top:0. Hai thứ cùng dính ở
     một mốc thì chồng lên nhau — cái z-index thấp hơn chui xuống dưới rồi
     biến mất, trông như lỗi vẽ. Chỉ để ĐÚNG MỘT thứ dính: thanh tìm. */
  .results .res-head{ position:static; }

  /* ---- 2 · huy hiệu máy chủ + số bản lên thanh tiêu đề ---------------
     Rời khỏi chân thanh bên (.rail-ft ẩn trên điện thoại ở responsive-core.css). Thanh dưới nay chỉ
     còn 5 nút đích — bề rộng mỗi nút (min-width 68px) khai ở .navbtn trong mobile.css. */

  .head-may{
    margin-left:auto;           /* việc đẩy sang phải nay là của khối này */
    display:inline-flex; flex-direction:column; align-items:flex-end;
    gap:2px; line-height:1; 
  }
  .head-ban{
    font-family:var(--f-mono); font-size:12px; font-weight:700;
    letter-spacing:.04em; color:var(--slate-2);
  }
  .head-may .server-mode{
    white-space:nowrap;
    /* .server-mode sinh ra cho CHÂN THANH BÊN, cỡ 8px. Trên thanh tiêu đề
       điện thoại thì 8px quá nhỏ — mà 8px cũng KHÔNG nằm trên thang chữ:
       nấc nhỏ nhất của tờ nhận diện là --t0 10.5px. Kéo lên đúng nấc, cho
       bằng .head-ban ngay dưới nó.
       Viết thẳng 10.5px chứ không var(--t0): app.css KHÔNG khai --t0 (đã
       grep 26/08). Dùng biến không khai thì nó im lặng không ăn — đúng cái
       bẫy .ei-r:hover/--sky-1 mà tờ nhận diện ghi. */
    font-size:12px; padding:2px 6px;
  }


  /* ---- 2b · giữ huy hiệu + nút tài khoản KHÔNG bị đẩy khỏi màn ----------
     ĐO ĐƯỢC 26/08 trên iPhone SE 375px, màn Hóa đơn:
        #head nội dung 439px / khung 375  →  nút tài khoản hết ở x=439.
     Tức là nó đã NẰM NGOÀI MÀN TỪ TRƯỚC b169, không phải lỗi mới —
     đo lại sau khi bỏ .head-may đi vẫn 439. b169 chỉ làm nó tệ thêm
     (507) và làm nó lộ ra. Ghi rõ để đừng ai đi tìm nhầm ở b169.

     Vì sao: .head là một hàng flex nowrap. Màn Hóa đơn nhét thêm hai nút
     chữ dài — "Xem lợi nhuận" 148px và "Xuất Excel" 127px. Cộng tiêu đề
     70 + huy hiệu 58 + nút tài khoản 40 + 5 khoảng cách là quá 375.
     Nút cuối hàng bị đẩy ra ngoài, mà .head không cuộn ngang nên nó mất hẳn.

     ĐÃ THỬ VÀ BỎ — cho nút co lại bằng `flex:0 1 auto; overflow:hidden;
     text-overflow:ellipsis`. Số đo đẹp (375/375, không nút nào ra ngoài)
     nhưng MỞ RA NHÌN thì chữ bị cắt cụt KHÔNG có dấu ba chấm — hiện ra
     "Xem lợi nh" và "Xuất Exc". Lý do: text-overflow chỉ ăn trên hộp khối,
     .btn là hộp flex nên nó lờ đi. Đúng Sổ lỗi #40: bộ kiểm đo số, không
     đo xấu — chụp ảnh ra nhìn mới thấy.
     Nay chữa ở MÃ chứ không ở CSS: màn hẹp thì rút gọn nhãn (xem
     VIEWS.invoices.head trong app.js). Ở đây chỉ chốt một luật: huy hiệu
     và nút tài khoản KHÔNG BAO GIỜ bị bóp — hai thứ này anh Đạt yêu cầu
     phải nằm trên cùng bên phải. (.head min-width:0 khai ở responsive-core.css.) */
  .head-may{ flex:0 0 auto; }
  /* b275 · số ms trong huy hiệu làm bề rộng thanh tiêu đề ĐỔI THEO ĐƯỜNG TRUYỀN:
     "6ms" 68px, "128ms" ~93px — ĐÃ ĐO 20/09 ở 360px màn Cho thuê: nút tài
     khoản 308→348 khi 6ms, 333→373 khi ms dài (văng ra 13px). Trên điện thoại
     giấu số ms (vẫn còn trong title/aria-label và ở chân thanh bên máy tính). */
  .head-may .sm-ms{ display:none; }
}

/* ═══ b296 → b304 · PHIẾU TRÊN ĐIỆN THOẠI: CHỖ BẤM 44px ═══
   b296 soát 24/09 ở 428×926: 27/41 chỗ bấm dưới 44px; ba nút Tiền mặt · CK · Ghi nợ ẩn sau "Thuế · giảm giá".
   b304 (anh Đạt 25/09, phương án A): dòng [tên][ô SL 44px][tiền][⋯ 44px]; dải lẻ ⇄ nguyên · − · + · Xong 44px chỉ
   dưới dòng đang sửa; khách đã chọn là thẻ; ba nút trả tiền cùng hàng KHÁCH TRẢ; chọn CK là thấy nút QR; đã gõ khách đưa
   thì thấy Thối lại. Nút ⋯ hộp 44px trong cột 24px: lề âm 10px hai bên, không đổi nhịp dòng. Đo ở PHẦN b304 của
   tests/browser/hoi-quy-ban-hang.js: 320 · 360 · 390 · 428, mọi chỗ bấm ≥ 44px, không chữ nào bị cắt. */
@media (max-width:880px){
  .tape-hd{padding:8px}
  .kh-av{display:none}   /* điện thoại: nhường chỗ cho tên + số */
  .custline{min-height:52px;padding:4px 0 4px 10px;gap:6px}
  .kh-sua,.kh-bo{width:44px;height:44px}
  .kh-sua svg,.kh-bo svg{width:17px;height:17px}
  .kh-so .num{white-space:nowrap}
  .cust-row{grid-template-columns:minmax(0,1fr) 124px 44px}
  .cust-row input{min-height:44px}
  .cust-row .cbtn{min-height:44px}
  body.big .cust-row input{font-size:16px}
  /* b307 · tên/tiền to thêm một bậc trên điện thoại (14,5→16 · 15,5→17,5 — bỏ luôn số lẻ ,5 của tên) — cột tiền
     nở 88→100px cho vừa số 10 ký tự ở cỡ mới (đo bằng Chromium T2/HOP, không đoán bằng mắt). */
  .item{--cot-but:24px;--khe:8px;grid-template-columns:minmax(0,1fr) 56px 100px var(--cot-but);padding:7px 10px}
  .item .nm{font-size:16px}
  .slo{height:44px;margin-top:-2px}
  .slo input{padding-bottom:13px;font-size:16px}
  .dvi{bottom:5px;font-size:12px;line-height:13px}
  .item .tt b{font-size:17.5px}
  .item .tt.dai b{font-size:13px}
  .slo.dai input{padding:0 0 13px;font-size:16px;letter-spacing:-1.5px}   /* số dài ("12,375") vẫn 16px — dưới 16 iPhone tự phóng trang — khít chữ cho vừa ô */
  .gio-top.ed .tape-td{white-space:normal;line-height:1.15}   /* "Sửa HĐ HD-000123" xuống dòng chứ không bị cắt mất đuôi số */
  .gio-top.ed .tape-phu{display:none}
  .item .dmenu{width:44px;height:44px;margin:-12px -10px 0;opacity:1}
  .item .dmenu svg{width:20px;height:20px}
  .item .dmenu:hover,.item .dmenu[aria-expanded="true"]{background:transparent}   /* hộp 44px lấn đuôi số tiền — tô nền là che mất chữ số cuối */
  .dmenu-pop button{min-height:44px;font-size:14px}
  .sl-doan button,.tg-doan button{height:44px;padding:0 12px;font-size:14px}
  .tg-doan button{padding:0 11px}
  .sl-b{flex:0 0 44px;height:44px;font-size:22px}
  .sl-xong,.nt-xong{height:44px;padding:0 16px;font-size:14px}
  .item .ntin{height:44px}
  .tape-ft{padding:8px 10px}
  .pseg,body.big .pseg{min-width:44px;min-height:44px;padding:0 13px;font-size:14px}
  .tra-hang .trow.tot .num{font-size:21px}
  .tg-bang input,body.big .tg-bang input{height:44px;font-size:16px}   /* chữ to cũng ≥ 16px: dưới 16 là iPhone tự phóng cả trang */
  .tg-goi .cashsug{height:44px}
  .tg-goi .cashsug button{height:44px;padding:0 6px;font-size:12px}
  .dua-hang.dt{font-size:13px;color:var(--slate)}
  /* b305 · khách đưa thiếu: "Ghi nợ <tên>" thay chữ "Khách đưa …" trên CÙNG hàng với "Còn thiếu" — không đẻ thêm dòng (320 chữ to
     đã chật). Hàng này vốn cao 44px (nút × 44px) nên chữ được xuống tối đa HAI dòng mà không cao thêm; tên quá dài thì cắt ở dòng 2
     (tên đủ đã có trên thẻ khách và trong hộp kiểm tra). */
  .dua-nt{flex:1 1 0;min-width:0;white-space:normal;line-height:1.3;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
  .dua-nt b{color:var(--ink);font-weight:700}
  .dua-nt.chua{color:var(--red);font-weight:600}
  .dua-hang.dt .chgclr{width:44px;height:44px;margin-right:-8px;border:0;background:none;font-size:18px}
  .tra-qr{height:44px}
  .ck-khung .tra-qr{width:120px;height:120px}   /* .btn.sm đặt min-height 34px mạnh hơn — đặt thẳng chiều cao */
}
/* b319 kiểm độc lập: điện thoại màn THẤP (320×640, 360×640) — khung QR 120px đẩy danh sách hàng còn 22px ⇒ QR 76px (chạm vẫn phóng to 280px
   cho khách quét), bỏ dòng tên chủ tài khoản; danh sách hàng thấy lại được trước khi bấm "Đã nhận tiền" */
@media (max-width:880px) and (max-height:700px){
  .ck-khung{margin-top:6px;padding:6px 8px;gap:4px 10px}
  .ck-khung .tra-qr{width:76px;height:76px}
  .ck-tt b{font-size:18px}
  .ck-ten{display:none}
  /* b306 · đ / % và "Chuyển khoản" trong bảng Thuế · giảm giá: vùng chạm 44px như mọi nút của phiếu; hẹp quá thì đoạn đ/% rớt
     xuống dưới chữ GIẢM GIÁ (không bóp ô số) */
  .tg-nhan:has(.tg-kieu){display:flex;flex-wrap:wrap;align-items:center;gap:2px 6px}
  .tg-kieu{margin-left:0}
  .tg-kieu button{min-width:44px;height:44px;font-size:14px}
  .tg-goi .ck-thieu,body.big .tg-goi .ck-thieu{height:44px;margin-left:0;padding:0 12px;font-size:14px}   /* chữ to (large-ui 30px) không được thắng vùng chạm */
  .tape-acts .btn.big{min-height:52px}
  .acts-2 .btn{min-height:44px}
}
/* 320–374px (iPhone SE đời đầu, máy Android nhỏ): cột hẹp lại, bỏ chữ phụ — đo ở 320 không chữ nào bị cắt. */
@media (max-width:374px){
  .gio-top .tape-phu{display:none}
  .gio-top .tape-tg{padding:0 10px;font-size:12.5px}
  /* b307 · 320px vẫn nhích lên được một bậc dù màn rất hẹp — cột tiền nở 80→96px (đo bằng Chromium: số 10 ký tự
     "28.500.000" ở 16px cần đúng ngần này mới không bị ô SL đè, #187) */
  .item{--khe:7px;grid-template-columns:minmax(0,1fr) 52px 96px var(--cot-but);padding:7px 10px 7px 8px}
  .item .nm{font-size:15px}
  .item .tt b{font-size:16px}
  .sl-doan i{display:none}
  .sl-dai{gap:5px;padding:5px}
  .sl-xong{padding:0 12px}
  .tra-hang{gap:8px}
  .pseg,body.big .pseg{padding:0 9px;font-size:13px}
  .tra-hang .trow.tot .num{font-size:19px}
}
/* 320px: ba nút trả tiền + KHÁCH TRẢ chỉ vừa một hàng khi thu nhỏ thêm (số 9 chữ số); số dài hơn thì xuống dòng. */
@media (max-width:340px){
  .cust-row{grid-template-columns:minmax(0,1fr) 116px 44px}   /* ô tên đủ chỗ cho chữ mờ "Tên khách"; ô số vẫn đủ 10 số */
  .pseg,body.big .pseg{padding:0 6px;font-size:12.5px}
  .tra-hang .trow.tot .num{font-size:17px}
}

/* ===== SOURCE: styles/chup-anh.css ===== */
/* ═══ b283 · CHỤP ẢNH SẢN PHẨM — lớp phủ riêng #chupov (frontend/chup-anh.js) ═══
   Nền tối như màn máy ảnh của điện thoại; chữ trắng trên #1B1E24 (--ink) — 15,6:1.
   Cam chỉ dùng cho nút "Dùng ảnh" (#FDBA74 trên nền tối 9,4:1) và núm xoay.
   Khung vuông 342px (= 390 − 2×24) — trên máy nhỏ hơn co theo min(342px, 100vw − 48px). */
#chupov{position:fixed;inset:0;z-index:95;background:#1B1E24;color:#fff;font-family:var(--f-ui)}
#chupov[hidden]{display:none}
body.dang-chup{overflow:hidden}
.ca{display:flex;flex-direction:column;height:100%;height:100dvh}
.ca-hd{height:calc(52px + env(safe-area-inset-top));padding-top:env(safe-area-inset-top);flex:none;display:flex;align-items:center;gap:10px;padding-left:8px;padding-right:12px}
.ca-hd3{display:grid;grid-template-columns:1fr auto 1fr;align-items:center}
.ca-hd3>b{font-size:15px;font-weight:700;text-align:center}
.ca-hd3 .ca-back{max-width:none;justify-self:start}
.ca-back{display:inline-flex;align-items:center;gap:4px;height:40px;padding:0 10px;border:0;background:transparent;color:#fff;font:inherit;font-size:14.5px;font-weight:600;border-radius:10px;max-width:60%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ca-back svg{width:18px;height:18px;flex:none;stroke:currentColor;fill:none;stroke-width:2}
.ca-ok{justify-self:end;height:40px;padding:0 12px;border:0;background:transparent;color:#FDBA74;font:inherit;font-size:15px;font-weight:700;border-radius:10px}
.ca-ok:disabled{color:#ffffff80}
.ca-dem{margin-left:auto;font-size:13px;font-weight:700;background:#ffffff22;border-radius:12px;padding:4px 10px;font-variant-numeric:tabular-nums}
.ca-xem{position:relative;flex:1;min-height:0;background:#2b2f36;display:flex;align-items:center;justify-content:center;overflow:hidden}
.ca-xem video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.ca-xem video[hidden]{display:none}
/* b290 · khung ngắm BẰNG ĐÚNG ô ảnh trong bảng hàng: 4:3, không còn vuông. */
.ca-khung{position:relative;width:min(342px,calc(100vw - 48px));aspect-ratio:4/3;border:2px solid #fff;border-radius:6px;box-shadow:0 0 0 999px rgba(0,0,0,.45);touch-action:none}
.ca-khung::before,.ca-khung::after{content:"";position:absolute;background:rgba(255,255,255,.35);pointer-events:none}
.ca-khung::before{left:33.33%;top:0;bottom:0;width:1px;box-shadow:calc(min(342px,100vw - 48px)/3) 0 0 rgba(255,255,255,.35)}
.ca-khung::after{top:33.33%;left:0;right:0;height:1px;box-shadow:0 calc(min(342px,100vw - 48px)/4) 0 rgba(255,255,255,.35)}
.ca-xem-ed{background:#2b2f36}
.ca-xem-ed canvas{position:absolute;width:min(342px,calc(100vw - 48px));height:auto;aspect-ratio:4/3;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:6px}
.ca-khung-ed{box-shadow:none;cursor:grab}
.ca-nhan{position:absolute;left:12px;right:12px;top:12px;display:flex;justify-content:space-between;gap:8px;font-size:12.5px;z-index:2;pointer-events:none}
.ca-nhan b{background:#000000aa;padding:5px 10px;border-radius:8px;font-weight:600;display:inline-flex;align-items:center;gap:5px}
.ca-nhan svg{width:14px;height:14px;stroke:#FDBA74;fill:none;stroke-width:2.4}
.ca-loi{position:absolute;left:16px;right:16px;top:50%;transform:translateY(-50%);z-index:2;background:#000000cc;border-radius:12px;padding:12px 14px;font-size:14px;line-height:1.45;text-align:center;pointer-events:none}
.ca-loi[hidden]{display:none}
.ca-ai{position:absolute;left:12px;right:12px;bottom:12px;background:#000000b3;border-radius:12px;padding:10px 12px;z-index:2;pointer-events:none}
.ca-ai .n{font-weight:700;font-size:16px;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ca-ai .s{font-size:12.5px;line-height:16px;color:#d5d9e0;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ca-ai.nho{padding:8px 12px}.ca-ai.nho .n{font-size:14px;line-height:18px}
.ca-ft{flex:none;height:116px;display:grid;grid-template-columns:1fr 84px 1fr;align-items:center;padding:0 24px}
.ca-b{display:flex;flex-direction:column;align-items:center;gap:6px;font-size:13px;font-weight:600;color:#e5e7eb}
.ca-tron{width:44px;height:44px;border-radius:50%;border:1.5px solid #ffffff55;background:transparent;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0}
.ca-tron svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:2}
.ca-nut{width:72px;height:72px;border-radius:50%;border:5px solid #fff;background:#fff;box-shadow:inset 0 0 0 4px #1B1E24;margin:0 auto;cursor:pointer;padding:0;position:relative}
.ca-nut:active{transform:scale(.94)}
.ca-nut.tep::after{content:"";position:absolute;inset:14px;border-radius:50%;background:#FDBA74}
.ca-chu{flex:none;text-align:center;font-size:12.5px;color:#aab0bb;padding:0 16px calc(14px + env(safe-area-inset-bottom))}
.ca-cc{flex:none;padding:12px 16px calc(14px + env(safe-area-inset-bottom))}
.ca-goc{display:flex;align-items:center;gap:12px;font-size:13px;color:#d5d9e0;font-variant-numeric:tabular-nums}
.ca-goc input[type=range]{flex:1;min-width:0;accent-color:var(--or);height:28px;margin:0;background:transparent}
.ca-goc b{width:38px;text-align:right;color:#fff}
.ca-tb{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:10px}
.ca-tb button{height:44px;border-radius:10px;border:1px solid #ffffff33;background:#ffffff14;color:#fff;font:inherit;font-size:13.5px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;gap:6px;white-space:nowrap;padding:0 6px}
.ca-tb button svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;flex:none}
.ca-tb button.on{background:#ffffff2e;border-color:#fff}
.ca-cc .ca-chu{padding:10px 0 0}

/* hộp Chụp theo nhóm (trong #ov) */
.ca-nhom{display:grid;gap:8px;max-height:56vh;overflow:auto}
.ca-nhom-i{display:grid;grid-template-columns:minmax(0,1fr) auto 20px;align-items:center;column-gap:10px;height:56px;padding:0 12px;border:1px solid var(--line);border-radius:10px;background:var(--paper);color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.ca-nhom-i .t{font-weight:600;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ca-nhom-i .s{font-size:12.5px;color:var(--slate);white-space:nowrap}
.ca-nhom-i .s b{color:var(--or-safe);font-weight:700}
.ca-nhom-i.du .s{color:var(--slate)}
.ca-nhom-i svg{width:18px;height:18px;stroke:var(--slate);fill:none;stroke-width:2;transform:scaleX(-1)}
@media (hover:hover){ .ca-nhom-i:hover{border-color:var(--sky-300)} }

/* form Thêm sản phẩm nhanh (điện thoại) */
.thn-anh{display:grid;grid-template-columns:96px 1fr;gap:12px;align-items:center}
.thn-o{width:96px;height:96px;border-radius:12px;border:1.5px dashed var(--sky-300);background:var(--paper);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;color:var(--or-safe);font:inherit;font-size:13px;font-weight:700;cursor:pointer;overflow:hidden;padding:0}
.thn-o svg{width:24px;height:24px;stroke:currentColor;fill:none;stroke-width:2}
.thn-o.co{border:1px solid var(--line)}
.thn-o img{width:100%;height:100%;object-fit:cover;display:block}
.thn-o{aspect-ratio:4/3}
.thn-t{font-size:12.5px;color:var(--slate);line-height:1.45}
.thn-t b{display:block;color:var(--ink);margin-bottom:2px}
.thn-lk{margin-top:8px}

/* chip trên màn Sản phẩm điện thoại: Chưa có ảnh · N — Chụp theo nhóm — + Thêm hàng */
.ph-chips{margin-bottom:8px}
.ph-chips .rchip{display:inline-flex;align-items:center;gap:5px;padding:0 12px}
.ph-chips .rchip svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;flex:none}

/* ô ảnh trên dòng hàng nay là <button> (b283) — bỏ kiểu nút mặc định, giữ nguyên hình dạng b248 */
.ph-row button.ph-cam{padding:0;font:inherit;color:inherit}

/* máy tính: lớp phủ mờ, hộp tối 440px ở giữa — thanh xoay và ba nút không kéo dài hết 1280px */
@media (min-width:800px){
  #chupov{background:rgba(6,43,68,.6);display:grid;place-items:center}
  #chupov[hidden]{display:none}
  .ca{width:440px;height:auto;max-height:calc(100vh - 40px);background:#1B1E24;border-radius:16px;overflow:hidden;box-shadow:var(--shadow-lg)}
  .ca-xem{flex:none;height:460px}
  .ca-khung,.ca-xem-ed canvas{width:342px}
  .ca-khung::before{box-shadow:114px 0 0 rgba(255,255,255,.35)}
  .ca-khung::after{box-shadow:0 85.5px 0 rgba(255,255,255,.35)}
}

/* ===== SOURCE: styles/cham-dien-thoai.css ===== */
/* ═══════════════════════════════════════════════════════════════════════════
   CHẠM TRÊN ĐIỆN THOẠI — hộp thoại toàn màn + chỗ bấm ≥ 44px cho CẢ APP (b296)
   Soát 24/09 (đợt lớn, Phần 3) ở 428×926: hộp Sửa SP có 25/29 chỗ bấm dưới 44px, Giao hàng 14/14,
   Cài đặt 15/15, Khách mới 13/13; chip 31–36px; nút phân trang 40px. Chỉ phiếu thuê (b295) đạt.
   · 44px: Apple HIG 44pt · WCAG 2.5.5 (AAA) 44px. Ô nhập 16px: iPhone tự phóng to trang khi chữ < 16px.
   · Material: hộp có ô gõ và chỉ lưu khi bấm Lưu thì dùng hộp TOÀN MÀN trên điện thoại. Hộp HẸP
     (`narrow`: PIN, mật khẩu, hỏi lại) vẫn nổi giữa màn.
   · Đo ở 320 · 360 · 390 · 412 · 428px — không sửa theo riêng một máy (anh Đạt hỏi 24/09).
   Luật riêng của phiếu thuê ở phieu-thue.css — tệp đó đứng SAU tệp này trong manifest nên thắng khi trùng.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:880px){
  /* ── hộp thoại: toàn màn (trừ hộp hẹp) ── */
  .ov:not(.drawer-host):has(> .modal:not(.narrow)){padding:0;place-items:stretch}
  .modal:not(.narrow){width:100%;max-width:none;height:100dvh;max-height:100dvh;border-radius:0}
  .modal:not(.narrow) .m-hd{border-radius:0;padding-top:max(var(--space-3),env(safe-area-inset-top))}
  .modal:not(.narrow) .m-ft{padding-bottom:max(var(--space-3),env(safe-area-inset-bottom))}
  /* hộp kiểu ngăn kéo (hóa đơn, sửa hàng) — chuyển từ responsive-core.css về đây: một khối, một tệp */
  .ov.drawer-host{padding:0;place-items:stretch}
  .modal.drawer,.modal.drawer.wide{width:100vw;max-width:none;height:100dvh;max-height:100dvh;border-radius:0}
  .modal.drawer .m-hd{border-radius:0}

  /* b319 · thanh tiêu đề (nút "?" mọi màn, Đặt bàn / Sắp bàn / Vãng lai / Đặt lịch) + nút việc ở Bảng hôm nay: ≥ 44px (đo b319: 40 và 34px) */
  #head .btn,#head .icobtn{min-height:44px;min-width:44px}
  .ql-bang .btn.sm{min-height:44px}
  .res-x{width:44px;height:44px}   /* ✕ đóng Danh mục / ô tìm (đo b319: 27px) */
  /* ── chỗ bấm trong hộp ── */
  .modal .m-hd .icobtn{width:44px;height:44px;flex:0 0 44px}   /* tiêu đề dài không được bóp nút ✕ (đo 360px: còn 39px) */
  .modal .btn{min-height:44px}
  .modal .f input:not([type=checkbox]):not([type=radio]),.modal .f select,.modal .f textarea{min-height:44px;font-size:16px}
  .modal label.chk{min-height:44px;display:flex;align-items:center;gap:var(--space-2)}
  .modal summary{min-height:44px}
  .modal .set-nav button,.modal .eqtab{min-height:44px}
  .modal .fchip{min-height:44px}

  /* ── chỗ bấm trên màn: chip lọc, ô tìm, phân trang, ô chọn ── */
  .rchip,.fchip{min-height:44px}
  .resource-search input,.search-in input{min-height:44px}
  .pgn{min-width:44px;min-height:44px}
  .resource-toolbar select,#p_pager select{min-height:44px}
  .paybar .pb-l,.paybar .pb-go{min-height:44px}
  .rky-b{width:44px;height:44px}
  .rky-now{min-height:44px}
  .text-action{min-height:44px}
  .phcam{width:44px;height:44px}
  .ixoa{width:44px;height:44px}
  .actbtn.key.wide{min-height:44px}
  .empty .btn{min-height:44px}   /* nút mời ở màn trống (Bảo hành, Sổ màu) — đo lại sau mục 17: 40px */

  /* ── ô tìm màn Bán hàng: chữ gõ cao 44px (trước 28px), bớt đệm hộp cho hộp gần như giữ chiều cao ── */
  .scanner{padding-top:var(--space-1);padding-bottom:var(--space-1)}
  .scan-field input{min-height:44px}
  .scan-mic,.scan-cam{width:44px;height:44px}
}

/* ===== SOURCE: styles/phieu-thue.css ===== */
/* ═══════════════════════════════════════════════════════════════════════════
   PHIẾU CHO THUÊ — MỌI luật CSS của hộp "Lập phiếu cho thuê" nằm ở tệp này (b295)
   Trước b295 phiếu rải ở BỐN tệp (commerce · responsive-core · mobile · workflows): luật máy tính và
   điện thoại giành nhau, lỗi hai ô đè nhau của b292 sống qua 7 bản. Nay một chỗ, đứng CUỐI manifest.
   Khung (rentals.js · rentForm): .phieuthue > .pt-tin · .pt-phai (.pt-hang + .pt-tien) · .pt-them
   Thứ tự trong mã = thứ tự tờ giấy của tiệm = thứ tự trên điện thoại (nút ‹ › bàn phím iPhone nhảy ô
   theo thứ tự trong mã). Máy tính chỉ xếp lại bằng lưới. Bài học: sổ tay thiết kế mục 7.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- khung chung: một cột (điện thoại, máy tính bảng) ---- */
.phieuthue{display:flex;flex-direction:column;gap:var(--space-4);min-width:0}
.pt-tin,.pt-phai,.pt-hang,.pt-tien{display:flex;flex-direction:column;gap:var(--space-3);min-width:0}
.pt-phai{gap:var(--space-4)}
.phieuthue .sect{margin:0}
/* cặp ô cùng MỘT thực thể (tên + điện thoại · hai ngày · công + tiền vận chuyển) — ngoại lệ Baymard
   cho phép, không phải lưới hai cột cho cả phiếu */
/* canh ĐẦU ô (start), không canh đáy: một ô hiện dòng lỗi bên dưới thì ô bên cạnh không bị kéo lệch */
.pt-cap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--space-3);align-items:start}
.pt-nguoi{grid-template-columns:minmax(0,1fr) 148px}   /* tên dài · điện thoại 10 số */
.phieuthue .f{min-width:0}
.phieuthue .f input{width:100%;min-width:0}
.phieuthue input.num{text-align:right}
/* nhãn của nhóm nút chọn: cùng bộ đồ với .f label (components.css) */
.phieuthue .f-nhan{display:block;font-size:12px;font-weight:700;color:var(--slate);margin-bottom:4px;letter-spacing:.02em}

/* ---- dòng đọc lại ngày: số ngày CHÍNH LÀ số tiền (b266) ---- */
.ngayxem{
  font-size:12.5px;color:var(--slate);background:var(--sky-50);
  border-left:3px solid var(--sky-400);
  padding:var(--space-2) var(--space-3);border-radius:var(--r);
}
.ngayxem strong{color:var(--ink);font-weight:700}
.ngayxem.xau{background:var(--red-soft);border-left-color:var(--red);color:var(--red)}
.ngayxem.xau strong{color:var(--red)}

/* ---- nút chọn liền khối (công vận chuyển · hình thức trả) — .segbar/.seg của app, trải hết ô ---- */
/* khối cao đúng bằng ô nhập đứng cạnh (38px): đệm khối 2px + ô 32px + viền */
.phieuthue .segbar{display:flex;width:100%;padding:calc(var(--space-1) / 2)}
.phieuthue .seg{flex:1 1 0;min-width:0;min-height:0;height:32px;padding:0 var(--space-1);font-size:14px}
.phieuthue .seg.on{color:var(--ink)}

/* ---- danh sách thiết bị: MỘT dòng đọc thành một câu  [SL] × [giá] = tiền đ  (PA-A anh chọn 22/09) ---- */
.eqtrong{padding:14px 12px;border:1px dashed var(--line-2);border-radius:10px;color:var(--slate);text-align:center}
.eqrow{display:grid;align-items:center;min-width:0}
.eqrow .eqo{display:contents}          /* ô bọc tàng hình: ô nhập bên trong là ô lưới */
.eqrow .eqnm{min-width:0;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.eqrow .eqnm small{color:var(--slate);font-weight:500}
.eqrow input{min-width:0;text-align:right}
.eqrow .eqtt{text-align:right;font-weight:700;color:var(--ink);white-space:nowrap}
.eqx{font-style:normal;font-weight:700;color:var(--slate);text-align:center}
.eqrow.eqcong{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-3);
  padding-top:var(--space-2);border-top:1px solid var(--line)}
.eqcong-t{font-size:12.5px;color:var(--slate)}
.eqrow.eqcong .eqtt{font-size:16px;font-weight:800}
/* "Giao thực tế" là thông tin để bốc hàng, không phải cảnh báo — dòng chữ thường, không khung cam */
.pt-giao{font-size:12.5px;line-height:1.5;color:var(--slate);overflow-wrap:anywhere}
.pt-giao strong{color:var(--ink);font-weight:600}

/* ≥ 561px (máy tính bảng, máy tính): BẢNG — nhãn cột in MỘT lần ở hàng đầu, dấu × = ẩn đi */
@media (min-width:561px){
  .eqrow{grid-template-columns:minmax(0,1fr) 64px 104px 104px 32px;column-gap:var(--space-2);min-height:44px}
  .eqx{display:none}
  .eqrow.eqhd{min-height:0;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--slate)}
  .eqrow.eqhd span{white-space:nowrap}
  .eqrow.eqhd span.r{text-align:right}
  .eqrow input{padding:6px 8px}
  .eqrow .eqbo{width:32px;height:32px;min-height:0;padding:0}
}
/* ≤ 560px (điện thoại): THẺ hai dòng — tên + ✕ ở dòng 1, câu tính tiền ở dòng 2. Xếp cột theo
   CLASS, không bao giờ theo nth-of-type (bài học b292: nth-of-type đếm theo TÊN THẺ). */
@media (max-width:560px){
  .eqrow.eqhd{display:none}
  .eqrow{grid-template-columns:56px 12px 96px 12px minmax(0,1fr) 44px;grid-template-rows:20px 44px;
    column-gap:var(--space-1);row-gap:var(--space-2);padding:var(--space-2) 0 var(--space-2) var(--space-3);
    border:1px solid var(--line);border-radius:var(--r);background:var(--paper)}
  .eqrow+.eqrow{margin-top:var(--space-2)}
  .eqrow .eqnm{grid-column:1/6;grid-row:1;line-height:20px}
  .eqrow .eqbo{grid-column:6;grid-row:1;width:44px;height:44px;margin:-12px 0;justify-self:end;padding:0}
  .eqrow .eqo-sl>input{grid-column:1;grid-row:2}
  .eqrow .eqx-x{grid-column:2;grid-row:2}
  .eqrow .eqo-gia>input{grid-column:3;grid-row:2}
  .eqrow .eqx-b{grid-column:4;grid-row:2}
  .eqrow .eqo-tt>.eqtt{grid-column:5/7;grid-row:2;padding-right:var(--space-3);font-size:16px}
  .eqrow input{height:44px;padding:0 var(--space-2)}
  .eqrow.eqcong{margin-top:var(--space-2);padding:var(--space-2) var(--space-1) 0;
    border:0;border-top:1px solid var(--line);border-radius:0;background:none}
}

/* ---- khối gấp: bốn ô ít dùng, luôn ở CUỐI phiếu ---- */
.pt-them{border-top:1px solid var(--line);padding-top:var(--space-2)}
.pt-them>summary{
  cursor:pointer;list-style:none;font-size:12.5px;font-weight:700;color:var(--slate);
  display:flex;align-items:center;gap:6px;min-height:32px;
}
.pt-them>summary::-webkit-details-marker{display:none}
.pt-them>summary::before{content:'▸';font-size:12px;color:var(--slate)}
.pt-them[open]>summary::before{content:'▾'}
@media (hover:hover){ .pt-them>summary:hover{color:var(--ink)} }
.pt-them-o{display:flex;flex-direction:column;gap:var(--space-3);margin-top:var(--space-2)}

/* ---- chân phiếu: MỘT con số "Khách trả hôm nay" (b276) ---- */
.m-ft .rsum{
  flex:1 1 100%;order:-1;min-width:0;
  display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-1) var(--space-4);
  padding-bottom:var(--space-2);border-bottom:1px solid var(--line);
}
.rsum .rs-b{font-size:12.5px;color:var(--slate)}
.rsum strong{font-size:16px;font-weight:800;color:var(--ink)}

/* ---- MÁY TÍNH ≥ 1101px: hai vùng, vừa MỘT màn 1366×768 (luật b268) ----
   trái = người thuê + ngày + Thêm · phải = thiết bị + tiền (tiền nằm ngay trên nút Lưu). */
.modal:has(.phieuthue){max-width:660px}
@media (min-width:1101px){
  .modal:has(.phieuthue){max-width:1120px}
  .phieuthue{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);grid-template-rows:auto 1fr;
    column-gap:var(--space-5);row-gap:var(--space-3);align-items:start}
  .pt-tin{grid-column:1;grid-row:1}
  .pt-phai{grid-column:2;grid-row:1/3}
  .pt-them{grid-column:1;grid-row:2}
  .pt-vc{grid-template-columns:minmax(0,1fr) 148px}
  /* cọc đứng dưới tiền vận chuyển (hai ô tiền thẳng một cột), nút "Hình thức trả" bên trái */
  .pt-coc{grid-template-columns:minmax(0,1fr) 148px}
  .pt-coc>.o-tien{grid-column:2;grid-row:1}
  .pt-coc>.f-ht{grid-column:1;grid-row:1}
  .modal:has(.phieuthue) .m-ft .rsum{flex:1 1 auto;order:0;margin-right:auto;border-bottom:0;padding-bottom:0}
}

/* ---- ĐIỆN THOẠI ≤ 880px: phiếu CHIẾM TRỌN màn (Material: hộp có ô gõ, lưu khi bấm Lưu) ----
   Trước b295 hộp nổi cách mép 20px, cao 90% màn: khung thấy được 580/844px (69%). */
@media (max-width:880px){
  .ov:has(.phieuthue){padding:0;place-items:stretch}
  .modal:has(.phieuthue){max-width:none;width:100%;height:100dvh;max-height:100dvh;border-radius:0}
  .modal:has(.phieuthue) .m-hd{border-radius:0;padding-top:max(15px,env(safe-area-inset-top))}
  .modal:has(.phieuthue) .m-bd{padding:var(--space-4)}
  .modal:has(.phieuthue) .m-ft{padding:var(--space-3) var(--space-4) max(var(--space-3),env(safe-area-inset-bottom))}
  .modal:has(.phieuthue) .m-ft .btn{min-height:44px}
  .modal:has(.phieuthue) .m-hd .icobtn{width:44px;height:44px}
  .pt-vc,.pt-coc{grid-template-columns:minmax(0,1fr)}
  .phieuthue .o-tien input{max-width:220px}
  .phieuthue .f input{min-height:44px;font-size:16px}
  .phieuthue .seg{height:44px;font-size:14px}
  .phieuthue .sect-act .btn{min-height:44px}
  .pt-them>summary{min-height:44px}
}

/* ═══ b276 · BỘ CHỌN THIẾT BỊ TRONG PHIẾU THUÊ ═══
   Nằm trong chính phiếu (không modal lồng), nên phải tự giới hạn chiều cao —
   danh sách dài thì cuộn trong khối, phần còn lại của phiếu vẫn thấy. */
.eqpick{border:1px solid var(--line);border-radius:12px;background:var(--sky-50);padding:10px;margin-bottom:10px}
/* b280 · anh Đạt soi ảnh: viền cam lúc gõ vẽ lên chính <input> bên trong, lệch với khung bo
   tròn bên ngoài → hai hình chữ nhật lệch nhau. Nay KHUNG là ô nhập: input không viền, không
   vòng focus riêng; khung đổi viền cam khi có con trỏ (:focus-within). Một hình, một viền. */
.eqpick-q{display:flex;align-items:center;gap:10px;height:44px;background:var(--paper);border:1px solid var(--line);
  border-radius:10px;padding:0 12px;margin-bottom:8px;transition:border-color var(--m-1,120ms)}
.eqpick-q:focus-within{border-color:var(--or);box-shadow:0 0 0 1px var(--or),0 0 0 4px var(--or-50)}
.eqpick-q svg{width:18px;height:18px;flex:none;stroke:var(--slate);fill:none;stroke-width:2}
.eqpick-q input{border:0;background:transparent;padding:0;height:100%;flex:1;min-width:0;font-size:16px;box-shadow:none}
.eqpick-q input:focus,.eqpick-q input:focus-visible{outline:none;box-shadow:none;border:0}
/* align-content:start — b295: không có nó, lưới giãn các dòng cho đầy chiều cao khung → thẻ hở 37px */
.eqpick-ds{display:grid;gap:5px;align-content:start;max-height:34vh;overflow:auto;overscroll-behavior:contain}
/* b282 · anh Đạt 21/09 (ảnh phóng to dòng "Cây chống tăng"): *"chữ trong ô nên gọn gàng,
   cân bằng lại"*. Trước: tên + đơn vị chung dòng, giá chữ mono lẻ loi dòng dưới, ô tích
   treo góc trên. Nay HAI DÒNG CỐ ĐỊNH, hai cột thẳng hàng như danh sách món của Loyverse:
   dòng 1 = tên (đậm, một dòng cắt …) · giá (đậm, phải); dòng 2 = đơn vị · "mỗi ngày";
   ô tích đứng giữa cả hai dòng. Số dùng tabular-nums, không đổi font mono. Cao 56px. */
.eqpick-i{display:grid;grid-template-columns:22px minmax(0,1fr) auto;grid-template-rows:20px 16px;align-items:center;
  column-gap:10px;row-gap:2px;width:100%;height:56px;padding:9px 12px;border:1px solid var(--line);border-radius:10px;
  background:var(--paper);cursor:pointer;text-align:left;font:inherit;color:var(--ink);line-height:1}
.eqpick-i.on{border-color:var(--sky-700);background:var(--sky-100)}
/* :hover chỉ trên máy có chuột — trên điện thoại nút vừa chạm giữ :hover mãi, viền mờ đi như mất viền (ảnh anh 21/09) */
@media (hover:hover){ .eqpick-i:hover{border-color:var(--line-2)} }
.eqpick-tick{grid-row:1/3;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;
  border:1.5px solid var(--line-2);border-radius:6px;background:var(--paper)}
.eqpick-i.on .eqpick-tick{background:var(--sky-700);border-color:var(--sky-700)}
.eqpick-tick svg{width:13px;height:13px;stroke:#fff;fill:none;stroke-width:3}
/* b295 · món ĐÃ có dòng trong phiếu: nút khóa, tích xám — nhìn là biết, chạm không làm gì.
   Trước b295 tích được, nút ghi "Thêm 1 thiết bị" mà bấm không thêm gì. (chữ xám trên --bg: 4,74:1) */
.eqpick-i.da-co{background:var(--bg);border-color:var(--line);cursor:default}
.eqpick-i.da-co .eqpick-tick{background:var(--slate);border-color:var(--slate)}
.eqpick-i.da-co .eqpick-dv b{color:var(--ink)}
.eqpick-nm{grid-column:2;grid-row:1;min-width:0;font-size:15px;line-height:20px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.eqpick-gi{grid-column:3;grid-row:1;font-size:14px;line-height:20px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;text-align:right}
.eqpick-gi small{font-size:12.5px;font-weight:500;color:var(--slate)}
.eqpick-dv{grid-column:2;grid-row:2;min-width:0;font-size:12.5px;line-height:16px;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.eqpick-dv b{font-weight:600;color:var(--sky-700)}
.eqpick-ng{grid-column:3;grid-row:2;font-size:12.5px;line-height:16px;color:var(--slate);white-space:nowrap;text-align:right}
.eqpick-trong{padding:14px 4px;color:var(--slate);text-align:center}
.eqpick-ft{display:flex;gap:8px;justify-content:flex-end;margin-top:9px}
.eqpick-ft .btn{min-height:40px}
/* b280 · điện thoại: màn chọn thiết bị CHIẾM TRỌN hộp — phiếu và chân Hủy/Lưu tạm ẩn, nháp giữ nguyên
   trong RTMP (không mở hộp thứ hai). b295: ẩn theo KHỐI của khung mới, không theo thứ tự con. */
@media (max-width:880px){
  .modal.dang-chon .m-ft,.modal.dang-chon .pt-tin,.modal.dang-chon .pt-tien,.modal.dang-chon .pt-them,
  .modal.dang-chon .pt-hang>.sect,.modal.dang-chon #r_eqs,.modal.dang-chon #r_parts{display:none}
  .modal.dang-chon .m-bd{padding:0;overflow:hidden}   /* MỘT thanh cuộn: chỉ danh sách cuộn, thân hộp đứng yên */
  /* b295 · MỘT thanh tiêu đề: lúc chọn ẩn thanh "Lập phiếu cho thuê ✕" của hộp (trước hai thanh chồng nhau,
     75px + 48px). Hộp phiếu chiếm trọn màn nên bộ chọn cao đúng 100dvh. */
  .modal.dang-chon .m-hd{display:none}
  .modal.dang-chon .eqpick{display:flex;flex-direction:column;height:100dvh;padding:0;border:0;border-radius:0;background:var(--bg);margin:0}
  .eqpick-hd{display:grid;grid-template-columns:72px 1fr 72px;align-items:center;min-height:56px;
    padding:max(var(--space-1),env(safe-area-inset-top)) var(--space-2) var(--space-1);background:var(--paper);border-bottom:1px solid var(--line)}
  .eqpick-hd b{text-align:center;font-size:16px;white-space:nowrap}
  .eqpick-back{display:inline-flex;align-items:center;gap:4px;border:0;background:transparent;font:inherit;font-size:14px;font-weight:700;color:var(--or-safe);
    min-height:44px;padding:0 var(--space-1);white-space:nowrap}
  .eqpick-back svg{width:16px;height:16px}
  /* ô tìm dính đỉnh trên nền riêng, danh sách bắt đầu DƯỚI nó — cuộn lên không chui dưới ô tìm */
  .modal.dang-chon .eqpick-q{margin:10px 12px}
  .modal.dang-chon .eqpick-hd+.eqpick-q{position:relative;z-index:1}
  .modal.dang-chon .eqpick-ds{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:10px 12px 10px;max-height:none;gap:8px;border-top:1px solid var(--line)}
  .modal.dang-chon .eqpick-ft{position:sticky;bottom:0;margin:0;padding:10px 12px max(10px,env(safe-area-inset-bottom));background:var(--paper);border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 2fr;gap:8px}
  .modal.dang-chon .eqpick-ft .btn{width:100%;min-height:44px}
}
/* b295 · MÁY TÍNH đang chọn thiết bị: phần tiền và các dòng tạm ẩn, danh sách dùng chỗ đó; thân hộp KHÔNG
   cuộn. Trước: mở bộ chọn là thân hộp cuộn 185px, chỉ thấy 4/7 món ở 1366×768. Thẻ 48px (chuột, chuẩn
   24px) vẫn hai dòng như b282. Trần danh sách = hộp (100vh − 48px) trừ phần cố định đo được, xem
   tests/browser/b295-regressions.js T19. */
@media (min-width:881px){
  .modal:has(.phieuthue){max-height:calc(100vh - 48px)}
  .modal.dang-chon .pt-tien,.modal.dang-chon #r_eqs,.modal.dang-chon #r_parts,
  .modal.dang-chon .pt-hang>.sect-act>.btn{display:none}
  .eqpick-i{height:48px;padding-top:5px;padding-bottom:5px}
  .eqpick-ds{gap:4px}
  .modal.dang-chon .eqpick-ds{max-height:calc(100vh - 391px)}
}

/* ═══ b296 · HỘP "NHẬN LẠI HÀNG" (quyết toán phiếu thuê) — rentReturn · retCalc trong rentals.js ═══
   Máy tính: bảng 6 cột như cũ. Điện thoại ≤ 560px: mỗi thiết bị một THẺ — tên một hàng; Đã giao ·
   Trả lại · Thiếu/hỏng một hàng; Giá đền · Tiền đền một hàng. Trước b296 bảng làm thân hộp tràn ngang
   234px ở 428px (302px ở 360px): cột Thiếu/hỏng, Giá đền, Tiền đền và dòng "trả lại khách …" bị cắt. */
.rt-bang{max-height:280px}
.rt-bang input{text-align:right;padding:4px 6px}
.rt-bang .rt-tra input{width:74px}
.rt-bang .rt-gia input{width:96px}
@media (max-width:560px){
  .rt-bang{max-height:none;overflow:visible;border:0}
  .rt-bang table,.rt-bang tbody,.rt-bang tr,.rt-bang td{display:block}
  .rt-bang thead{display:none}
  .rt-bang tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
    grid-template-areas:"ten ten ten" "giao tra thieu" "gia gia den";gap:var(--space-2) var(--space-3);
    padding:var(--space-3);border:1px solid var(--line);border-radius:var(--r);background:var(--paper)}
  .rt-bang tr+tr{margin-top:var(--space-2)}
  .rt-bang td{padding:0;border:0;text-align:left;min-width:0}
  .rt-bang td{align-self:start}
  .rt-bang td::before{content:attr(data-nhan);display:block;font-family:var(--f-ui);font-size:12px;font-weight:700;letter-spacing:0;color:var(--slate);margin-bottom:2px;line-height:16px}
  .rt-bang .rt-ten{grid-area:ten;font-weight:700}
  .rt-bang .rt-ten::before{content:none}
  .rt-bang .rt-giao{grid-area:giao;line-height:44px}
  .rt-bang .rt-tra{grid-area:tra}
  .rt-bang .rt-thieu{grid-area:thieu;line-height:44px}
  .rt-bang .rt-gia{grid-area:gia}
  .rt-bang .rt-den{grid-area:den;line-height:44px;text-align:right}
  .rt-bang .rt-den::before{text-align:right}
  .rt-bang .rt-tra input,.rt-bang .rt-gia input{width:100%;min-height:44px;font-size:16px}
}

/* ===== SOURCE: styles/khoa-nhanh.css ===== */
/* ============================================================
   b300 · MÀN KHÓA NHANH 6 SỐ (frontend/khoa-nhanh.js) — b325 kiểu iPhone (mẫu anh duyệt: docs/thiet-ke/b325/khoa-mau.*)
   Nền tối TOÀN màn (bỏ thẻ trắng): tên người + "Nhập mật mã", 6 vòng rỗng tô dần, bàn phím 3×4 phím tròn 76px (số 32px) ở nửa dưới —
   đúng bàn phím mở khóa iPhone ai cũng quen tay; màn thấp / hẹp (320px, laptop 680px) phím 64px. Không ô nhập nào ⇒ điện thoại không
   bật bàn phím hệ thống. Máy tính gõ thẳng bằng bàn phím thật, bấm phím trên màn cũng được.
   Lúc khóa, app phía sau bị ẩn hẳn (visibility) chứ không làm mờ: mờ vẫn đọc được số to.
   ============================================================ */
body.khoa-on>.app,body.khoa-on>#ov,body.khoa-on>#saleFollow{visibility:hidden}
.khoa{
  position:fixed;inset:0;z-index:9500;display:flex;flex-direction:column;align-items:center;overflow-y:auto;overflow-x:hidden;
  padding:max(20px,env(safe-area-inset-top)) 16px max(12px,env(safe-area-inset-bottom));
  background:linear-gradient(180deg,#2A303A 0,#1A1D23 55%,#121418 100%);color:#fff;
}
.khoa:focus{outline:0}
.khoa button{font-family:inherit;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}
.khoa button:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* b325 · anh 28/09 "làm cao lên chút, thuận một tay": khối chữ + bàn phím đứng giữa phần trên (hai lề auto chia đều), dòng dưới cùng dính đáy —
   như iPhone: phím đầu ~36% chiều cao màn, phím 0 ~78% ⇒ ngón cái một tay với tới cả 12 phím */
.khoa-tren{flex:0 0 auto;margin-top:auto;display:flex;flex-direction:column;align-items:center;gap:10px;width:100%;max-width:360px;padding:8px 0 24px}
.khoa-dau{display:flex;align-items:center;gap:6px;max-width:100%;font-size:13px;font-weight:600;color:rgba(255,255,255,.72)}
.khoa-dau svg{flex:0 0 14px;width:14px;height:14px}
.khoa-dau span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.khoa-ten{margin:6px 0 0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:22px;font-weight:700;letter-spacing:-.2px;color:#fff}
.khoa-nhap{margin:0;font-size:17px;font-weight:500;color:rgba(255,255,255,.9)}
.khoa-cham{display:flex;gap:22px;margin-top:14px}
.khoa-cham i{width:14px;height:14px;border-radius:50%;border:1.5px solid #fff;box-sizing:border-box}
.khoa-cham i.co{background:#fff}
.khoa-cham.rung{animation:khoa-rung .4s ease-in-out}
@keyframes khoa-rung{20%{transform:translateX(-10px)}40%{transform:translateX(9px)}60%{transform:translateX(-6px)}80%{transform:translateX(3px)}}
.khoa-dem{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.khoa-loi{min-height:20px;margin:6px 0 0;text-align:center;font-size:14px;line-height:1.4;color:rgba(255,255,255,.8)}
.khoa-loi.loi{color:#FFB4A9}
.khoa-phim{flex:0 0 auto;margin-bottom:auto;display:grid;grid-template-columns:repeat(3,76px);grid-auto-rows:76px;gap:18px 24px;justify-content:center}
.khoa-so{width:76px;height:76px;padding:0;border:0;border-radius:50%;background:rgba(255,255,255,.16);color:#fff;
  font-size:32px;font-weight:400;display:grid;place-items:center}
.khoa-so:active{background:rgba(255,255,255,.34)}
@media (hover:hover){.khoa-so:hover{background:rgba(255,255,255,.24)}}
.khoa-so.khoa-xoa{background:transparent;font-size:16px;font-weight:500}
.khoa-duoi{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:6px;width:100%;max-width:380px;margin-top:18px}
.khoa-nguoi{display:flex;justify-content:center;gap:8px;max-width:100%;overflow-x:auto;scrollbar-width:none}
.khoa-ng{flex:0 0 auto;display:flex;align-items:center;gap:6px;min-height:44px;max-width:180px;padding:0 12px 0 6px;border:0;border-radius:22px;
  background:rgba(255,255,255,.1);color:rgba(255,255,255,.88);font-size:13px;font-weight:600}
.khoa-ng b{display:grid;place-items:center;flex:0 0 30px;width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.18);font-size:13px}
.khoa-ng span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.khoa-ng[aria-pressed="true"]{background:rgba(255,255,255,.24);color:#fff}
.khoa-mk{min-height:44px;padding:0 12px;border:0;background:transparent;color:rgba(255,255,255,.8);font-size:13px;font-weight:600}
@media (hover:hover){.khoa-mk:hover{text-decoration:underline}}
/* 320px, điện thoại xoay ngang, laptop màn thấp: phím 64px, bỏ dòng tên tiệm cho đủ chỗ */
@media (max-width:359px),(max-height:680px){
  .khoa-phim{grid-template-columns:repeat(3,64px);grid-auto-rows:64px;gap:12px 22px}
  .khoa-so{width:64px;height:64px;font-size:28px}
  .khoa-tren{gap:6px;padding:0 0 10px}
  .khoa-dau{display:none}
  .khoa-cham{margin-top:8px}
  .khoa-duoi{gap:2px;margin-top:10px}
}
/* chữ LỚN: phóng theo (styles/co-chu.css) */
body.big .khoa-ten{font-size:26px}
body.big .khoa-nhap{font-size:20px}
body.big .khoa-so{font-size:36px}
body.big .khoa-so.khoa-xoa{font-size:18px}
body.big .khoa-dau,body.big .khoa-ng,body.big .khoa-ng b,body.big .khoa-mk{font-size:15px}
body.big .khoa-loi{font-size:16px}
/* hộp đặt mã */
.khoa-giai{margin:0 0 var(--space-3);color:var(--ink-2);line-height:1.5}
.khoa-o{letter-spacing:.35em;font-size:20px}
.khoa-bo{margin-top:var(--space-3)}
@media (prefers-reduced-motion:reduce){.khoa-cham.rung{animation:none}}

/* ===== SOURCE: styles/dat-hang.css ===== */
/* ============================================================
   b301 · ĐẶT HÀNG · BÁO GIÁ (frontend/dat-hang.js) + CA BÁN (frontend/ca-ban.js)
   Dựng trên khối sẵn có (kpis · panel · inv-tbl · mcard · trow · fchip · note) — chỉ thêm phần riêng.
   Cam chỉ cho số cần chú ý (tiền còn phải thu, cọc đang giữ, tổng báo giá); còn lại xám mực như các màn khác.
   ============================================================ */

/* ── danh sách ── */
.dh-bang .dh-so{white-space:nowrap}
.dh-bang .dh-hang{max-width:280px;font-size:12.5px;line-height:1.45;color:var(--slate)}
.dh-bang tr.clk{cursor:pointer}
.dh-the{cursor:pointer}
.dh-the-tt{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px}
.dh-coc{font-size:12.5px;font-weight:700;color:var(--or-safe)}
.dh-loc .fchips{flex:1 1 auto;justify-content:flex-end}

/* chữ phụ XUỐNG DÒNG được (khác .cell-sub của bảng: một dòng, cắt "…") — câu giải thích trong hộp không bao giờ bị cắt */
.dh-phu{margin:0;font-size:12.5px;line-height:1.5;color:var(--slate)}
span.dh-phu{display:inline}
.dh-chon-o span.dh-phu,.dh-dong .dh-phu{display:block}

/* ── chi tiết một phiếu ── */
.dh-ct{display:flex;flex-direction:column;gap:var(--space-3)}
.dh-so-nhanh{display:flex;flex-wrap:wrap;gap:6px 18px;font-size:13.5px;color:var(--slate)}
.dh-so-nhanh b{margin-left:4px;font-size:16px;color:var(--ink)}
.dh-so-nhanh .dh-con-thu b{color:var(--or-safe)}
.dh-acts{display:flex;flex-wrap:wrap;gap:var(--space-2)}
.dh-acts .btn{min-height:40px}
.dh-dau{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.dh-khach{display:grid;gap:4px;padding:10px 12px;border:1px solid var(--line-2);border-radius:var(--r);background:var(--sky-50);font-size:14px;line-height:1.5}
.dh-khach>div{display:grid;grid-template-columns:78px minmax(0,1fr);align-items:baseline}
.dh-nhan{color:var(--slate);font-size:12.5px}
.dh-dong td{vertical-align:top}
.dh-dong-dt{list-style:none;margin:0;padding:0;border-top:1px solid var(--line-2)}
.dh-dong-dt li{padding:10px 0;border-bottom:1px solid var(--line-2)}
.dh-dt-ten{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:14.5px}
.dh-dt-ten .num{flex:0 0 auto;font-weight:700}
.dh-tien{display:grid;gap:2px;width:min(380px,100%);margin-left:auto}
.dh-tien .trow{font-size:13.5px}
.dh-tien .trow.tot{text-transform:none;letter-spacing:0;font-size:13px}
.dh-tien .dh-giu .num{color:var(--or-safe);font-weight:700}
.dh-tien .dh-con{padding-top:6px;margin-top:4px;border-top:1px dashed var(--line);color:var(--ink);font-weight:700}
.dh-tien .dh-con .num{font-size:17px;color:var(--or-safe)}
.dh-tien p{margin:4px 0 0}
.dh-h{margin:6px 0 2px;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--slate)}
.dh-so-coc,.dh-hd{list-style:none;margin:0;padding:0;display:grid;gap:4px}
.dh-so-coc li,.dh-hd li{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:6px 0;border-bottom:1px solid var(--line-2);font-size:13.5px}
.dh-so-coc .dh-am{color:var(--red)}
.dh-link{border:0;background:none;padding:0;font:inherit;font-weight:700;color:var(--sky-700);text-decoration:underline;cursor:pointer}

/* ── hộp lưu từ phiếu bán: một khuôn, hai loại (báo giá / đơn đặt) ── */
.dh-form{display:flex;flex-direction:column;gap:var(--space-3)}
.dh-form[data-loai="quote"] .dh-dd,.dh-form[data-loai="order"] .dh-bg{display:none}
.dh-loai{display:grid;grid-template-columns:repeat(2,minmax(0,max-content));gap:8px}
.dh-loai .fchip{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:8px 14px;border-radius:var(--r);text-align:left}
.dh-loai .fchip .cell-sub{font-size:12.5px;white-space:normal;overflow:visible}
.dh-loai .fchip.on .cell-sub{color:#E7EAEE}
.dh-tomtat{font-size:14px}
.dh-goi{margin:0;font-size:13.5px;line-height:1.55;color:var(--ink-2)}
.dh-kh{display:block;padding:8px 0;font-size:14px}

/* ── lựa chọn dạng thẻ (trả / giữ cọc, rút / nộp két) ── */
.dh-chon{display:grid;gap:8px}
.dh-chon-o{display:flex;align-items:flex-start;justify-content:flex-start;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r);cursor:pointer;line-height:1.45;text-align:left}
.dh-chon-o>span{flex:1 1 auto;min-width:0}
/* ô tích / ô chọn: foundation.css cho MỌI input width:100% + viền + đệm — trả về đúng cỡ nút */
.dh-chon-o input,.dh-tick input{flex:0 0 18px;width:18px;height:18px;min-height:0;margin:3px 0 0;padding:0;border:0;box-shadow:none;accent-color:var(--sky-900)}
.dh-chon-o:has(input:checked){border-color:var(--sky-700);background:var(--sky-50)}
.dh-chon-o .cell-sub{display:block}

/* ── giao một chuyến ── */
.dh-giao .dh-sl{width:110px;text-align:right;font-weight:700}
.dh-giao-bar{display:flex;flex-wrap:wrap;gap:8px;margin:var(--space-2) 0}
.dh-giao-duoi{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,380px);gap:var(--space-4);align-items:start;margin-top:var(--space-2)}
.dh-giao-trai{display:flex;flex-direction:column;gap:var(--space-2)}
.dh-giao-duoi .dh-tien{width:100%}
.dh-tick{display:flex;align-items:center;gap:10px;min-height:44px;font-size:14px;cursor:pointer}
.dh-tick input{margin:0}

/* (b304) nút "Báo giá · Đặt" dưới phiếu bán: chân phiếu còn hai nút phụ ("Xóa hết" vào ⋯ đầu phiếu) — hết lưới 3 cột. */

/* ── ca bán ── */
.ca-truoc{padding:10px 12px;border-radius:var(--r);background:var(--sky-50);font-size:13.5px;line-height:1.6}
.ca-goi{display:block;min-height:22px;font-size:13px}
.ca-ct{display:flex;flex-direction:column;gap:var(--space-3)}
.ca-kpi{margin-bottom:0}
.ca-hai{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4)}
.ca-hai .trow{font-size:13.5px}
.ca-ck{margin-top:6px;padding-top:6px;border-top:1px dashed var(--line)}
.ca-ds .inv-tbl td{vertical-align:top}
.ca-chieu{grid-template-columns:1fr 1fr}

@media (max-width:880px){
  .dh-tien{width:100%}
  .dh-giao-duoi{grid-template-columns:1fr}
  .dh-loai{grid-template-columns:1fr 1fr}
  .dh-loc .fchips{justify-content:flex-start}
  .ca-hai{grid-template-columns:1fr}
  .dh-acts .btn{flex:1 1 auto}
  .dh-giao .dh-sl{width:88px}
}

/* ── in A4 (khuôn .p-inv của app) ── */
@media print{
  .p-inv .dh-c{text-align:center}
  .p-inv .dh-r{text-align:right}
  .p-inv .dh-w6{width:6%}
  .p-inv .dh-w9{width:9%}
  .p-inv .dh-w15{width:15%}
  .p-inv .dh-w17{width:17%}
  .p-inv .dh-in-ten{font-size:14pt}
  .p-inv .dh-in-gc{font-size:8.5pt;font-style:italic;color:#333}
  .p-inv .dh-in-vat{margin-top:2mm;font-size:9.5pt}
  .p-inv .dh-in-gc2{margin-top:2mm;font-size:9.5pt}
  .p-inv .dh-in-nh{margin-top:3mm;padding:2mm 3mm;border:1px solid #000;font-size:10pt}
  .dh-in .p-sign em{font-size:9pt}
}

/* ===== SOURCE: styles/tich-hop.css ===== */
/* ============================================================
   b306 · TÍCH HỢP — hóa đơn điện tử · tiền CK tự báo · sổ hộ kinh doanh (frontend/tich-hop.js, gói tải sau) +
   ba chỗ ở gói chính: huy hiệu HĐĐT trên dòng hóa đơn, dòng HĐĐT trong hộp hóa đơn, dải "HĐ cho …" dưới khách ở phiếu bán.
   Dựng trên khối sẵn có (tag · note · fgrid · btn) — chỉ thêm phần riêng. Chỗ bấm điện thoại 44px ở cham-dien-thoai.css
   đã phủ .btn / input trong hộp; dải người mua ở phiếu bán tự đặt 44px (mobile-runtime.css).
   ============================================================ */

/* ── huy hiệu + dòng HĐĐT ── */
.hd-tag{margin-left:6px;padding:0 6px;font-size:12px;font-style:normal;font-family:var(--f-ui);vertical-align:1px}
.hd-o{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;margin:0 0 14px;padding:8px 12px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--sky-50);font-size:13.5px}
.hd-o svg,.mua-chu svg{width:15px;height:15px;vertical-align:-2px;margin-right:4px}
.hd-dong{padding:10px 0;border-bottom:1px solid var(--line);font-size:13.5px;line-height:1.5}
.hd-dau{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px}
.hd-phu{font-size:12.5px;color:var(--slate);overflow-wrap:anywhere}
.hd-loi{color:var(--red)}
.hd-tay{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px}
.hd-tay input{flex:1 1 150px;min-width:0;height:34px}
.hd-mua{margin-top:14px}
.hd-in{margin-top:2mm;font-size:9.5pt}
.th-chk{display:flex;align-items:flex-start;gap:8px;font-size:13px;line-height:1.45;color:var(--ink-2)}
/* ô tích 17px — luật chung input{width:100%} làm ô tích chiếm cả dòng, đẩy chữ ra ngoài hộp (ảnh b306 Cài đặt HĐĐT) */
.th-chk input{flex:0 0 auto;width:17px;height:17px;margin-top:2px;accent-color:var(--or-6);cursor:pointer}

/* ── hộp QR: tiền về ── */
.qr-ck{margin-top:10px;font-size:13.5px}
.qr-ck .btn{margin-top:6px}
.ck-cho{color:var(--slate)}
.ck-da{font-size:16px;font-weight:800;color:var(--green)}
.ck-da svg{width:18px;height:18px;vertical-align:-3px;margin-right:4px}

/* ── dải người mua lấy hóa đơn (phiếu bán) ── */
.mua-hd{display:flex;align-items:center;gap:4px;margin-top:6px;padding:2px 2px 2px 10px;border-radius:var(--r-sm);background:var(--sky-50);
  font-size:12.5px;color:var(--slate)}
.mua-chu{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mua-chu b{color:var(--ink)}
.mua-nut{flex:0 0 auto;width:28px;height:28px;display:grid;place-items:center;border-radius:6px;color:var(--slate-2)}
.mua-nut:hover{background:#fff;color:var(--ink)}
.mua-nut svg{width:14px;height:14px}

/* điện thoại: nút sửa / bỏ người mua đủ 44px (luật chỗ bấm của phiếu bán) */
@media (max-width:880px){
  .mua-nut{width:44px;height:44px}
  .hd-tay input{height:44px;font-size:16px}   /* ô "Số hóa đơn đã lập" / "Số hóa đơn để gắn" */
}
/* b319 · Cài đặt → Nhận tiền — QR: kiểu QR (hai nút chọn) + QR cố định đã đọc từ ảnh */
.qr-kieu-hang{display:flex;flex-wrap:wrap;gap:8px}
.qr-kieu{min-height:44px;padding:8px 14px;border-radius:var(--r);border:1.5px solid var(--line);background:var(--paper);color:var(--ink);font-size:14px;font-weight:700}
.qr-kieu.on{border-color:#173247;background:#173247;color:#fff}
.qr-cd{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.qr-cd-xem{display:flex;align-items:center;gap:12px}
.qr-cd-ma{flex:0 0 auto;width:120px;height:120px}
.qr-cd-ma svg{width:100%;height:100%;display:block}
.qr-cd-tt{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:14px}
.qr-cd-tt b{font-size:16px}
.qr-tai{align-self:flex-start;min-height:44px}
.qr-loi{color:var(--red);font-size:14px;font-weight:600}

/* ===== SOURCE: styles/nganh.css ===== */
/* ============================================================
   nganh.css · b308 · HỒ SƠ NGÀNH — thẻ Ngành trong Cài đặt, bảng dòng (sỉ), bảng model (điện máy).
   Màu, cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md (thang t0–t6, biến màu có sẵn). Thẻ hàng .grid-p/.pcard ở the-hang.css.
   ============================================================ */
.ng-luoi{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:10px 0 8px}
.ng-the{position:relative;min-height:76px;padding:12px 12px 10px;border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;
  text-align:left;display:flex;flex-direction:column;gap:4px;cursor:pointer;font-family:var(--f-ui);color:var(--ink)}
.ng-the b{font-size:14px;font-weight:800;line-height:1.3}
.ng-the span{font-size:12.5px;color:var(--slate);line-height:1.35}
.ng-the[aria-pressed="true"]{border:2.5px solid var(--sky-900);box-shadow:0 0 0 3px rgba(24,27,32,.08)}
.ng-the[aria-pressed="true"] b{padding-right:28px}
.ng-the[aria-pressed="true"]::after{content:"✓";position:absolute;top:9px;right:10px;width:22px;height:22px;border-radius:50%;
  background:var(--sky-900);color:#fff;display:grid;place-items:center;font-size:12.5px;font-weight:800}
.ng-sap{margin:0 0 6px;font-size:12.5px;color:var(--slate)}
.ng-nhan{font:800 12px var(--f-ui);letter-spacing:.05em;color:var(--or-safe);background:var(--or-50);padding:2px 8px;border-radius:99px}
.ng-h{margin:16px 0 6px;font-size:14px;font-weight:800}
.ng-ds{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
/* b310 · công tắc quán gấp một mục (ngành khác không thấy bày ra) */
.ng-quan{margin-top:10px}
.ng-quan summary{min-height:44px;display:flex;align-items:center;gap:8px;font-size:15px;font-weight:700;cursor:pointer}
.ng-quan .ng-ds{margin-top:6px}
.ng-tn{display:flex;gap:10px;align-items:flex-start;min-height:44px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg);
  background:#fff;text-align:left;cursor:pointer;font-family:var(--f-ui);color:var(--ink)}
.ng-cong{flex:0 0 auto;width:36px;height:20px;margin-top:1px;border-radius:99px;background:var(--line);position:relative;transition:background .12s}
.ng-cong::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;transition:left .12s}
.ng-tn[aria-checked="true"] .ng-cong{background:var(--sky-900)}
.ng-tn[aria-checked="true"] .ng-cong::after{left:18px}
.ng-tn:focus-visible,.ng-the:focus-visible{outline:3px solid var(--or);outline-offset:2px}
.ng-tn-c{display:flex;flex-direction:column;gap:2px;font-size:14px}
.ng-mo{font-size:12.5px;color:var(--slate);line-height:1.35}
.ng-luu{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
.ng-bang{width:100%;border-collapse:collapse;background:#fff;font-size:14px}
.ng-bang th{font-size:12.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--slate);text-align:left;padding:8px;border-bottom:1px solid var(--line)}
.ng-bang td{padding:9px 8px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.ng-bang .r{text-align:right}
.ng-sl{width:9ch;height:36px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;text-align:right;font:inherit}
.ng-sl:focus{outline:3px solid rgba(169,71,4,.25);border-color:var(--or)}
/* nhập từ app khác (màn Dữ liệu, gói nhap-xuat) */
.nk-bd{padding-top:0}
.nk-hang{display:flex;gap:9px;flex-wrap:wrap;margin-top:10px}
.nk-tom{margin:10px 0;font-size:14px}
.nk-loi{width:100%;border-collapse:collapse;font-size:13px;margin-top:8px}
.nk-loi th,.nk-loi td{text-align:left;padding:6px 8px;border-bottom:1px solid var(--line-2);vertical-align:top}
.nk-loi th{font-size:12.5px;color:var(--slate);text-transform:uppercase;letter-spacing:.04em}
@media (max-width:880px){
  .nk-hang .btn{flex:1 1 100%;min-height:44px}
  .ng-luoi{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ng-ds{grid-template-columns:1fr}
  .ng-the{min-height:84px}
  .ng-sl{height:44px;font-size:16px}
}
/* b326 · Cài đặt → Dạy từ (frontend/nganh.js · dayTu…, chỉ chủ sổ Thanh Hiền): dòng "chữ → nghĩa" + Sửa / Xóa — điện thoại nút vẫn bên phải, chạm ≥ 44px
   (.modal .btn ở cham-dien-thoai.css). Hộp "Dạy từ mới" là lớp phủ thứ hai trên hộp Cài đặt, như #hoibo. */
#dt_hop{z-index:90}
.dt-chu{margin:0;font-size:13.5px;line-height:1.5;color:var(--slate)}
.dt-hop>label{margin-top:14px}
.dt-o{width:100%;max-width:320px}
.dt-go{max-width:260px}
.dt-ra{margin:6px 0 0;font-size:13px;line-height:1.45;color:var(--slate);overflow-wrap:anywhere}
.dt-ra b{color:var(--ink)}
.dt-tim{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.dt-tim .dt-o{flex:1 1 180px}
.dt-ds{list-style:none;margin:12px 0 0;padding:0;display:grid;gap:8px}
.dt-dong{display:flex;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r)}
.dt-tt{flex:1;min-width:0}
.dt-ten{font-size:14.5px;line-height:1.4;color:var(--ink);overflow-wrap:anywhere}
.dt-phu{margin-top:2px;font-size:12.5px;color:var(--slate)}
.dt-rong{padding:12px;font-size:14px;color:var(--slate)}

/* ===== SOURCE: styles/don-vi.css ===== */
/* ============================================================
   don-vi.css · b309 · ĐỢT 3 — đơn vị quy đổi · kích thước · lô + hạn · bảng giá.
   Dòng phiếu: chữ kích thước (.kt-dong đi cùng .ghi) và nhãn lô (.lo-chip). Hộp dài × rộng, chọn lô, màn Bảng giá, báo hạn,
   form đơn vị: gói tải sau don-vi. Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md (biến có sẵn, không thêm mã màu).
   ============================================================ */
.item .nm .kt-dong{color:var(--slate)}
.lo-chip{display:inline-block;max-width:100%;margin-top:3px;padding:1px 8px;border-radius:6px;background:var(--sky-50);border:1px solid var(--line);
  font-size:12px;font-weight:600;color:var(--slate);line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:top}
.lo-chip.het{background:var(--red-soft);border-color:var(--red);color:var(--red)}
/* hộp kích thước */
/* một hàng = dài × rộng × số tấm + nút bỏ; lưới co theo bề ngang hộp (320px không cuộn ngang · KĐL máy bán 13) */
.kt-ds{display:flex;flex-direction:column;gap:8px;margin:6px 0 10px}
.kt-hang{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr) auto minmax(0,.8fr) 44px;align-items:center;gap:6px}
.kt-hang.dai{grid-template-columns:minmax(0,1fr) auto minmax(0,.8fr) 44px}
.kt-hang input{width:100%;min-width:0;height:40px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;text-align:right;font:inherit}
.kt-hang span{color:var(--slate);font-weight:700}
.kt-dau{font-size:12px;letter-spacing:.02em}
.kt-bo{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--slate)}
.kt-bo svg{width:16px;height:16px}
.dl-kt{font-size:8.5pt;font-style:italic}
.kt-tong{margin:10px 0 0;font-size:16px;font-weight:800;color:var(--ink)}
/* chọn lô */
.lo-ds{display:flex;flex-direction:column;gap:8px}
.lo-the{display:flex;flex-direction:column;gap:2px;min-height:48px;padding:9px 12px;border:1.5px solid var(--line);border-radius:var(--r-lg);
  background:#fff;text-align:left;cursor:pointer;font-family:var(--f-ui);color:var(--ink)}
.lo-the b{font-size:14px;font-weight:800}
.lo-the span{font-size:12.5px;color:var(--slate)}
.lo-the.on{border:2.5px solid var(--sky-900)}
.lo-the.sap span{color:var(--or-safe)}
.lo-the.het{border-color:var(--red)}
.lo-the.het span{color:var(--red)}
.lo-the:focus-visible{outline:3px solid var(--or);outline-offset:2px}
/* phiếu nhập kho: số lô ngắn — bề rộng theo chữ sẽ gõ */
.f input.w-lo{max-width:22ch}
/* bảng giá · báo hạn */
.bg-ds{display:flex;flex-direction:column;gap:8px;margin:10px 0 12px}
.bg-the{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.bg-the div{display:flex;flex-direction:column;gap:2px}
.bg-bang{width:100%;border-collapse:collapse;background:#fff;font-size:14px}
.bg-bang th{font-size:12.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--slate);text-align:left;padding:8px;border-bottom:1px solid var(--line)}
.bg-bang td{padding:8px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.bg-bang .r{text-align:right}
.bg-bang input,.bg-bang select{height:36px;border:1.5px solid var(--line);border-radius:8px;padding:0 8px;font:inherit}
.bg-bang input{width:12ch;text-align:right}
.bg-bang tr.het td{color:var(--red)}
.bg-bang input.w-lo{text-align:left}
.bg-bang input[type=date]{width:auto;text-align:left}
.bg-bang .o-ngay-k{width:auto;max-width:none}   /* b324 · khung ô ngày (ngayVN) ôm đúng ô rộng-theo-chữ */
.bg-them{display:flex;gap:8px;margin-top:8px}
.bg-them input{flex:1;min-width:0;height:40px;border:1.5px solid var(--line);border-radius:8px;padding:0 10px;font:inherit}
/* form hàng: đơn vị quy đổi thêm */
.dv-dong{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,.9fr) minmax(0,1fr) minmax(0,1.2fr) auto 44px;align-items:end;gap:6px;
  margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid var(--line-2)}
.dv-o{display:flex;flex-direction:column;gap:3px;min-width:0}
.dv-o span{font-size:12px;font-weight:700;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dv-dong input{min-width:0;height:40px;border:1.5px solid var(--line);border-radius:8px;padding:0 8px;font:inherit}
.dv-ban{display:flex;align-items:center;gap:6px;min-height:44px;font-size:13px;font-weight:600;color:var(--ink-2)}
.f input.w-pct{max-width:10ch}
@media (max-width:880px){
  .kt-hang input{height:44px;font-size:16px}
  .bg-bang{table-layout:fixed}
  .bg-bang td{word-break:break-word}
  .bg-bang .bg-dv{width:28%}
  .bg-bang .bg-gia{width:30%}
  .bg-bang .bg-bo{width:52px}
  .bg-bang input,.bg-bang select{width:100%;min-width:0}
  .lo-the{min-height:52px}
  .bg-bang input,.bg-bang select{height:44px;font-size:16px}
  .bg-them input{height:44px;font-size:16px}
  .dv-dong{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  /* bảng giá trên điện thoại: mỗi dòng một thẻ — tên hàng trọn hàng trên, đơn vị · giá · bỏ hàng dưới */
  .gia-bang thead{display:none}
  .gia-bang tr{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) 44px;gap:6px;align-items:center;padding:8px 0;border-bottom:1px solid var(--line-2)}
  .gia-bang td{padding:0;border:0}
  .gia-bang td.bg-ten{grid-column:1/-1}
  .dv-dong .kt-bo{justify-self:end}
  .dv-dong input{height:44px;font-size:16px}
}

/* ===== SOURCE: styles/quan.css ===== */
/* ============================================================
   quan.css · b310 · QUÁN MANG ĐI + TIỆM BÁNH — hộp tùy chọn món, menu quán (dải nhóm món), cài tùy chọn, bánh cần làm,
   phiếu pha chế + tem ly (in). Dòng phiếu / phiếu in chỉ thêm một dòng chữ tùy chọn (.tc-dong, .p-tc) và số thứ tự (.stt).
   Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md (biến có sẵn, không thêm mã màu). Chỗ bấm ≥ 44px.
   ============================================================ */
.item .nm .tc-dong{color:var(--slate)}
/* hộp chọn tùy chọn */
.qn-chon{display:flex;flex-direction:column;gap:12px}
.qn-gia{margin:0;font-size:14px;color:var(--slate)}
.qn-gia b{color:var(--ink);font-weight:800}
.qn-nhom{margin:0;padding:0;border:0;min-width:0}
.qn-nhom legend{padding:0;margin-bottom:6px;font-size:15px;font-weight:700;color:var(--ink)}
.qn-luat{font-size:12.5px;font-weight:400;color:var(--slate)}
.qn-luat b{color:var(--or-safe);font-weight:700}
.qn-chips{display:flex;flex-wrap:wrap;gap:8px}
.qn-chip{display:inline-flex;flex-direction:column;align-items:flex-start;justify-content:center;min-height:48px;min-width:88px;max-width:100%;padding:6px 12px;
  border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;color:var(--ink);font:inherit;font-size:14.5px;font-weight:600;text-align:left;cursor:pointer}
.qn-chip span{overflow-wrap:anywhere}
.qn-chip small{font-size:12.5px;font-weight:700;color:var(--slate)}
.qn-chip.on{border:2.5px solid var(--sky-900);background:var(--sky-50);padding:5px 11px}
.qn-chip.on small{color:var(--sky-900)}
.qn-chip:focus-visible,.qn-sl-b:focus-visible,.qn-tab:focus-visible{outline:3px solid var(--or);outline-offset:2px}
.qn-dong{display:flex;align-items:center;justify-content:space-between;gap:12px}
.qn-sl-nhan{font-size:15px;font-weight:700}
.qn-sl{display:flex;align-items:center;gap:6px}
.qn-sl b{min-width:36px;text-align:center;font-size:18px;font-weight:800}
.qn-sl-b{width:48px;height:48px;border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;font-size:22px;font-weight:700;color:var(--ink);cursor:pointer}
/* menu quán: dải nhóm món cuộn ngang */
.qn-tabs{display:flex;gap:8px;overflow-x:auto;padding:2px 0 10px;scrollbar-width:none}
.qn-tab{flex:0 0 auto;min-height:44px;padding:0 14px;border:1.5px solid var(--line);border-radius:999px;background:#fff;font:inherit;font-size:14.5px;font-weight:700;color:var(--ink);cursor:pointer;white-space:nowrap}
.qn-tab span{font-weight:400;color:var(--slate)}
.qn-tab.on{background:var(--sky-900);border-color:var(--sky-900);color:#fff}
.qn-tab.on span{color:#fff}
/* cài tùy chọn món */
.qn-cai{display:flex;flex-direction:column;gap:16px}
.qn-muc h4{margin:0 0 6px;font-size:16px}
.qn-muc .f select{max-width:32ch}
.qn-tick{display:flex;align-items:center;gap:10px;min-height:44px;font-size:14px;font-weight:600}
.qn-tick input{width:22px;height:22px}
.qn-g{display:flex;flex-direction:column;gap:8px;margin:12px 0;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--sky-50)}
.qn-g .f input{max-width:30ch}
.qn-g .f .qn-so{max-width:8ch}
.qn-cds{display:flex;flex-direction:column;gap:6px}
.qn-c{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr) 56px 44px;align-items:center;gap:6px}
.qn-c input:not([type]){width:100%;min-width:0;height:44px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;font:inherit;background:#fff}
.qn-md{display:flex;align-items:center;justify-content:center;width:44px;height:44px;justify-self:center;cursor:pointer}
.qn-md input{width:24px;height:24px}
.qn-c .icobtn{width:44px;height:44px}
.qn-c-dau{font-size:12px;font-weight:600;color:var(--slate)}
.qn-ap{display:flex;flex-direction:column;gap:6px}
.qn-ap-t{font-size:13px;font-weight:600;color:var(--slate)}
.qn-tim{max-width:30ch;height:44px;padding:0 10px;border:1.5px solid var(--line);border-radius:8px;font:inherit}
.qn-goiy:empty{display:none}
/* bánh cần làm */
.qn-banh-loc{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px}
.qn-banh-ngay{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600}
.qn-banh-ngay input{height:44px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;font:inherit}
.qn-tong{margin:12px;padding:12px;border-radius:var(--r-lg);background:var(--or-50)}
.qn-tong h4{margin:0 0 6px;font-size:15px}
.qn-tong ul,.qn-don-ds{margin:0;padding-left:0;list-style:none;display:flex;flex-direction:column;gap:6px}
.qn-don{margin:12px;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.qn-don-dau{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:8px}
.qn-gio{font-size:20px;font-weight:800;color:var(--sky-900)}
.qn-don-dau .dh-link{display:inline-flex;align-items:center;min-height:44px}
/* tên tiệm trên phiếu K80 của tiệm KHÔNG phải VLXD: chữ thường xuống dòng được, tên dài không bị cắt (VLXD giữ khối logo cũ) */
.p-80 .lk-ten{font-size:14pt;font-weight:800;line-height:1.2;text-align:center;overflow-wrap:anywhere}
.qn-chu,.dh-chu b{color:var(--or-safe)}
.dh-tc{color:var(--slate)}
/* in danh sách bánh cần làm */
.qn-in-phu{font-size:9pt;margin-bottom:4mm}
/* phiếu in: số thứ tự to · dòng tùy chọn */
.p-80 .stt{margin:1mm 0 1.2mm;font-size:11pt;font-weight:700;letter-spacing:1pt}
.p-80 .stt b{font-size:22pt;font-weight:800}
.p-tc{font-size:8.5pt}
/* phiếu pha chế — in liền sau phiếu tính tiền (vạch cắt) hoặc riêng */
.p-pc{padding-top:1mm}
.p-pc.k58{width:48mm;padding:2mm 2.5mm}
.p-pc .pc-cat{text-align:center;font-size:8pt;margin:2mm 0 3mm;letter-spacing:.5pt}
.p-pc .pc-dau{display:flex;align-items:center;justify-content:space-between;font-size:13pt;font-weight:800;letter-spacing:1pt}
.p-pc .pc-so{font-size:26pt;line-height:1}
.p-pc .pc-mt{font-size:8.5pt}
.p-pc .pc-mon{font-size:11pt;line-height:1.35;margin:1.2mm 0;break-inside:avoid;page-break-inside:avoid}
.p-pc .pc-tc{font-size:10pt;padding-left:3mm}
.p-pc .pc-ghi{font-size:9.5pt;font-style:italic;padding-left:3mm}
/* tem ly: mỗi ly một tem; máy in tem 50×30 / 40×30 mỗi tem một trang, cuộn nhiệt thì xếp dọc có vạch cắt */
.tem{width:50mm;height:30mm;box-sizing:border-box;padding:1.2mm 1.8mm;display:flex;flex-direction:column;gap:.3mm;color:#000;font-size:7pt;line-height:1.15;overflow:hidden;
  break-after:page;page-break-after:always}
.tem.t40{width:40mm}
.tem.cuon{width:72mm;height:auto;padding:2mm 4mm;border-bottom:1px dashed #000;break-after:auto;page-break-after:auto}
.tem-dau{display:flex;justify-content:space-between;align-items:baseline;gap:2mm;font-size:7pt}
.tem-dau span{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.tem-dau b{font-size:11pt;font-weight:800;line-height:1}
.tem-ten{flex:none;font-size:8.5pt;font-weight:800;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tem-tc{flex:none;font-size:7pt;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.tem-ghi{font-size:7.5pt;font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tem-chan{margin-top:auto;flex:none;display:flex;justify-content:space-between;font-size:7pt}
@media (max-width:420px){
  .qn-chip{min-width:0;flex:1 1 calc(50% - 8px)}
  .qn-c{grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) 44px 44px;gap:4px}
}

/* ===== SOURCE: styles/khuyen-mai.css ===== */
/* ============================================================
   khuyen-mai.css · b311 · KHUYẾN MÃI · COMBO · TÍCH ĐIỂM · VOUCHER — hộp voucher · đổi điểm của phiếu, cài chương trình, tích điểm,
   đợt voucher (xem · in mã), phần combo của form hàng. Phiếu bán chỉ thêm một dòng nhắc voucher chưa dùng (.km-bo).
   Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md (biến có sẵn, không thêm mã màu). Chỗ bấm ≥ 44px.
   ============================================================ */
.trow.km-bo span{font-size:12.5px;color:var(--or-safe);white-space:normal}
.km-hop{display:flex;flex-direction:column;gap:14px}
.km-muc{display:flex;flex-direction:column;gap:10px}
.km-muc h4{margin:0;font-size:16px}
.km-dang{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0;font-size:14.5px}
.km-dang .btn{min-height:44px}
.km-o-ma{max-width:24ch;text-transform:uppercase}
.km-o-so{max-width:14ch}
.km-o-ten{max-width:36ch}
.km-nut{display:flex;flex-wrap:wrap;gap:8px}
.km-nut .btn{min-height:44px}
.km-canh{margin:4px 0 0;font-size:13px;font-weight:600;color:var(--red)}
/* danh sách chương trình */
.km-ds{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px}
.km-dong{display:grid;grid-template-columns:52px minmax(0,1fr) auto 44px;align-items:center;gap:8px;padding:6px 8px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.km-dong.mo{border-color:var(--sky-900);background:var(--sky-50)}
.km-dong .btn{min-height:44px}
.km-dong .icobtn{width:44px;height:44px}
.km-bat{min-height:44px;padding:0;border:0;background:none;justify-content:center}
.km-ten{display:flex;flex-direction:column;min-width:0}
.km-ten b{overflow-wrap:anywhere}
.km-ten span{font-size:12.5px;color:var(--slate);overflow-wrap:anywhere}
.km-form{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--sky-50)}
.km-gt{display:flex;gap:8px;align-items:center}
.km-gt select{width:auto;min-width:88px;min-height:44px}
.km-ap{display:flex;flex-direction:column;gap:6px}
.km-ap-t{font-size:13px;font-weight:600;color:var(--slate)}
.km-ap .fchips{flex-wrap:wrap;overflow:visible}
.km-ap .fchip{min-height:44px;min-width:44px;justify-content:center}
.km-tim{max-width:30ch;height:44px;padding:0 10px;border:1.5px solid var(--line);border-radius:8px;font:inherit}
.km-goiy:empty{display:none}
/* hạng thành viên */
.km-hang{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,.8fr) 44px;gap:6px;align-items:center}
.km-hang input{width:100%;min-width:0;height:44px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;font:inherit;background:#fff}
.km-hang .icobtn{width:44px;height:44px}
.km-hang-dau span{font-size:12px;font-weight:600;color:var(--slate)}
/* bảng: sổ điểm, đợt voucher, danh sách mã */
.km-bang{width:100%;border-collapse:collapse;font-size:13.5px}
.km-bang th,.km-bang td{padding:8px 6px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.km-bang th{font-size:12.5px;color:var(--slate);font-weight:600}
.km-bang .r{text-align:right}
.km-bang .km-nut{justify-content:flex-end}
.km-tat td{color:var(--slate)}
/* combo trong form hàng */
.km-cb{display:flex;flex-direction:column;gap:8px;padding:4px 0}
.km-cb-dong{display:grid;grid-template-columns:minmax(0,1fr) 72px 44px;gap:8px;align-items:center}
.km-cb-dong span{overflow-wrap:anywhere}
.km-cb-dong input{height:44px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;font:inherit;text-align:right}
.km-cb-dong .icobtn{width:44px;height:44px}
/* in danh sách mã voucher */
.km-in-phu{font-size:9pt;margin-bottom:4mm}
.km-in-ma{display:grid;grid-template-columns:repeat(3,1fr);gap:3mm}
.km-in-o{display:flex;flex-direction:column;gap:1mm;padding:3mm;border:1px dashed #000;break-inside:avoid;page-break-inside:avoid}
.km-in-o b{font-size:12pt;letter-spacing:.5pt}
.km-in-o span{font-size:8pt}
@media (max-width:420px){
  .km-dong{grid-template-columns:52px minmax(0,1fr) 44px;grid-template-areas:"b t x" ". s s"}
  .km-dong .km-bat{grid-area:b}
  .km-dong .km-ten{grid-area:t}
  .km-dong .icobtn{grid-area:x}
  .km-dong .btn{grid-area:s;justify-self:start}
  /* bảng thành thẻ: mỗi dòng xuống hàng, nút xuống dòng riêng — không cuộn ngang trong hộp (KĐL máy bán 8) */
  .km-bang thead{display:none}
  .km-bang tr{display:flex;flex-wrap:wrap;gap:4px 10px;padding:8px 0;border-bottom:1px solid var(--line)}
  .km-bang td{padding:0;border:0}
  .km-bang .km-nut{flex-basis:100%;justify-content:flex-start}
  .km-hang{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr) 56px 44px}
  .km-hang input{padding:0 6px}
}

/* ===== SOURCE: styles/bien-the.css ===== */
/* ============================================================
   bien-the.css · b312 · BIẾN THỂ SIZE × MÀU · IMEI / SERIAL · PHIẾU SỬA — lưới chọn biến thể ở màn bán, chip số IMEI (dòng phiếu, hộp
   trả hàng, hộp chọn số), mẫu hàng + sửa giá hàng loạt, tra IMEI, màn Phiếu sửa. Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md
   (biến có sẵn, không thêm mã màu). Chỗ bấm ≥ 44px; không bảng nào rộng hơn hộp ở 320px (lưới chỉ dựng khi cột vừa màn).
   ============================================================ */
.bt-hop{display:flex;flex-direction:column;gap:12px}
/* lưới chọn biến thể */
.bt-chip{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.bt-chip>span{font-size:13px;font-weight:600;color:var(--slate);margin-right:4px}
.bt-chip .fchip{min-height:44px;min-width:44px;justify-content:center}
.bt-luoi{width:100%;border-collapse:separate;border-spacing:6px;table-layout:fixed}
.bt-truc{margin:0;font-size:13px;color:var(--slate)}
.bt-luoi th{font-size:13px;color:var(--slate);font-weight:600;text-align:center;overflow-wrap:anywhere;text-transform:none;letter-spacing:0;white-space:normal;padding:4px 2px}
.bt-luoi thead th:first-child{width:52px}
.bt-luoi tbody th{text-align:left;font-size:15px;color:var(--ink)}
.bt-luoi td{padding:0}
.bt-o-ds{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:8px}
.bt-o{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;width:100%;min-height:60px;padding:6px 4px;
  border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;font:inherit;color:var(--ink);cursor:pointer}
.bt-o b{font-size:15px;overflow-wrap:anywhere}
.bt-o small{font-size:12px;color:var(--green)}
.bt-o.het{background:var(--paper);color:var(--slate)}
.bt-o.het small{color:var(--red)}
.bt-o.co{border-color:var(--sky-900);background:var(--sky-50)}
.bt-o i{position:absolute;top:2px;right:4px;font-style:normal;font-size:12px;font-weight:700;color:var(--sky-900)}
.bt-o.khong{cursor:default;border-style:dashed;color:var(--slate)}
.bt-gia{font-size:12px;color:var(--slate)}
/* mẫu hàng · giá hàng loạt */
.bt-mau-ds{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px}
.bt-mau-ds>li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.bt-mau-t{display:flex;flex-direction:column;min-width:0}
.bt-mau-t b{overflow-wrap:anywhere}
.bt-mau-t span{font-size:12.5px;color:var(--slate);overflow-wrap:anywhere}
.bt-tt{display:flex;flex-direction:column;gap:6px;padding:10px;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--sky-50)}
.bt-tt-dau{display:flex;align-items:flex-end;gap:8px}
.bt-tt-dau .icobtn{width:44px;height:44px}
.bt-gt,.bt-ap{display:flex;flex-wrap:wrap;align-items:flex-end;gap:6px}
.bt-gt .btn,.bt-ap .btn{min-height:44px}
.bt-ap select{width:auto;min-height:44px}
.bt-bien{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px}
.bt-bien>li{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:6px 8px;border:1px solid var(--line);border-radius:8px;background:#fff}
.bt-bien>li.cu{background:var(--paper)}
.bt-bien>li.bo{opacity:.6}
.bt-bien .btn{min-height:44px}
.bt-bien-t{flex:1 1 140px;min-width:0;display:flex;flex-direction:column;overflow-wrap:anywhere}
.bt-bien-t small{font-size:12px;color:var(--slate)}
.bt-nhan{display:flex;flex-direction:column;gap:2px;font-size:12px;color:var(--slate)}
.bt-hop input.km-o-so,.bt-hop input.km-o-ten,.bt-hop select{min-height:44px}
.bt-ap .btn{min-width:44px}
.bt-so{width:12ch;height:44px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;font:inherit;text-align:right}
.bt-ma{width:16ch;height:44px;padding:0 8px;border:1.5px solid var(--line);border-radius:8px;font:inherit}
/* IMEI: chip số trên dòng phiếu, hộp trả hàng, hộp chọn số */
.sr-chip{display:inline-flex;align-items:center;gap:2px 6px;min-height:32px;margin:2px 4px 0 0;padding:2px 8px;border:1px solid var(--line);border-radius:12px;
  background:#fff;font:inherit;font-size:12.5px;font-family:var(--f-mono);color:var(--ink);cursor:pointer;flex-wrap:wrap;text-align:left}
/* một số IMEI không bao giờ bị bẻ giữa chừng (15 chữ số đọc sai là bán nhầm máy) — chỉ xuống dòng giữa hai số */
.sr-so{white-space:nowrap;font-family:var(--f-mono)}
.sr-dong{display:flex;flex-wrap:wrap;gap:2px 6px;margin-top:4px;font-size:12.5px;color:var(--slate)}
button.sr-chip{min-height:44px}
.sr-chip.het{border-color:var(--red);color:var(--red)}
.sr-chip.on{border-color:var(--sky-900);background:var(--sky-50)}
.sr-chip.la{border-style:dashed}
.sr-x{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;margin:-6px -8px -6px 0;border:0;background:none;color:var(--slate);cursor:pointer}
.sr-x svg{width:14px;height:14px}
.sr-tra{display:flex;flex-wrap:wrap}
.sr-da{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin:0;font-size:13px}
.sr-thieu{font-size:13px;font-weight:600;color:var(--red)}
.sr-luoi{display:flex;flex-wrap:wrap;gap:6px}
.sr-o{max-width:28ch;font-family:var(--f-mono);text-transform:uppercase}
.sr-o-chon{min-height:44px;padding:0 12px;border:1.5px solid var(--line);border-radius:8px;background:#fff;font:inherit;font-size:14px;cursor:pointer}
.sr-nhap{width:100%;font-family:var(--f-mono);text-transform:uppercase}
.sr-kq{padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.sr-kq h4{margin:0 0 4px;font-size:16px;display:flex;flex-wrap:wrap;gap:8px;align-items:center;overflow-wrap:anywhere}
.sr-kq p{margin:2px 0;font-size:13.5px;overflow-wrap:anywhere}
.sr-con{color:var(--green);font-weight:600}
.sr-het{color:var(--red);font-weight:600}
.sr-lich{margin:6px 0 0;padding-left:18px;font-size:12.5px;color:var(--slate)}
/* màn Phiếu sửa */
.sc-loc{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;margin:0 0 12px}
.sc-loc .fchips,.sc-cach.fchips{flex-wrap:wrap;overflow:visible}
.sc-loc .fchip,.sc-tim .btn{min-height:44px}
.sc-tim{display:flex;gap:6px;flex:1 1 240px;max-width:420px}
.sc-tim .km-tim{flex:1;min-width:0;max-width:none}
.sc-ds{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px}
.sc-the{display:flex;flex-direction:column;gap:3px;width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff;font:inherit;text-align:left;cursor:pointer}
.sc-l1{display:flex;justify-content:space-between;gap:8px;align-items:center}
.sc-l1 b{overflow-wrap:anywhere}
.sc-l2,.sc-l3{font-size:13px;color:var(--slate);overflow-wrap:anywhere}
.sc-tre{color:var(--red);font-weight:600}
.sc-dau{display:flex;flex-wrap:wrap;gap:6px}
.sc-tt{display:grid;grid-template-columns:minmax(80px,max-content) minmax(0,1fr);gap:4px 12px;margin:0;font-size:14px}
.sc-tt dt{color:var(--slate)}
.sc-tt dd{margin:0;overflow-wrap:anywhere}
.sc-anh{display:flex;flex-wrap:wrap;gap:6px}
.sc-anh img{width:88px;height:66px;object-fit:cover;border-radius:6px;border:1px solid var(--line)}
.sc-lk{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px}
.sc-lk>li{display:flex;align-items:center;gap:8px;justify-content:space-between;font-size:14px}
.sc-lk>li>span{flex:1;min-width:0;overflow-wrap:anywhere}
.sc-lk small{color:var(--slate)}
.sc-lk .icobtn{width:44px;height:44px}
.sc-lk-them{position:relative;display:flex;flex-direction:column;gap:6px}
.sc-lk-dong{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px;border:1px solid var(--line);border-radius:8px;background:var(--sky-50)}
.sc-lk-dong label{display:flex;align-items:center;gap:4px;font-size:13px}
.sc-lk-dong .btn{min-height:44px}
.sc-tong{margin:0;font-size:15px}
.bt-hop a.btn{text-decoration:none}

/* ===== SOURCE: styles/ban.css ===== */
/* ============================================================
   ban.css · b313 · QUÁN CÓ BÀN PHỤC VỤ — sơ đồ bàn (màu theo trạng thái), sắp bàn kéo thả, gọi món tại bàn (thực đơn ô to + phiếu bàn),
   tính tiền, màn bếp ba cột, phiếu bếp in K80, đặt bàn, cài đặt quán, báo cáo quán.
   Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md (biến có sẵn, không thêm mã màu mới). Chỗ bấm ≥ 44px; ô nhập ≥ 16px trên điện thoại.
   Trạng thái bàn: trống = mặt trắng · có khách = than đậm chữ trắng · chờ tính tiền = cam chữ than (6,35:1) · đặt trước = cam nhạt chữ --or-safe.
   ============================================================ */
.ba-body{display:flex;flex-direction:column;gap:12px}
.ba-lui{width:44px;height:44px}
.ba-h1{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:880px){ .ba-sub{display:none} }
.ba-loc{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center}
.ba-loc .fchip{min-height:44px}
.ba-tts .fchip::before{content:"";display:inline-block;flex:0 0 10px;width:10px;height:10px;border-radius:50%;margin-right:6px;border:1.5px solid var(--sky-400);background:#fff}
.ba-tts .ba-tt-co::before{background:var(--sky-800);border-color:var(--sky-800)}
.ba-tts .ba-tt-tam::before{background:var(--or);border-color:var(--or)}
.ba-tts .ba-tt-dat::before{background:var(--or-50);border-color:var(--or-safe)}
.ba-khu{display:flex;flex-direction:column;gap:8px}
.ba-khu-t{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:4px 0 0;font-size:16px;font-weight:700}
.ba-khu-t .btn{min-height:44px}
.ba-luoi{--cot:4;display:grid;grid-template-columns:repeat(var(--cot),minmax(120px,1fr));grid-auto-rows:minmax(112px,auto);gap:12px}
/* thẻ bàn */
.ba-ban{position:relative;display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:2px;min-width:0;min-height:112px;padding:10px 12px;
  border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;color:var(--ink);font:inherit;text-align:left;cursor:pointer;touch-action:manipulation}
.ba-ban.hinh-tron{border-radius:28px}
.ba-ban.hinh-dai{border-left-width:6px}
.ba-ban:focus-visible,.ba-mon:focus-visible,.bep-mon:focus-visible,.ba-o:focus-visible{outline:3px solid var(--or);outline-offset:2px}
.ba-ten{font-size:18px;font-weight:800;line-height:1.2;overflow-wrap:anywhere}
.ba-dong2{font-size:13px;color:var(--slate);overflow-wrap:anywhere}
.ba-tt{font-size:13px;font-weight:600;color:var(--slate)}
.ba-tien{margin-top:auto;font-size:16px;font-weight:800}
.ba-hieu{display:inline-block;margin-top:2px;padding:1px 8px;border-radius:999px;background:var(--sky-50);color:var(--ink);font-size:12.5px;font-weight:600}
.ba-hieu.am{background:var(--or-50);color:var(--or-safe)}
.ba-hieu.gn{background:var(--green-soft);color:var(--green)}
.ba-ban.tt-co{background:var(--sky-800);border-color:var(--sky-800);color:#fff}
.ba-ban.tt-co .ba-dong2,.ba-ban.tt-co .ba-tt{color:var(--sky-100)}
.ba-ban.tt-tam{background:var(--or);border-color:var(--or-6);color:var(--ink)}
.ba-ban.tt-tam .ba-dong2{color:var(--ink)}
.ba-ban.tt-dat{background:var(--or-50);border-color:var(--or-safe)}
.ba-ban.tt-dat .ba-dong2{color:var(--or-safe);font-weight:600}
/* sắp bàn */
.ba-dang-sua .ba-ban{cursor:grab;border-style:dashed;touch-action:none}   /* KĐL máy bán 9: kéo bằng ngón tay (không để trình duyệt nuốt thành cuộn / lùi trang) */
.ba-dang-sua{overscroll-behavior:contain}
.ba-dang-sua .ba-ban.chon{outline:3px solid var(--or);outline-offset:2px}
.ba-ban.dang-keo{z-index:10;cursor:grabbing;box-shadow:var(--shadow-lg);opacity:.92}
.ba-o{min-height:112px;border:1.5px dashed var(--sky-300);border-radius:var(--r-lg);background:transparent;cursor:pointer}
.ba-sua-nut{position:sticky;bottom:0;padding:8px 0;background:var(--bg)}
.ba-dat-sap ul{margin:0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:8px}
.ba-dat-i{min-height:44px;padding:6px 12px;border:1.5px solid var(--or-safe);border-radius:var(--r-lg);background:var(--or-50);font:inherit;color:var(--ink);cursor:pointer}
/* gọi món: thực đơn + phiếu bàn */
.ba-goi{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(320px,1fr);grid-template-rows:auto 1fr;gap:12px;min-height:0;align-items:start}
.ba-menu{grid-column:1;grid-row:1 / span 2;display:flex;flex-direction:column;gap:8px;min-width:0}
.ba-tim input{width:100%;height:44px;padding:0 12px;border:1.5px solid var(--line);border-radius:var(--r);font:inherit;background:#fff}
.ba-nhom{flex-wrap:nowrap;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin}
.ba-nhom .fchip{flex:0 0 auto;min-height:44px;white-space:nowrap}
.ba-mon-ds{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:8px;align-content:start}
.ba-mon{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:72px;padding:8px 10px;border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;
  font:inherit;color:var(--ink);text-align:left;cursor:pointer;min-width:0}
.ba-mon img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-sm)}
.ba-mon b{font-size:14.5px;line-height:1.25;overflow-wrap:anywhere}
.ba-mon span{font-size:13px;color:var(--slate)}
.ba-mon span i{font-style:normal;color:var(--or-safe)}
.ba-mon small{font-size:12px;font-weight:700;color:var(--red)}
.ba-mon.het{background:var(--paper);border-style:dashed}
.ba-phieu{grid-row:1;grid-column:2;display:flex;flex-direction:column;gap:10px;min-width:0;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.ba-p-dau{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:6px}
.ba-p-dau b{font-size:18px}
.ba-p-dau>span{font-size:13px;color:var(--slate)}
.ba-phieu h3{margin:0 0 4px;font-size:14px;font-weight:700}
.ba-phieu h3 small{font-weight:400;color:var(--slate)}
.ba-phieu ul,.ba-tach,.ba-dat-ds,.ba-lich{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px}
.ba-nhap{padding:8px;border:1.5px dashed var(--or-safe);border-radius:var(--r-lg);background:var(--or-50)}
.ba-dong{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0}
.ba-dong-b{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:48px;padding:4px 6px;border:0;border-bottom:1px solid var(--line-2);
  background:transparent;font:inherit;color:var(--ink);text-align:left;cursor:pointer}
.ba-dong-b:disabled{cursor:default;color:var(--slate)}
.ba-dong-t{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto;overflow-wrap:anywhere}
.ba-dong-n{font-weight:600}
.ba-dong-n>b{margin-right:4px}
.ba-dong-t small{font-size:12.5px;color:var(--slate)}
.ba-dong-p{display:flex;flex-direction:column;align-items:flex-end;gap:2px;flex:0 0 auto}
.ba-ghi{color:var(--or-safe);font-weight:600}
.st-huy .ba-dong-t{text-decoration:line-through}
.ba-cu summary{min-height:44px;display:flex;align-items:center;cursor:pointer;color:var(--slate);font-size:13px}
.ba-tong{display:flex;flex-direction:column;gap:2px;padding-top:6px;border-top:1px solid var(--line)}
.ba-nhap-t{color:var(--or-safe)}
.ba-day{grid-column:2;grid-row:2;display:flex;flex-wrap:wrap;gap:8px;position:sticky;bottom:0;padding:8px 0;background:var(--bg)}   /* KĐL máy bán 8: phiếu dài vẫn thấy nút */
.ba-day .btn{flex:1 1 auto}
.ba-day .btn{min-height:48px;font-size:15px}
.ba-gui{flex:1 1 220px}
/* điện thoại: một cột, hai thẻ Thực đơn / Phiếu bàn, thanh việc dính đáy */
.ba-tab{display:none}
@media (max-width:880px){
  .ba-luoi{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));grid-auto-rows:auto}
  .ba-dang-sua{grid-template-columns:repeat(var(--cot),minmax(96px,1fr));overflow-x:auto}
  .ba-ban{min-height:96px}
  .ba-goi{display:flex;flex-direction:column;padding-bottom:72px}
  .ba-tab{display:flex;gap:8px}
  .ba-tab .fchip{flex:1 1 0;min-height:48px;justify-content:center;font-size:15px}
  .ba-goi[data-panel="menu"] .ba-phieu,.ba-goi[data-panel="phieu"] .ba-menu{display:none}
  .ba-mon-ds{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ba-mon{min-height:76px}
  .ba-day{position:fixed;left:0;right:0;bottom:calc(var(--h-rail) + env(safe-area-inset-bottom,0px));z-index:55;padding:8px 16px;background:var(--paper);border-top:1px solid var(--line)}
  .ba-day:empty{display:none}
  .ba-tim input,.ba-thu input,.bt-hop input,.bt-hop select{font-size:16px}
}
/* chuyển / gộp / tách / chọn bàn */
.ba-viec-ds{display:flex;flex-direction:column;gap:8px}
.ba-viec{justify-content:flex-start;min-height:48px}
.ba-pick h4{margin:12px 0 6px;font-size:14px}
.ba-pick-ds{display:grid;grid-template-columns:repeat(auto-fill,minmax(112px,1fr));gap:8px}
.ba-pick-ds .ba-ban{min-height:72px}
.ba-tach>li{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:4px 0;border-bottom:1px solid var(--line-2)}
.ba-lich>li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px;padding:6px 0;border-bottom:1px solid var(--line-2);font-size:13px}
/* tính tiền */
.ba-thu-hang{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px 24px}
.ba-thu .fchip{min-height:44px}
.ba-phan{margin:4px 0 0;font-size:14px}
.ba-phan small{color:var(--slate)}
.ba-qr{display:flex;flex-direction:column;align-items:center;gap:4px}
.ba-qr svg{width:160px;height:160px}
.ba-mua summary{min-height:44px;display:flex;align-items:center;cursor:pointer;font-weight:600}
/* màn bếp */
.bep-body{display:flex;flex-direction:column;gap:12px}
.bep-body>.fchips .fchip{min-height:44px}
.bep-in-nhac{margin:0}
.bep-huy{padding:8px 12px;border:2px solid var(--red);border-radius:var(--r-lg);background:var(--red-soft);color:var(--red)}
.bep-huy p{margin:2px 0;font-size:15px}
.bep-cot{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;align-items:start}
.bep-c{display:flex;flex-direction:column;gap:8px;min-width:0}
.bep-c h2{margin:0;font-size:16px;font-weight:800}
.bep-c.st-cho h2{color:var(--or-safe)}
.bep-c.st-xong h2{color:var(--green)}
.bep-the{display:flex;flex-direction:column;gap:6px;padding:10px;border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff}
.bep-the.tre{border-color:var(--red);box-shadow:0 0 0 2px var(--red-soft)}
.bep-the header{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:6px}
.bep-the header b{font-size:18px}
.bep-the header>span{font-size:13px;color:var(--slate)}
.bep-the ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px}
.bep-mon{display:flex;align-items:center;gap:10px;width:100%;min-height:52px;padding:6px 8px;border:1px solid var(--line);border-radius:var(--r);background:var(--sky-50);
  font:inherit;color:var(--ink);text-align:left;cursor:pointer}
.bep-mon>b{flex:0 0 auto;font-size:20px;min-width:2ch;text-align:right;white-space:nowrap}
.bep-mon>span{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;font-size:16px;font-weight:700;overflow-wrap:anywhere}
.bep-mon small{font-size:13px;font-weight:400;color:var(--slate)}
.bep-mon i{font-style:normal;font-size:13px;font-weight:600;color:var(--slate);white-space:nowrap}
.bep-mon small.bep-ghi{color:var(--or-safe);font-weight:700}
.bep-ca{min-height:44px}
@media (max-width:700px){ .bep-cot{grid-template-columns:minmax(0,1fr)} }   /* máy tính bảng dọc 768 vẫn ba cột */
/* đặt bàn */
.ba-dat-ds>li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 10px;padding:8px 10px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.ba-dat-ds>li.dat-huy,.ba-dat-ds>li.dat-vang{opacity:.7}
.ba-dat-ds .km-nut{flex-basis:100%}
.ba-dat-ds .btn{min-height:44px}
/* cài đặt · báo cáo */
.ba-cai-nhom{width:100%;border-collapse:collapse}
.ba-cai-nhom th{text-align:left;font-weight:600;padding:4px 8px 4px 0;overflow-wrap:anywhere}
.ba-cai-nhom select{min-height:44px}
.ba-cai-ten{flex:1 1 140px}
.ba-bc-so{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px}
.ba-bc-so>div{display:flex;flex-direction:column;padding:8px 10px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.ba-bc-so span{font-size:12.5px;color:var(--slate)}
.ba-bc-so b{font-size:18px;font-weight:800}
.ba-bc-bang{width:100%;border-collapse:collapse}
.ba-bc-bang th{text-align:left;font-weight:600;padding:6px 8px 6px 0;overflow-wrap:anywhere}
.ba-bc-bang th small{display:block;font-weight:400;font-size:12.5px;color:var(--slate)}
.ba-bc-bang td{text-align:right;padding:6px 0 6px 8px;white-space:nowrap;border-bottom:1px solid var(--line-2)}
.ba-bc-gio{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px}
.ba-bc-gio li{display:grid;grid-template-columns:40px minmax(0,1fr) auto;align-items:center;gap:8px;font-size:13px}
.ba-bc-gio i{display:block;height:14px;border-radius:4px;background:var(--sky-700)}
/* phiếu bếp · phiếu tạm tính (in) */
@media print{
  .bep-in h1{font-size:22pt;margin:2mm 0}
  .bep-in-khu{font-size:13pt;font-weight:800}
  .bep-in table{width:100%}
  .bep-in .bep-sl{min-width:12mm;padding-right:2mm;white-space:nowrap;font-size:16pt;font-weight:800;vertical-align:top}
  .bep-in .bep-ten{font-size:14pt}
  .bep-in .bep-ten div{font-size:11pt}
  .ba-in .stt{font-size:16pt}
}
.ba-thu-hang .qn-sl b{font-size:16px;font-weight:700;min-width:64px}
.ba-thu-hang .bt-ap label.chk{display:flex;align-items:center;gap:6px;min-height:44px}
/* b319 · ⑦ sơ đồ bàn phương án B (frontend/ban-so-do.js): sơ đồ | khung phải 340px (món của bàn đang chọn / "Cần chú ý"); bàn 2 ghế tròn; bàn đang
   chọn viền cam; "chờ bếp N'" đỏ (món gửi bếp chờ quá 15 phút). Chỉ máy tính — điện thoại giữ như b313. */
.ba-hai{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:14px;align-items:start}
.ba-trai{min-width:0}
.ba-ben{position:sticky;top:0;max-height:calc(100vh - 150px);overflow:auto;display:flex;flex-direction:column;gap:8px;padding:14px;
  background:var(--paper);border:1px solid var(--line);border-radius:12px}
.ba-ben-t{margin:0;font-size:18px;font-weight:700}
.ba-ben-t small{font-size:12.5px;font-weight:400;color:var(--slate)}
.ba-ben-phu{margin:0;font-size:14px;color:var(--slate)}
.ba-ben-ds ul{margin:0;padding:0;list-style:none}
.ba-ben-nhap{margin:0 0 6px;padding:6px 10px;border-radius:8px;background:var(--or-50);color:#B34700;font-size:14px;font-weight:700}
.ba-ben-tong{display:flex;justify-content:space-between;align-items:baseline;gap:8px;padding-top:8px;border-top:1px solid var(--line);font-size:14px}
.ba-ben-tong b{font-size:21px;font-weight:800;font-family:var(--f-mono)}
.ba-ben-nut{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.ba-ben-nut .btn,.ba-ben-mo{min-height:44px;justify-content:center}
.ba-ben-thu{grid-column:1/-1}
.ba-chu-y{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;list-style:none}
.ba-cy{display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%;min-height:44px;padding:8px 12px;text-align:left;font-size:14px;
  background:var(--paper);border:1px solid var(--line);border-radius:10px;color:var(--ink)}
.ba-cy.m3{border-left:4px solid var(--red)}
.ba-cy.m2{border-left:4px solid var(--or)}
.ba-cy span{color:var(--slate)}
.ba-hieu.rd{background:var(--red-soft);color:var(--red)}
.ba-ban.xem{outline:3px solid var(--or);outline-offset:2px}
.ba-luoi .ba-ban.hinh-tron{justify-self:center;width:100%;max-width:150px;aspect-ratio:1;border-radius:50%;align-items:center;justify-content:center;text-align:center}
@media (max-width:1100px){ .ba-hai{grid-template-columns:minmax(0,1fr) 300px} }

/* ===== SOURCE: styles/lich.css ===== */
/* ============================================================
   lich.css · b314 · DỊCH VỤ CÓ LỊCH HẸN — lưới lịch theo KTV / giường (máy tính), danh sách theo giờ chữ to (điện thoại), hàng chờ + xếp tua,
   gói · điểm danh, chip KTV trên dòng phiếu bán, KTV · ca làm, hoa hồng, báo cáo dịch vụ.
   Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md (biến có sẵn, không thêm mã màu mới — màu KTV do chủ chọn, chỉ làm vạch trái). Chỗ bấm ≥ 44px.
   Trạng thái: đặt = trắng · đã đến = cam nhạt chữ --or-safe · đang làm = than chữ trắng · xong = xanh nhạt · đã thu = xám · không đến = đỏ nhạt.
   ============================================================ */
.lh-body{display:flex;flex-direction:column;gap:12px}
.lh-thanh{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}
.lh-thanh>.fchip{min-height:44px}
.lh-ngay{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.lh-mui{width:44px;min-height:44px;padding:0;justify-content:center}
.lh-mui svg{width:20px;height:20px}
.lh-toi svg{transform:scaleX(-1)}
.lh-ngay-o{position:relative;display:inline-flex;align-items:center;min-height:44px;padding:0 14px;border:1px solid var(--line);border-radius:var(--r);background:#fff;font-weight:700;font-size:16px;cursor:pointer}
.lh-ngay-o input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer}
.lh-che .fchip,.lh-loc .fchip{min-height:44px}
.lh-cham{display:inline-block;flex:0 0 10px;width:10px;height:10px;border-radius:50%;margin-right:6px;background:var(--mau,var(--sky-400))}
/* hàng chờ + xếp tua */
.lh-cho{display:flex;flex-direction:column;gap:8px;padding:12px;border:1.5px solid var(--or-safe);border-radius:var(--r-lg);background:var(--or-50)}
.lh-cho-t{margin:0;font-size:16px;font-weight:700}
.lh-cho-ds{display:flex;flex-wrap:wrap;gap:8px}
.lh-cho-i{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:56px;min-width:0;max-width:100%;padding:8px 12px;border:1px solid var(--or-safe);border-radius:var(--r);background:#fff;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.lh-cho-i span{font-size:13.5px;color:var(--slate);overflow-wrap:anywhere}
.lh-cho-i .lh-cho-xep{color:var(--or-safe);font-weight:700}
.lh-tua{display:flex;flex-wrap:wrap;gap:6px;margin:0;font-size:14px;align-items:center}
.lh-tua-i{padding:2px 10px;border-radius:999px;background:#fff;border:1px solid var(--line)}
.lh-tua-i.dau{border-color:var(--or-safe);color:var(--or-safe);font-weight:700}
/* lưới giờ (máy tính) */
.lh-luoi-khung{overflow:auto;max-height:calc(100vh - 190px);border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.lh-luoi{--so:52;--cot:3;display:grid;grid-template-columns:56px repeat(var(--cot),minmax(160px,1fr));min-width:min-content}
.lh-gio-cot,.lh-cot{display:flex;flex-direction:column;border-right:1px solid var(--line-2)}
.lh-cot-dau{position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:4px;height:44px;padding:0 8px;border-bottom:1px solid var(--line);background:var(--sky-50);font-weight:700;overflow:hidden;white-space:nowrap}
.lh-cot-dau small{margin-left:4px;font-weight:500;color:var(--slate)}
.lh-o-gio{height:24px;padding:0 6px;font-size:12px;color:var(--slate);text-align:right;border-top:1px solid transparent}
.lh-o-gio.tron{border-top-color:var(--line-2)}
.lh-cot-than{position:relative}
.lh-o{display:block;width:100%;height:24px;border:0;border-top:1px dashed var(--line-2);background:transparent;cursor:pointer}
.lh-o:hover{background:var(--sky-50)}
.lh-dat,.lh-nghi{position:absolute;left:3px;right:3px;z-index:2}
.lh-dat::after{content:"";position:absolute;left:4px;right:4px;top:100%;height:var(--don,0);background:repeating-linear-gradient(135deg,var(--line-2) 0 4px,transparent 4px 8px);border-radius:0 0 var(--r-sm) var(--r-sm)}
.lh-dat.keo{z-index:5;opacity:.85;box-shadow:var(--shadow-md)}
.lh-nghi{z-index:1;display:flex;align-items:flex-start;padding:4px 8px;border-radius:var(--r-sm);background:repeating-linear-gradient(135deg,var(--sky-100) 0 6px,var(--sky-50) 6px 12px);color:var(--slate);font-size:12.5px;pointer-events:none}
.lh-bay-gio{position:absolute;left:0;right:0;height:2px;background:var(--red);z-index:4;pointer-events:none}   /* b319 · vạch ĐỎ giờ hiện tại */
.lh-khoi{display:flex;flex-direction:column;align-items:flex-start;gap:1px;width:100%;height:100%;min-height:22px;overflow:hidden;padding:3px 8px;border:1px solid var(--line);border-left:4px solid var(--mau,var(--sky-400));
  border-radius:var(--r-sm);background:#fff;color:var(--ink);font:inherit;font-size:13px;line-height:1.25;text-align:left;cursor:pointer;touch-action:none}
.lh-khoi:focus-visible,.lh-the button:focus-visible,.lh-cho-i:focus-visible,.gd-the:focus-visible,.lh-xep-i:focus-visible{outline:3px solid var(--or);outline-offset:2px}
.lh-k-gio{font-weight:700;font-size:12.5px}
.lh-k-ten{font-weight:700;overflow-wrap:anywhere}
.lh-k-dv,.lh-k-tt{color:var(--slate);overflow-wrap:anywhere}
.lh-trong{margin:0}
/* màu trạng thái (khối lưới · thẻ danh sách · nhãn) */
.st-den{background:var(--or-50);border-color:var(--or-safe)}
.st-lam{background:var(--sky-800);border-color:var(--sky-800);color:#fff}
.st-lam .lh-k-dv,.st-lam .lh-k-tt,.st-lam .lh-t-phu,.st-lam .lh-t-tt{color:var(--sky-100)}
.st-xong{background:var(--green-soft);border-color:var(--green)}
.st-thu{background:var(--sky-100);color:var(--slate)}
.st-vang{background:var(--red-soft);border-color:var(--red);color:var(--red)}
.st-huy{color:var(--slate);text-decoration:line-through}
.lh-pill{display:inline-block;padding:2px 10px;border-radius:999px;border:1px solid var(--line);font-size:13px;font-weight:600}
/* danh sách (điện thoại · tuần) — chữ to */
.lh-ngay-t{margin:8px 0 4px;font-size:16px;font-weight:700}
.lh-ds{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.lh-the{border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.lh-the.st-den,.lh-the.st-xong,.lh-the.st-vang,.lh-the.st-lam,.lh-the.st-thu{border-width:1.5px}
/* b321 · thẻ danh sách (điện thoại): `.lh-the{background:#fff}` đứng sau đè màu trạng thái ⇒ "Đang làm" chữ trắng trên nền trắng (có từ b314) */
.lh-the.st-den{background:var(--or-50)}
.lh-the.st-lam{background:var(--sky-800)}
.lh-the.st-xong{background:var(--green-soft)}
.lh-the.st-thu{background:var(--sky-100)}
.lh-the.st-vang{background:var(--red-soft)}
.lh-the button{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;width:100%;min-height:64px;padding:10px 12px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
.lh-t-gio{grid-row:1 / span 2;font-size:20px;font-weight:800;line-height:1.1}
.lh-t-gio small{display:block;font-size:14px;font-weight:600;color:inherit;opacity:.75}
.lh-t-than{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:16px}
.lh-t-than b{font-size:17px;overflow-wrap:anywhere}
.lh-t-phu{font-size:14px;color:var(--slate);overflow-wrap:anywhere}
.lh-t-tt{grid-column:2;font-size:13.5px;font-weight:700;color:var(--slate)}
/* chi tiết · form */
.lh-xem{display:flex;flex-direction:column;gap:10px}
.lh-xem-tt{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:0}
.lh-xem-tt a{min-height:44px;display:inline-flex;align-items:center}
.lh-xem-ds{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.lh-xem-ds li{display:flex;flex-direction:column;gap:2px;padding:8px 10px;border-radius:var(--r);background:var(--sky-50)}
.lh-xem-ds span{font-size:14px;color:var(--slate)}
.lh-xem-nut .btn,.lh-f .btn{min-height:44px}
.lh-ls{list-style:none;margin:0;padding:0;font-size:13.5px;display:flex;flex-direction:column;gap:4px;overflow-wrap:anywhere}
.lh-f-dong{display:flex;flex-direction:column;gap:8px;margin:0;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg)}
.lh-f-hang{display:flex;flex-wrap:wrap;gap:8px 12px}
.lh-f select,.lh-f input{min-height:44px}
.lh-xep{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}
.lh-xep-i{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:60px;padding:8px 12px;border:1.5px solid var(--line);border-radius:var(--r-lg);background:#fff;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.lh-xep-i span{font-size:13.5px;color:var(--slate)}
.lh-xep-i.dau{border-color:var(--or-safe);background:var(--or-50)}
.lh-xep-i:disabled{opacity:.5;cursor:not-allowed}
.lh-vl-dv{display:flex;flex-direction:column;gap:4px}
.lh-vl-i{min-height:44px;display:flex;align-items:center;gap:8px}
/* chip KTV / trừ gói trên dòng phiếu bán */
.lh-chip{display:inline-flex;align-items:center;align-self:flex-start;min-height:30px;margin-top:3px;padding:2px 10px;border:1px dashed var(--sky-400);border-radius:999px;background:#fff;color:var(--slate);font:inherit;font-size:12.5px;cursor:pointer;max-width:100%;overflow-wrap:anywhere;text-align:left}
.lh-chip.co{border-style:solid;border-color:var(--or-safe);color:var(--or-safe);font-weight:600}
.lh-nv{display:flex;flex-wrap:wrap;gap:8px}
.lh-nv .fchip{min-height:44px}
.lh-tip{flex-direction:row;align-items:center;gap:8px}
/* gói · điểm danh */
.gd-dd{display:flex;flex-direction:column;gap:8px;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.gd-dd-f label{font-weight:700;font-size:16px}
.gd-dd-hang{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}
.gd-dd-hang input{flex:1 1 180px;min-width:0;min-height:48px;font-size:20px}
.gd-dd-nut{min-height:48px;font-size:16px}
.gd-ok,.gd-loi{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border-radius:var(--r);font-size:16px}
.gd-ok{background:var(--green-soft);color:var(--green)}
.gd-ok span{font-size:14px;color:var(--ink)}
.gd-loi{background:var(--red-soft);color:var(--red);font-weight:600}
.gd-ds{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.gd-the{display:grid;grid-template-columns:1fr auto;gap:2px 12px;width:100%;min-height:60px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.gd-t-ten{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline;min-width:0;overflow-wrap:anywhere}
.gd-t-goi{grid-column:1;font-size:14px;color:var(--slate);overflow-wrap:anywhere}
.gd-t-con{grid-column:2;grid-row:1 / span 2;align-self:center;text-align:right;font-size:15px}
.gd-t-tt{grid-column:1 / span 2;font-size:13px;font-weight:600;color:var(--slate)}
.gd-t-tt.co{color:var(--red)}
.gd-tt{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;margin:0}
.gd-tt dt{color:var(--slate)}
.gd-tt dd{margin:0;overflow-wrap:anywhere}
/* quản lý · báo cáo */
.lh-ql{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.lh-ql li{display:flex;align-items:center;gap:8px;min-height:52px;padding:6px 0;border-bottom:1px solid var(--line-2)}
.lh-ql-t{display:flex;flex-direction:column;flex:1;min-width:0;overflow-wrap:anywhere}
.lh-ql-t span{font-size:13.5px;color:var(--slate)}
.lh-ql .btn{min-height:44px}
.lh-ca{display:flex;flex-direction:column;gap:6px}
.lh-ca-d{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.lh-ca-d .chk{min-width:110px;min-height:44px;display:flex;align-items:center;gap:6px}
.lh-ca-d input[type=time]{min-height:44px}
.lh-gdv{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:4px 12px}
.lh-gdv .chk{min-height:44px;display:flex;align-items:center;gap:6px}
.lh-hh-o{display:flex;gap:6px}
.lh-hh-o select,.lh-hh-o input{min-height:44px}
.lh-dm{list-style:none;margin:0 0 6px;padding:0;display:flex;flex-direction:column;gap:4px}
.lh-dm li{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.lh-dm li span:first-child{flex:1 1 160px;min-width:0;overflow-wrap:anywhere}
.lh-dm-them{display:flex;gap:6px;flex-wrap:wrap}
.lh-dm-them select{flex:1 1 200px;min-width:0;min-height:44px}
.lh-bang td,.lh-bang th{white-space:nowrap}
.lh-so-hang{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px}
.lh-so{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.lh-so span{font-size:13.5px;color:var(--slate)}
.lh-so b{font-size:20px}
.lh-so small{font-size:12.5px;color:var(--slate);overflow-wrap:anywhere}
.lh-kin{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.lh-kin li{display:grid;grid-template-columns:minmax(80px,140px) 1fr auto;gap:4px 10px;align-items:center}
.lh-kin small{grid-column:2 / span 2;font-size:12.5px;color:var(--slate)}
.lh-kin-thanh{height:10px;border-radius:999px;background:var(--sky-100);overflow:hidden}
.lh-kin-thanh i{display:block;height:100%;background:var(--sky-700)}
@media (max-width:600px){
  .lh-the button{min-height:72px}
  .lh-chip,.gd-dd-hang .btn{min-height:44px}   /* KĐL-R13: chỗ bấm ≥ 44px trên điện thoại */
  .lh-t-gio{font-size:22px}
  .gd-the{grid-template-columns:1fr}
  .gd-t-con{grid-column:1;grid-row:auto;text-align:left}
}
/* bề rộng ô theo độ dài chữ sẽ gõ (luật form) */
.lh-f #lhf_dt,#lhv_dt,#kt_dt,#gd_the{max-width:220px}
.lh-f #lhf_ten,#lhv_ten,#kt_ten{max-width:360px}
.lh-f select,.lh-f #lhf_note{max-width:480px}
.lh-f input[type=date],.lh-f input[type=time],.lh-f .o-ngay-k{max-width:200px}
.fm-dv .num,.fm-goi .num,#fm_lh .lh-hh-o .num,#lc_lau,#lc_het,#lc_con{max-width:120px}
#lh_dong .lh-tip input{max-width:160px}
#lh_dong select{max-width:320px}
.lh-body .fchips .fchip{min-height:44px}
#gd_q{max-width:320px}

/* b314 · KĐL-R1 · R8: phiếu đang thu lịch hẹn / có tip KTV */
.trow.dv-phieu{justify-content:flex-start;font-size:12.5px;color:var(--ink);padding:4px 0}
/* b319 · ⑧ lịch hẹn phương án B (frontend/lich-ben.js): lưới | khung phải 340px (Khách chờ + gợi ý KTV rảnh · lịch đang chọn); nhãn giờ đỏ trên vạch;
   đầu cột KTV có số lịch; khối đang chọn viền cam. Chỉ máy tính, xem theo ngày. */
.lh-hai{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:14px;align-items:start}
.lh-trai{min-width:0}
.lh-ben{position:sticky;top:0;max-height:calc(100vh - 130px);overflow:auto;display:flex;flex-direction:column;gap:12px}
.lh-ben-k{display:flex;flex-direction:column;gap:6px;padding:12px 14px;background:var(--paper);border:1px solid var(--line);border-radius:12px}
.lh-ben-t{margin:0;font-size:16px;font-weight:700}
.lh-ben-t b{display:inline-block;min-width:24px;padding:0 6px;border-radius:99px;background:var(--or);color:var(--ink);text-align:center;font-size:13px}
.lh-ben-cho{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;list-style:none}
.lh-ben-cho li{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border-radius:10px;background:var(--or-50)}
.lh-ben-cho li div{display:flex;flex-direction:column;min-width:0;font-size:14px}
.lh-ben-cho li span{font-size:12.5px;color:var(--slate)}
.lh-ben-cho .lh-ben-goiy{color:#B34700;font-weight:700}
.lh-ben-cho .btn{min-height:44px;flex:0 0 auto}
.lh-ben-ten{margin:0;font-size:18px;font-weight:700}
.lh-ben-dt{margin:0;font-size:14px}
.lh-ben-nut{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.lh-ben-nut .btn{min-height:44px;justify-content:center}
.lh-ben-thu{grid-column:1/-1}
.lh-khoi.xem{outline:3px solid var(--or);outline-offset:1px;z-index:2}
.lh-cot-so{margin-left:auto}
.lh-gio-cot{position:relative}
.lh-bay-nhan{position:absolute;left:2px;z-index:5;padding:1px 5px;border-radius:5px;background:var(--red);color:#fff;font-size:12px;font-weight:700;font-family:var(--f-mono);pointer-events:none}
@media (max-width:1180px){ .lh-hai{grid-template-columns:minmax(0,1fr) 290px} }

/* ===== SOURCE: styles/thuoc.css ===== */
/* ============================================================
   thuoc.css · b315 · NHÀ THUỐC — màn Nhà thuốc (tab · ô tổng quan · bảng sổ GPP), hộp đơn thuốc, phiếu nhập / xuất theo lô, nhãn ra lẻ (in),
   chip lô cận hạn trên dòng phiếu bán. Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md — biến có sẵn, không thêm mã màu. Chỗ bấm ≥ 44px.
   Trạng thái: đỏ = hết hạn / thu hồi / lỗi · cam = cận hạn / chờ gửi · xanh = còn hạn / đã nhận · xám = bỏ qua.
   ============================================================ */
.nt-body{display:flex;flex-direction:column;gap:12px;min-width:0}
.nt-tabs{display:flex;flex-wrap:nowrap;gap:6px;overflow-x:auto;scrollbar-width:thin;padding-bottom:2px}
.nt-tabs .fchip{flex:none;min-height:44px;white-space:nowrap}
.nt-luoi{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}
.nt-o{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:88px;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.nt-o b{font-size:21px;font-weight:800}
.nt-o span{font-weight:600}
.nt-o small{font-size:12.5px;color:var(--slate)}
.nt-o.rd{border-color:var(--red);background:var(--red-soft)}
.nt-o.rd b{color:var(--red)}
.nt-o.am{border-color:var(--or-safe);background:var(--or-50)}
.nt-o.am b{color:var(--or-safe)}
.nt-o:focus-visible{outline:3px solid var(--or);outline-offset:2px}
.nt-khoi{display:flex;flex-direction:column;align-items:flex-start;gap:8px;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.nt-khoi h3,.nt-khoi p{margin:0}
.nt-co{border-color:var(--red)}
.nt-ds{list-style:none;margin:0;padding:0;width:100%}
.nt-ds li{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line-2);overflow-wrap:anywhere}
.nt-pill{display:inline-block;padding:2px 8px;border-radius:999px;border:1px solid var(--line);font-size:12.5px;font-weight:600;white-space:nowrap}
.nt-pill.rd{background:var(--red-soft);border-color:var(--red);color:var(--red)}
.nt-pill.am{background:var(--or-50);border-color:var(--or-safe);color:var(--or-safe)}
.nt-pill.gn{background:var(--green-soft);border-color:var(--green);color:var(--green)}
.nt-pill.gy{background:var(--sky-50);color:var(--slate)}
.nt-ky{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.nt-ky label{display:inline-flex;align-items:center;gap:4px;font-weight:600}
.nt-ky input{min-height:44px}
.nt-bang{max-width:100%;overflow-x:auto}
.nt-bang td{vertical-align:top;overflow-wrap:anywhere}
.nt-bang td small{color:var(--slate)}
.nt-nut{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.nt-bang+.nt-nut,.nt-bang+p{margin-top:12px}
.nt-nut .btn,.nt-nut .fchip,.nt-so .fchip,.nt-loai .fchip,.nt-khoi .btn,.nt-bang .btn{min-height:44px}
.nt-gt{min-width:56px;min-height:44px;justify-content:center}
.nt-cot{flex-direction:column;align-items:stretch}
.nt-h{margin:12px 0 4px}
.nt-nhap,.nt-don,.nt-form,.nt-cai{display:flex;flex-direction:column;gap:8px;min-width:0}
.nn-d{display:flex;flex-direction:column;gap:8px;padding:12px;border:1px solid var(--line);border-radius:var(--r);background:var(--sky-50)}
.nn-hang{display:flex;flex-wrap:wrap;gap:8px}
.nn-hang .f{flex:0 1 auto;min-width:0}
.nt-ma{display:flex;gap:8px;align-items:center}
.nt-ma input{flex:1;min-width:0}
.nt-loi{padding:8px 12px;border-radius:var(--r);background:var(--red-soft);color:var(--red);font-weight:600}
.nt-nhom{display:inline-flex;align-items:center;gap:4px;min-height:44px}
.nt-dl{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;margin:0}
.nt-dl dt{font-weight:600;color:var(--slate)}
.nt-dl dd{margin:0;overflow-wrap:anywhere}
.nt-in-phu{margin:0 0 3mm;font-size:9pt}
/* dòng phiếu bán: lô cận hạn (thuốc — ngưỡng nhà thuốc) */
.lo-chip.can{background:var(--or-50);border-color:var(--or-safe);color:var(--or-safe)}
/* nhãn ra lẻ — xem trước trong hộp + in (tem 50×30 / 40×30 hoặc cuộn 80 / 58) */
.nt-nhan-ds{display:flex;flex-direction:column;gap:8px}
.nt-nhan-ds.xem .nt-nhan{border:1px dashed var(--line);border-radius:var(--r-sm);height:auto}
.nt-nhan{width:50mm;height:30mm;box-sizing:border-box;padding:1.2mm 1.8mm;display:flex;flex-direction:column;gap:.3mm;color:#000;background:#fff;font-size:7pt;line-height:1.2;overflow:hidden;break-after:page;page-break-after:always}
.nt-nhan-ds.cuon .nt-nhan{width:72mm;height:auto;padding:2mm 4mm;border-bottom:1px dashed #000;break-after:auto;page-break-after:auto}
.nt-nhan-ds.k4030 .nt-nhan{width:40mm;padding:1mm 1.2mm}
.nt-nhan-ds.cuon.k58 .nt-nhan{width:48mm;padding:2mm 1.5mm}
.nt-nhan-ds.k4030 .nt-nh-chan,.nt-nhan-ds.k58 .nt-nh-chan{flex-wrap:wrap}
.nt-nh-tiem{font-size:6.5pt;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nt-nh-ten{font-size:9pt;font-weight:800;overflow-wrap:anywhere}
.nt-nh-phu{font-size:7pt}
.nt-nh-dung{font-size:8pt;font-weight:700;overflow-wrap:anywhere}
.nt-nh-chan{margin-top:auto;display:flex;justify-content:space-between;gap:1mm;font-size:6.5pt}
@media (max-width:880px){
  .nt-ky input,.nt-nhap input,.nt-nhap select,.nt-don input,.nt-cai input,.nt-cai select,.nt-form input,.nt-form select{font-size:16px}
  .nn-hang .f{flex:1 1 40%}
}

/* ===== SOURCE: styles/web.css ===== */
/* ============================================================
   web.css · b316 · ĐƠN ONLINE + GIAO QUA HÃNG trong app — hộp đơn online, cài đặt web, vận đơn, nhãn dán kiện (in A6 100×150).
   Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md — biến có sẵn, không thêm mã màu. Chỗ bấm ≥ 44px. Dùng lại khung .nt-* của nhà thuốc (thuoc.css).
   ============================================================ */
.wb-an{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.wb-lk{min-height:44px;padding:0;border:0;background:none;color:var(--or-safe);font:inherit;text-align:left;cursor:pointer}
.wb-lk:focus-visible{outline:3px solid var(--or);outline-offset:2px}
.wb-st{flex:1;min-width:0}
.wb-tim input{max-width:100%;min-height:44px}
#wb_hang .btn{min-height:44px}
.wb-bang td.num,.wb-bang .wb-lk{white-space:nowrap;overflow-wrap:normal}
.wb-cai{max-width:760px}
.nt-cot>.nt-nhom{justify-content:flex-start;text-align:left}
.nt-nhom>input[type=radio],.nt-nhom>input[type=checkbox]{flex:none;width:auto;padding:0;margin:0 6px 0 0}
.wb-ct .nt-dl{margin-bottom:8px}
/* nhãn dán kiện — khổ A6 100×150mm (cuộn 80mm in được, tự co) */
.gh-nhan{width:100mm;min-height:148mm;box-sizing:border-box;padding:4mm;color:#000;background:#fff;font-size:10pt;line-height:1.3;display:flex;flex-direction:column;gap:2.5mm}
.gh-hang{font-size:12pt;border-bottom:1px solid #000;padding-bottom:1.5mm}
.gh-ma svg{width:100%;height:24mm}
.gh-o{display:flex;flex-direction:column;border:1px solid #000;padding:1.5mm 2mm;overflow-wrap:anywhere}
.gh-o small,.gh-cod small{font-size:7.5pt;letter-spacing:.04em}
.gh-o b{font-size:12pt}
.gh-cod{display:flex;justify-content:space-between;align-items:baseline;border:2px solid #000;padding:2mm}
.gh-cod b{font-size:16pt}
.gh-chan{margin-top:auto;display:flex;justify-content:space-between;font-size:8.5pt}
@media (max-width:880px){.wb-tim input,.nt-cai textarea{font-size:16px}}

/* ===== SOURCE: styles/san.css ===== */
/* ============================================================
   san.css · b317 · NỐI SÀN trong màn Đơn online — dòng "Liên kết hàng" (SKU sàn ↔ mã trong app). Các khung còn lại dùng lại .nt-* (thuoc.css) + .wb-* (web.css).
   Màu / cỡ chữ theo docs/thiet-ke/TO-NHAN-DIEN.md — không thêm mã màu. Chỗ bấm ≥ 44px.
   ============================================================ */
.nt-ds li.sn-lk{flex-wrap:wrap;align-items:flex-start}
.sn-sp{flex:1 1 220px;min-width:0}
.sn-lk .btn,.sn-kn .btn{min-height:44px}
.sn-lk small{color:var(--slate)}
@media (max-width:880px){.nt-ds li.sn-lk>span{flex:1 1 100%}}

/* ===== SOURCE: styles/bang-hom-nay.css ===== */
/* ============================================================
   bang-hom-nay.css · b319 · ⑤ QUẢN LÝ — "BẢNG HÔM NAY" (frontend/quan-ly.js vẽ vào #ql_bang; khung ở managementBody)
   Máy tính 1366×768 vừa MỘT màn không cuộn: [doanh thu + cột theo giờ] | [Cần làm · Bán chạy], dưới đáy 8 ô nhỏ + hàng "Khác".
   Điện thoại: xếp dọc, số hôm nay lên đầu. Biểu đồ MỘT trục triệu đồng; hôm nay than #173247 · hôm qua xám #7D8B99 (3,49:1 trên trắng) ·
   giờ đang bán cam #EA6A0B (3,2:1) — màu luôn kèm chú giải chữ (BAO-CAO-BIEU-DO mục 1).
   ============================================================ */
.ql-bang{display:grid;gap:12px;margin-bottom:12px}
.ql-so,.ql-khoi{background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:14px 16px;min-width:0}
.ql-dt small{display:block;font-size:14px;font-weight:700;color:var(--slate)}
.ql-dt>b{display:block;font-size:44px;font-weight:800;font-family:var(--f-mono);letter-spacing:-.02em;line-height:1.1;color:var(--ink);overflow-wrap:anywhere}
.ql-dt>b span{font-size:21px}
.ql-phu{display:flex;flex-wrap:wrap;gap:4px 16px;margin-top:4px;font-size:14px;color:var(--slate)}
.ql-phu b{color:var(--ink);font-family:var(--f-mono)}
.ql-phu .len{color:var(--green);font-weight:700}
.ql-phu .xuong{color:var(--red);font-weight:700}
.ql-loi{display:flex;align-items:center;gap:8px;margin:8px 0 0;font-size:14px;color:var(--red)}
.ql-bieu{display:flex;gap:6px;height:230px;margin-top:12px}
.ql-truc{display:flex;flex-direction:column;justify-content:space-between;min-width:28px;padding-bottom:18px;
  font-size:12px;line-height:0;color:var(--slate);font-family:var(--f-mono);text-align:right}
.ql-cots{flex:1;display:flex;gap:3px;min-width:0;background-image:linear-gradient(to bottom,var(--line-2) 1px,transparent 1px);
  background-size:100% calc((100% - 18px) / 3);background-repeat:repeat-y}
.ql-cot{flex:1;display:flex;flex-direction:column;min-width:0}
.ql-cot-t{flex:1;display:flex;align-items:flex-end;justify-content:center;gap:2px;border-bottom:1px solid var(--slate-2)}
.ql-cot-t i{display:block;width:40%;max-width:14px;border-radius:2px 2px 0 0}
.ql-nay{background:#173247}
.ql-qua{background:#7D8B99}
.ql-cot.dang .ql-nay{background:#EA6A0B}
.ql-cot small{height:18px;line-height:18px;text-align:center;font-size:12px;color:var(--slate);white-space:nowrap;overflow:hidden}
.ql-chu{display:flex;flex-wrap:wrap;gap:4px 14px;margin-top:6px;font-size:12.5px;color:var(--slate)}
.ql-chu i{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:5px;vertical-align:-1px}
.ql-chu .ql-dang{background:#EA6A0B}
.ql-dv{margin-left:auto}
.ql-ben{display:flex;flex-direction:column;gap:12px;min-width:0}
.ql-khoi{padding:12px 14px}
.ql-khoi h3{margin:0 0 8px;font-size:14px;font-weight:700}
.ql-viec{display:flex;flex-direction:column;gap:4px}
.ql-v{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;min-height:44px}
.ql-v>b{min-width:32px;padding:3px 8px;border-radius:99px;text-align:center;font-size:14px;font-weight:800}
.ql-v.rd>b{background:var(--red-soft);color:var(--red)}
.ql-v.am>b{background:var(--or-50);color:#B34700}
.ql-v span{font-size:14px}
.ql-b{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:3px 10px;margin-bottom:8px;font-size:14px}
.ql-b-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ql-b b{font-family:var(--f-mono)}
.ql-b i{grid-column:1/-1;display:block;height:6px;border-radius:3px;background:#173247}
.ql-trong{margin:0;font-size:14px;color:var(--slate)}
.mg-phu-hang .mg-h{margin-top:4px}
@media (min-width:881px){
  .ql-bang{grid-template-columns:minmax(0,1.7fr) minmax(0,1fr)}
  .ql-ben .ql-khoi{flex:1 1 0;overflow:auto}
  .mg-bang>.mg-ds{grid-template-columns:repeat(8,minmax(0,1fr));gap:8px;margin-bottom:10px}
  .mg-bang>.mg-ds .mg-i{position:relative;grid-template-columns:1fr;justify-items:center;gap:4px;min-height:74px;padding:8px 6px;text-align:center}
  .mg-bang>.mg-ds .mg-i-t{font-size:13px;line-height:1.25}
  .mg-bang>.mg-ds .mg-i-n{position:absolute;top:6px;right:6px}
  .mg-bang .mg-i-ch{display:none}
  .mg-phu-hang{display:flex;align-items:center;flex-wrap:wrap;gap:8px}
  .mg-phu-hang .mg-h{margin:0}
  .mg-bang .mg-phu{display:flex;flex-wrap:wrap;gap:6px;margin:0}
  .mg-bang .mg-phu .mg-i{width:auto;grid-template-columns:auto auto auto;gap:6px;min-height:40px;padding:4px 12px}
  .mg-bang .mg-phu .mg-i-ic{width:24px;height:24px;background:transparent}
}
@media (max-width:880px){
  .ql-dt>b{font-size:36px}
  .ql-bieu{height:170px}
  /* b319 kiểm độc lập (người lớn tuổi): 16 cột chen nhau, nhãn 10,5px bị cắt ⇒ chỉ ghi mỗi 3 giờ, chữ 13px */
  .ql-cot small{font-size:13px;overflow:visible}
  .ql-cot.le small{visibility:hidden}
  .ql-truc{font-size:13px;min-width:30px}
  /* thứ tự điện thoại: số hôm nay → Cần làm → các ô (đích của "Xem thêm") → biểu đồ → bán chạy — danh sách không bị đẩy xuống dưới bảng */
  .mg-bang{display:flex;flex-direction:column;gap:12px}
  .mg-bang .ql-bang,.mg-bang .ql-ben,.mg-bang .ql-so{display:contents}
  .mg-bang .ql-dt,.mg-bang .ql-bieu{background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:14px 16px}
  .mg-bang .ql-dt,.mg-bang .ql-loi{order:1}
  .mg-bang .ql-khoi{order:2}
  .mg-bang>.mg-ds{order:3;margin:0}
  .mg-bang>.mg-phu-hang{order:4}
  .mg-bang .ql-bieu,.mg-bang .ql-chu{order:5;margin:0}
  .mg-bang .ql-khoi-ban{order:6}
}
/* việc chờ chủ (managementBody vẽ đồng bộ, cùng chữ b229) nằm trong "Cần làm" dưới dạng dòng: số · việc · bấm cả dòng là làm */
.ql-v.viec-chip{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;margin:0;padding:4px 0;border:0;border-radius:0;background:transparent;
  color:var(--ink);font-size:14px;font-weight:400;text-align:left;box-shadow:none}
.ql-v.viec-chip:hover{background:var(--sky-50)}

/* ===== SOURCE: styles/san-pham.css ===== */
/* ============================================================
   san-pham.css · b319 · ⑥ SẢN PHẨM — danh sách + KHUNG CHI TIẾT (frontend/sp-chi-tiet.js vẽ vào #p_ct; điện thoại: hộp)
   Máy tính: [bảng hàng | khung 380px dính trên]. Dòng đang xem nền xanh nhạt + vạch trái. Màn hẹp hơn 1100px: khung ẩn, bấm dòng mở hộp.
   Điện thoại (danh sách Tra giá): MỌI dòng CAO BẰNG NHAU 84px (anh Đạt 27/09) — có ô ảnh hay không, có giá nguyên hay không.
   ============================================================ */
.p-hai{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;align-items:start}
.p-hai.co-ct{grid-template-columns:minmax(0,1fr) 380px}
.p-hai:not(.co-ct) .p-ct{display:none}
.spct-dau{position:relative}
.spct-dong{position:absolute;top:-6px;right:-8px}
.modal .spct-dong{display:none}
.p-trai{min-width:0}
.p-ct{position:sticky;top:0;max-height:calc(100vh - 170px);overflow:auto;background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:14px 16px}
#ptbl tr[data-pid]{cursor:pointer}
#ptbl tr.on td{background:var(--sky-50)}
#ptbl tr.on td:first-child{box-shadow:inset 3px 0 0 #173247}
.spct-dau{display:flex;align-items:center;gap:10px}
.spct-dau h2{margin:0;font-size:18px;font-weight:700;line-height:1.3;overflow-wrap:anywhere}
/* b324 · anh Đạt 28/09: ảnh hàng ở đầu khung chi tiết — 96×72 (ảnh 4:3), phủ kín ô, bo góc như ô ảnh form sửa (.pimg-cur).
   Chữ cái đầu tên nằm dưới ảnh, trong suốt; ảnh lỗi tải thì JS đổi ô về .ptimg.none (ô chữ cái). */
.spct-anh{position:relative;flex:0 0 96px;width:96px;height:72px;overflow:hidden;border:1px solid var(--line);border-radius:var(--r);background:#fff;color:transparent}
.spct-anh img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.spct-dau>div{min-width:0}
.spct-so{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:8px;margin-top:12px}
.spct-o{display:flex;flex-direction:column;gap:2px;min-width:0;padding:8px 10px;border:1px solid var(--line);border-radius:10px}
.spct-o small{font-size:12.5px;color:var(--slate)}
.spct-o b{font-size:18px;font-weight:800;font-family:var(--f-mono);overflow-wrap:anywhere}
.spct-o span{font-size:12.5px;color:var(--slate)}
.spct-o em{font-style:normal;font-weight:700}
.spct-o em.rd{color:var(--red)}
.spct-o em.am{color:#B34700}
.spct-gm{margin-top:8px;font-size:14px;font-weight:700;color:#B34700}
.spct-gm span{font-weight:400;color:var(--slate)}
.spct-nut{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:12px}
.spct-nut .btn{min-height:44px;justify-content:center}
.spct-khoi{margin-top:14px}
.spct-khoi h3{margin:0 0 6px;font-size:14px;font-weight:700}
.spct-d{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:baseline;gap:8px;padding:6px 0;border-bottom:1px solid var(--line-2);font-size:12.5px}
.spct-d span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.spct-d .nhap{color:var(--green)}
.spct-d .xuat{color:var(--red)}
.spct .text-action{margin-top:10px}
.ph-row{cursor:pointer}
.ph-sub .gia-moi{margin-left:6px;vertical-align:1px}
@media (max-width:1100px){ .p-hai{grid-template-columns:minmax(0,1fr)} .p-ct{display:none} }
@media (max-width:880px){
  /* b319 · anh Đạt 27/09: "tên sản phẩm nên được nhìn rõ, bị chật quá" — tên chiếm TRỌN bề ngang cột chữ (không chia với cột giá), tối đa 2 dòng;
     giá · giá nguyên · tồn xuống một hàng ngang bên dưới. Mọi dòng vẫn CAO BẰNG NHAU; ô ảnh 25% sát mép trái (luật b290) giữ nguyên. */
  .ph-row,.ph-row:has(.ph-cam){grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto;column-gap:11px;row-gap:6px;
    height:104px;box-sizing:border-box;overflow:hidden;align-items:stretch;padding:10px 13px}
  .ph-row:has(.ph-cam){grid-template-columns:25% minmax(0,1fr);padding:0 13px 0 0}
  .ph-row:has(.ph-cam) .ph-cam{grid-row:1 / -1;height:100%;aspect-ratio:auto}
  .ph-row .ph-cam img{object-fit:contain}   /* ô cao theo dòng, ảnh 4:3 hiện TRỌN (không cắt) — vẫn "chụp sao thấy vậy" (b290) */
  .ph-row .ph-nm{grid-column:-2;align-self:end;display:block;overflow:visible}
  /* tên là phần tử RIÊNG, cắt ở dòng 2 — trước đây dòng mã nằm trong cùng khối cắt nên tên dài chỉ còn một dòng ("Bia lo…") */
  .ph-row .ph-ten{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:15px;line-height:1.3;font-weight:700}
  .ph-row .ph-sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ph-row:has(.ph-cam) .ph-nm{padding-top:10px}
  .ph-row .ph-pr{grid-column:-2;flex-direction:row;flex-wrap:nowrap;align-items:baseline;justify-content:flex-start;gap:8px;text-align:left;min-width:0}
  .ph-row:has(.ph-cam) .ph-pr{padding-bottom:10px}
  .ph-row .ph-w{overflow:hidden;text-overflow:ellipsis;min-width:0}
  .ph-row .ph-pr .tag{margin-left:auto;flex:0 0 auto}
  /* b323 · anh Đạt 28/09: hàng CHƯA có ảnh không chừa cột ảnh / chữ cái 25% — chữ dùng trọn bề ngang; nút chụp thu về một nút máy ảnh 44px góc trên phải */
  .ph-row:has(.ph-cam:not(.co)){grid-template-columns:minmax(0,1fr);padding:10px 13px;position:relative}
  .ph-row:has(.ph-cam:not(.co)) .ph-cam{position:absolute;top:4px;right:4px;width:44px;height:44px;border-radius:10px;background:transparent}
  .ph-row .ph-cam:not(.co) b{display:none}
  .ph-row .ph-cam:not(.co) .ph-cam-hh{position:static;width:30px;height:30px;border-radius:9px}
  .ph-row .ph-cam:not(.co) .ph-cam-hh svg{width:16px;height:16px}
  .ph-row:has(.ph-cam:not(.co)) .ph-nm{padding-right:44px;padding-top:0}
  .ph-row:has(.ph-cam:not(.co)) .ph-pr{padding-bottom:0}
  .spct-d{grid-template-columns:minmax(0,1fr) auto;row-gap:2px}
  .spct-d .d-luc{grid-column:1;grid-row:1}
  .spct-d .d-sl{grid-column:2;grid-row:1;text-align:right}
  .spct-d .d-nd{grid-column:1;grid-row:2}
  .spct-d .d-con{grid-column:2;grid-row:2;text-align:right}
}

/* ===== SOURCE: styles/dau-tien.css ===== */
/* ============================================================
   dau-tien.css · b319 · ④ LẦN ĐẦU MỞ APP — 3 bước toàn màn (frontend/dau-tien.js). Nền than, thẻ trắng giữa màn, một cột,
   nút chính cuối thẻ (luật form), chỗ bấm ≥ 44px, điện thoại thẻ phủ cả màn.
   ============================================================ */
.dt-man{position:fixed;inset:0;z-index:9000;display:flex;align-items:center;justify-content:center;padding:16px;background:#101B26;overflow:auto}
.dt-the{width:100%;max-width:640px;max-height:100%;display:flex;flex-direction:column;background:var(--paper);border-radius:14px;box-shadow:var(--shadow-lg);overflow:hidden}
.dt-dau{display:flex;align-items:center;gap:12px;padding:16px 20px 0}
.dt-logo{font-size:14px;font-weight:800;color:var(--ink)}
.dt-vach{display:flex;gap:6px;margin-left:auto}
.dt-vach i{display:block;width:32px;height:5px;border-radius:3px;background:var(--line)}
.dt-vach i.on{background:var(--or)}
.dt-so{font-size:12.5px;color:var(--slate)}
.dt-than{display:flex;flex-direction:column;gap:12px;padding:16px 20px;overflow:auto}
.dt-than h1{margin:0;font-size:24px;font-weight:800;color:var(--ink)}
.dt-than .f{display:flex;flex-direction:column;gap:4px}
.dt-than label{font-size:14px;font-weight:700}
.dt-than input{min-height:44px;font-size:16px}
.dt-o-dt{max-width:220px}
.dt-nganh{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px}
.dt-ng,.dt-hang{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:64px;padding:10px 12px;text-align:left;
  background:var(--paper);border:1.5px solid var(--line);border-radius:12px;color:var(--ink)}
.dt-ng:hover,.dt-hang:hover{border-color:#173247}
.dt-ng.on,.dt-hang.on{border-color:var(--or);background:var(--or-50);box-shadow:inset 0 0 0 1px var(--or)}
.dt-ng b,.dt-hang b{font-size:15px;font-weight:700}
.dt-ng span,.dt-hang span{font-size:12.5px;color:var(--slate)}
.dt-hangs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.dt-hang{min-height:112px}
.dt-hang svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:2;margin-bottom:4px}
.dt-than .text-action{align-self:flex-start}
.dt-nut{display:flex;justify-content:space-between;gap:12px;padding:12px 20px 18px;border-top:1px solid var(--line-2)}
.dt-nut .btn{min-height:44px;padding:0 18px}
.dt-loi{margin:10px 0 0;color:var(--red);font-weight:700;font-size:15px}
.dt-dang{align-self:center;color:var(--slate);font-weight:600}
@media (max-width:560px){
  .dt-man{padding:0;align-items:stretch}
  .dt-the{max-width:none;border-radius:0}
  .dt-hangs{grid-template-columns:1fr}
  .dt-hang{min-height:64px}
  .dt-nganh{grid-template-columns:1fr 1fr}
}

/* ===== SOURCE: styles/co-chu.css ===== */
/* ═══════════════════════════════════════════════════════════════════════════
   b323 · CỠ CHỮ TỐI THIỂU (anh Đạt 28/09, soi trên b322)
   · Mọi chữ ≥ 12px (nguồn CSS + chữ nội dòng đã nâng); chữ phụ quan trọng (mã hàng, tồn, "Khách trả", nhãn cột, thẻ) ≥ 12,5px — nâng ngay trong luật gốc.
   · Ngoại lệ anh cho: "Online · bNNN" ở chân thanh trái ≥ 11px (thanh 56px), tương phản ≥ 4,5.
   · Cỡ chữ LỚN phóng cả chữ phụ (trước đây chỉ tên hàng / giá to lên).
   Đo bằng docs/thiet-ke/b323/do-giao-dien.js (Chromium, chữ thật đang hiện trên màn).
   ═══════════════════════════════════════════════════════════════════════════ */
body.big .tag,body.big .cell-sub,body.big .tot-nhan,body.big th,body.big .ph-sub,body.big .ph-w,
body.big .kbd,body.big .ilb,body.big .p-stat,body.big small{font-size:14px}

/* b324 · anh Đạt 28/09: ô ngày TRẢ DÁNG b322 — MỘT ô (ngayVN — settings-ui.js). b323 thêm hộp nút lịch 44px ⇒ ô Hóa đơn điện thoại cao 70px.
   Nay: ô date gốc vẫn là cái hộp nhìn thấy, đúng mọi luật CSS cũ của từng màn — chỉ giấu chữ mm/dd/yyyy + biểu tượng gốc của nó.
   Ô chữ dd/mm/yyyy phủ trong suốt đúng lên hộp đó (viền trong suốt ⇒ lúc chọn thì viền xanh vẽ đúng chỗ viền ô gốc); biểu tượng lịch
   nhỏ nằm TRONG ô, bên phải, không nhận chạm (vùng bấm là .o-ngay-k::after).
   Khung .o-ngay-k đứng đúng vai ô gốc b322: nội dòng, rộng 100% như luật chung của input (chân chữ = chân chữ ô gốc) — màn nào đặt ô ngày
   rộng khác (width:auto / max-width) thì đặt y vậy cho khung (hoa-don · don-vi · lich · commerce; width nội dòng thì ngayVN chép sang). */
.o-ngay-k{position:relative;display:inline-flex;width:100%;min-width:0;max-width:100%}
.o-ngay-k>input.o-ngay-goc{color:transparent}
.o-ngay-k>input.o-ngay-goc::-webkit-datetime-edit,.o-ngay-k>input.o-ngay-goc::-webkit-calendar-picker-indicator{opacity:0}
.o-ngay-k>input.o-ngay{position:absolute;inset:0;width:100%;height:100%;min-width:0;min-height:0;padding-right:34px;background:transparent;border-color:transparent;box-shadow:none;
  font-family:var(--f-mono);font-variant-numeric:tabular-nums;text-align:left}
.o-ngay-k>input.o-ngay::placeholder{font-family:var(--f-mono)}
.o-ngay-k>input.o-ngay:focus{border-color:var(--sky-500);box-shadow:0 0 0 3px var(--sky-100)}
/* ô chữ readOnly lúc chạm tay (chặn bàn phím) giữ màu chữ thường; chỉ ô gốc readonly thật mới xám như input[readonly] */
.o-ngay-k>input.o-ngay[readonly]{color:inherit}
.o-ngay-k:has(>input.o-ngay-goc[readonly])>input.o-ngay{color:var(--slate)}
/* b324 · vùng bấm biểu tượng lịch: dải ~36px mép phải, cao hết ô (chuột bấm đây mới mở lịch; vùng chữ để gõ). Ô gốc khóa ⇒ không mời bấm. */
.o-ngay-k::after{content:'';position:absolute;top:0;right:0;bottom:0;width:36px;cursor:pointer}
.o-ngay-k:has(>input.o-ngay-goc:disabled)::after,.o-ngay-k:has(>input.o-ngay-goc[readonly])::after{cursor:default}
.o-ngay-ic{position:absolute;top:50%;right:10px;width:16px;height:16px;margin-top:-8px;color:var(--ink-2);pointer-events:none}
.o-ngay-ic svg{display:block;width:16px;height:16px;stroke-width:2}
