/* ===== POS KOREA STYLE - MICOVINA ===== */
:root{
  --bg:#d4d0c8;
  --panel:#ece9d8;
  --panel2:#f0eff0;
  --text:#000000;
  --muted:#6b6b6b;
  --line:#808080;
  --line2:#c0c0c0;
  --primary:#4a7a3f;
  --primary-dark:#2d5a22;
  --primary-text:#ffffff;
  --header-bg:#4a7a3f;
  --header2-bg:#6aad5e;
  --title-bar:#316a72;
  --btn-bg:#ece9d8;
  --btn-border:#808080;
  --btn-hover:#d4d0c8;
  --accent:#f59e0b;
  --danger:#cc0000;
  --danger-bg:#ffcccc;
  --success:#006600;
  --warning:#cc6600;
  --row-selected:#316a72;
  --row-selected-text:#fff;
  --row-alt:#f7f7f0;
  --shadow:inset 1px 1px 0 #fff, inset -1px -1px 0 #808080;
  --shadow-out:inset -1px -1px 0 #fff, inset 1px 1px 0 #808080;
  --radius:7px;
}
*{box-sizing:border-box;margin:0;padding:0}
body{
  margin:0;
  font-family:"Be Vietnam Pro","Segoe UI","Malgun Gothic",Arial,sans-serif;
  background:var(--bg);
  color:var(--text);
  font-size:12px;
  overflow:hidden;
  height:100vh;
}
button,input,select,textarea{font:inherit;font-size:12px}
button{cursor:pointer}

/* ===== TOP BAR (title bar) =====
   Bố cục: [thương hiệu — không co lại] .......... [nhóm hành động — co giãn, tự cuộn ngang nếu
   hết chỗ]. Trước đây khối thương hiệu (logo + tên) là 1 div không có bảo vệ chiều rộng, nằm
   trong .topbar (display:flex, justify-content:space-between) — khi tổng bề rộng các nút/khối bên
   phải vượt quá khung màn hình (thường gặp ở màn hình laptop cỡ trung, RỘNG HƠN mốc mobile 820px
   nên không kích hoạt được layout mobile, nhưng vẫn KHÔNG đủ chỗ cho desktop) trình duyệt tự co
   khối thương hiệu lại theo flex-shrink mặc định — vì bên trong nó cũng là flex nên chữ bị vỡ dòng
   theo từng cụm từ, rất xấu. Sửa: khối thương hiệu CỐ ĐỊNH không co (flex-shrink:0), phần co giãn
   chuyển hết sang ô tìm kiếm (có mức tối thiểu riêng) rồi tới toàn bộ nhóm nút — nếu vẫn không đủ
   chỗ, nhóm nút tự có thanh cuộn ngang ẩn thay vì vỡ chữ. */
.topbar{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  background:linear-gradient(180deg,#1a6b3a 0%,#0d5a2a 100%);
  color:#fff;
  padding:5px 12px;
  height:40px;
  border-bottom:2px solid #0a4020;
  box-shadow:0 2px 6px rgba(0,0,0,.15);
  flex-shrink:0;
}
.topbar-brand{
  display:flex;align-items:center;gap:8px;
  flex-shrink:0; /* KHÔNG BAO GIỜ để khối này bị co — xem lý do ở comment phía trên */
}
.topbar-logo{
  display:flex;align-items:center;justify-content:center;
  width:24px;height:24px;flex-shrink:0;
  background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.35);
  border-radius:6px;font-weight:800;font-size:14px;
}
.topbar .brand-name{font-size:14px;font-weight:700;letter-spacing:.01em;white-space:nowrap}
.top-actions{
  display:flex;gap:6px;align-items:center;
  flex:1 1 auto;min-width:0; /* cho phép co giãn/cuộn — khác khối thương hiệu ở trên */
  overflow-x:auto;overflow-y:hidden;
  scrollbar-width:none; /* Firefox: ẩn thanh cuộn cho gọn, vẫn cuộn được bằng chuột/trackpad */
  /* QUAN TRỌNG: KHÔNG đặt justify-content:flex-end ở đây — đã thử và gây lỗi âm thầm: khi nội
     dung tràn (overflow-x:auto), flex-end đẩy phần tràn sang ĐẦU bên trái container thay vì bên
     phải, khiến ô tìm kiếm + nút đầu tiên bị CẮT MẤT ở vị trí cuộn mặc định (scrollLeft=0) mà
     không có dấu hiệu báo lỗi nào — trông như nội dung "biến mất" dù DOM vẫn đúng. Giữ mặc định
     (flex-start) để phần tràn (nếu có) luôn nằm ở CUỐI bên phải, đúng hành vi cuộn thông thường. */
}
.top-actions::-webkit-scrollbar{display:none} /* Chrome/Safari/Edge: ẩn thanh cuộn cho gọn */
.top-actions>*{flex-shrink:0} /* nút/select/badge giữ nguyên kích thước — không bị bóp méo chữ */
.top-actions-divider{
  width:1px;align-self:stretch;margin:5px 2px;
  background:rgba(255,255,255,.18);flex-shrink:0;
}
.top-actions .search{
  height:28px;padding:3px 10px;font-size:11px;
  border:1px solid #c4c0b4;background:#fff;
  border-radius:var(--radius);width:180px;min-width:120px;
  flex-shrink:1; /* ô duy nhất được phép co lại trước khi tới lượt cuộn ngang toàn nhóm */
  transition:border-color .15s ease, box-shadow .15s ease;
}
.top-actions .search:focus{border-color:#5a9aa2;box-shadow:0 0 0 3px rgba(49,106,114,.12);outline:none}
.top-actions .btn{
  height:28px;padding:0 10px;font-size:11px;
  background:var(--btn-bg);border:1px solid #c4c0b4;
  border-radius:var(--radius);
  transition:background .15s ease, box-shadow .15s ease;
}
.top-actions .btn:hover{background:#d4e8d4;box-shadow:0 2px 5px rgba(0,0,0,.1)}
.launch-pos-btn{background:#1b7a3e!important;border-color:#155f30!important;color:#fff!important;font-weight:700}
.launch-pos-btn:hover{background:#1f8f47!important}
.top-actions .topbar-icon-btn{width:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}
.branch-select{
  height:28px;font-size:11px;border:1px solid rgba(255,255,255,.4);
  background:#fff;border-radius:var(--radius);padding:0 6px;color:var(--text);
}
.user-badge{color:rgba(255,255,255,.88);font-size:11px;white-space:nowrap}
@media(max-width:820px){
  /* Việc A + E: nút Sửa/Xóa & vùng chạm chung dễ bấm hơn bằng ngón tay (chuẩn tối thiểu ~40px) */
  .action-btn{min-height:30px;padding:6px 10px;font-size:12px;margin:2px 3px 2px 0}
  .pos-btn{min-height:32px;padding:6px 10px;font-size:13px}
  input,select,textarea{font-size:14px!important}
  input[type=number],input[type=text],input[type=date],select{min-height:32px}

  /* Việc B: dialog thêm/sửa (SP, NCC, Nhóm hàng...) chuyển 2 cột cố định -> 1 cột khi màn hẹp,
     tránh cột chính bị bóp còn ~190px như trước */
  .dialog-body{grid-template-columns:1fr!important}

  /* Thanh trên cùng: bỏ chiều cao cố định, cho tự xuống dòng. */
  .topbar{height:auto;flex-wrap:wrap;row-gap:6px;padding:8px}
  .top-actions{width:100%;flex-wrap:wrap;overflow:visible}
  .top-actions-divider{display:none}
  .top-actions .search{flex:1 1 100%;width:auto;min-width:0;height:30px;font-size:13px}
  .top-actions a.pos-btn,
  .top-actions button.pos-btn{flex:1 1 auto;height:30px;font-size:12px;white-space:nowrap}
}

/* Việc D — gộp gọn thanh 12 tab thành menu sổ xuống trên mobile.
   Mặc định ẩn nút toggle (chỉ hiện khi màn hình hẹp); tab-bar mặc định vẫn hiển thị bình thường
   trên desktop, chỉ chuyển thành dropdown khi ở mobile VÀ đang bấm mở. */
.mobile-nav-toggle{
  display:none;
  width:100%;
  background:linear-gradient(180deg,#4a9a5a 0%,#316a3a 100%);
  color:#fff;border:none;border-bottom:2px solid #205a28;
  padding:10px 12px;font-size:14px;font-weight:700;text-align:left;
  cursor:pointer;
}
@media(max-width:820px){
  .mobile-nav-toggle{display:block}
  .tab-bar{display:none!important}
  /* QUAN TRỌNG: mọi thuộc tính layout của menu mobile phải đặt ở SELECTOR NÀY (.tab-bar.mobile-open,
     2 class) chứ không phải .tab-bar (1 class) — vì có 1 rule ".tab-bar{...}" KHÁC (không nằm trong
     @media) nằm ở PHÍA SAU trong file (mục "NAV TABS"), cùng độ ưu tiên 1-class nên nó sẽ THẮNG và
     âm thầm ghi đè bất kỳ thuộc tính nào đặt ở .tab-bar thường tại đây. Dùng .tab-bar.mobile-open
     (2 class) để luôn thắng bất kể thứ tự khai báo trong file.

     QUAN TRỌNG #2: dùng position:fixed + "top" ĐO THẬT bằng JS (xem toggleMobileNav() trong app.js)
     thay vì đoán chiều cao topbar bằng số cố định/calc(vh) — vì topbar có ô tìm kiếm + nhiều nút,
     rất dễ XUỐNG DÒNG trên màn hẹp làm topbar cao thấp khác nhau tuỳ máy/tuỳ lúc, đoán sai 1 chút
     là menu bị che khuất mất phần trên hoặc bị đẩy tràn xuống dưới màn hình không cuộn tới được. Với
     position:fixed + bottom:0 + top đo thật, menu LUÔN vừa khít đúng phần còn lại của màn hình. */
  .tab-bar.mobile-open{
    display:block!important;
    position:fixed;
    top:96px; /* dự phòng — sẽ bị JS ghi đè bằng giá trị đo thật ngay khi mở menu */
    left:0; right:0; bottom:0;
    z-index:1000;
    background:#fff;
    box-shadow:0 8px 20px rgba(0,0,0,.25);
    padding:6px;
    margin:0;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    touch-action:pan-y;
    overscroll-behavior:contain;
  }
  /* display:block (không flex) — mỗi tab CHẮC CHẮN chiếm trọn 1 hàng, không có chuyện co lại hay
     nhảy sang "cột" khác khi danh sách dài hơn khung nhìn (đây chính là nguyên nhân bị chèn ép/che
     khuất nhau ở lần sửa trước — dùng flex-direction:column dễ bị trình duyệt tự ý bóp nhỏ hoặc bẻ
     sang cột mới khi nội dung dài hơn khung, dù đã set flex-wrap:nowrap). */
  .tab-bar.mobile-open .tab-btn{
    display:block;
    width:100%;
    max-width:none;
    text-align:left;
    border-radius:6px;
    margin-bottom:3px;
  }
}

/* ===== NAV TABS ===== */
.sidebar{
  display:none; /* hidden - nav is now tab bar */
}
.tab-bar{
  display:flex;align-items:stretch;gap:4px;flex-wrap:wrap;
  background:var(--bg);
  padding:6px 8px 0;
  border-bottom:2px solid var(--primary-dark);
  flex-shrink:0;
}
.tab-btn{
  /* flex-grow/shrink giống hệt nhau trên mọi tab → luôn ra ĐÚNG 1 độ rộng bằng nhau,
     bất kể chữ dài ngắn khác nhau (VD "In tem" vs "Kiểm soát HSD"). */
  flex:1 1 110px;
  max-width:170px;
  border:1px solid var(--line2);
  border-bottom:none;
  background:#fbfbf8;
  color:var(--primary-dark);
  padding:8px 6px;
  font-size:12px;
  font-weight:600;
  border-radius:6px 6px 0 0;
  text-align:center;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  position:relative;
  top:1px;
  cursor:pointer;
  box-shadow:0 -1px 2px rgba(0,0,0,.05);
  transition:background .15s ease, color .15s ease, box-shadow .15s ease;
}
.tab-btn:hover{background:#e6f2e3;color:var(--primary-dark)}
.tab-btn.active{
  background:linear-gradient(180deg,var(--header2-bg) 0%,var(--primary) 100%);
  border-color:var(--primary-dark);
  color:#fff;
  font-weight:700;
  z-index:2;
  box-shadow:0 -3px 6px rgba(0,0,0,.18);
}

/* ===== DROPDOWN "Quản lý kho" (gộp Hàng hoá/Tồn kho/Nhập kho/Xuất-Bán/Nhóm hàng/HSD/Chi phí) =====
   CHỈ áp dụng dạng dropdown trên PC (>820px) — trên mobile menu đã tự xổ dọc toàn bộ (.mobile-open)
   nên để nguyên dạng phẳng, dùng display:contents để "gỡ" khung bọc ra, coi 7 nút con như đang nằm
   thẳng trong .tab-bar (không lồng thêm 1 cấp), tránh phải viết lại toàn bộ logic mobile-open. */
.tab-dropdown{position:relative;display:inline-flex}
.tab-dropdown-menu{
  position:fixed; /* toạ độ top/left do JS đo & gán thật (xem positionDropdownMenu() trong app.js) —
                      dùng fixed để THOÁT khỏi #navHeader (có overflow:hidden) là cha của tab-bar,
                      nếu để absolute thì phần menu tràn ra sẽ bị cắt/che bởi overflow đó. */
  z-index:1500; /* cao hơn hẳn nội dung các tab (.view, .db-wrap...) để không bị đè lên */
  min-width:190px;
  background:#fff;
  border:1px solid var(--primary-dark);
  border-radius:8px;
  box-shadow:0 8px 18px rgba(0,0,0,.22);
  padding:5px;
  display:flex;
  flex-direction:column;
  gap:3px;
  /* Hiệu ứng "sổ ra": mờ dần + trượt nhẹ từ trên xuống + hơi co theo chiều cao, thay vì bật/tắt
     display đột ngột. visibility trễ khi ĐÓNG (transition-delay) để opacity/transform kịp chạy hết
     trước khi thật sự biến mất; lúc MỞ thì visibility đổi ngay (delay 0s) để không bị "khựng". */
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transform:translateY(-8px) scaleY(.94);
  transform-origin:top left;
  transition:opacity .16s ease, transform .16s ease, visibility 0s linear .16s;
}
.tab-dropdown.open .tab-dropdown-menu{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transform:translateY(0) scaleY(1);
  transition:opacity .16s ease, transform .16s ease, visibility 0s linear 0s;
}
.tab-dropdown-menu .tab-btn{
  flex:none;max-width:none;width:100%;
  text-align:left;
  border-radius:4px;
  border-bottom:1px solid var(--line2);
  top:0;box-shadow:none;
}
/* Tiêu đề nhóm nhỏ, không bấm được, chỉ để phân tách các mục trong dropdown (VD "Công cụ hệ thống"
   / "Công cụ riêng") — ẩn/hiện tuỳ quyền qua class .hidden như các nút khác (xem setupUserUI()). */
.tab-dropdown-section{
  font-size:10px;font-weight:800;color:#8a8;text-transform:uppercase;letter-spacing:.04em;
  padding:5px 8px 2px;margin-top:2px;
  border-top:1px solid var(--line2);
}
.tab-dropdown-section:first-child{border-top:none;margin-top:0}

/* Menu lồng cấp 2 — "Công cụ hệ thống ▸"/"Cài đặt hệ thống ▸" giờ là 1 mục CÓ THỂ DI CHUỘT VÀO để sổ
   thêm 1 khung con các tab bên trong, sang CẠNH PHẢI (hoặc trái nếu không đủ chỗ — xem openSubmenu()
   trong app.js) — y hệt kiểu menu chuột phải nhiều cấp quen thuộc, thay vì dàn hết ra cùng 1 khung. */
.tab-dropdown-subgroup{position:relative}
.tab-dropdown-section-trigger{
  cursor:default;user-select:none;
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  font-size:12px!important;font-weight:700!important;color:var(--primary-dark)!important;
  text-transform:none!important;letter-spacing:0!important;
  background:#eaf3ea;
  padding:7px 10px!important;
  border-top:none!important;
  border-radius:4px;
}
.tab-dropdown-section-arrow{font-weight:800;color:var(--primary)}
/* Tô đậm hẳn (nền xanh đậm, chữ trắng) khi đang di chuột vào NHÓM đó hoặc khung con của nó đang mở —
   để thấy rõ ràng đây là 1 mục "còn sổ thêm được", không phải chỉ 1 dòng chữ phân cách tĩnh như trước. */
.tab-dropdown-subgroup:hover .tab-dropdown-section-trigger{
  background:var(--primary);color:#fff!important;
}
.tab-dropdown-subgroup:hover .tab-dropdown-section-arrow{color:#fff}
.tab-dropdown-submenu{
  position:absolute;top:-5px;left:100%;margin-left:2px;
  display:none;flex-direction:column;gap:3px;
  min-width:190px;
  background:#fff;border:1px solid var(--primary-dark);border-radius:6px;
  box-shadow:0 8px 18px rgba(0,0,0,.22);
  padding:5px;z-index:1;
}
.tab-dropdown-submenu.open{display:flex}
.tab-dropdown-submenu.flip-left{left:auto;right:100%;margin-left:0;margin-right:2px}
.tab-dropdown .dropdown-trigger.active-group{
  background:linear-gradient(180deg,var(--header2-bg) 0%,var(--primary) 100%);
  border-color:var(--primary-dark);
  color:#fff;font-weight:700;
}
@media(max-width:820px){
  .tab-dropdown{display:contents}
  .tab-dropdown .dropdown-trigger{display:none} /* nút "Quản lý kho ▾" không cần trên mobile, 7 nút con hiện thẳng như các tab khác */
  .tab-dropdown-menu{
    display:contents; /* bỏ khung bọc, 7 nút con nằm ngang hàng các tab khác trong menu mobile-open */
    /* QUAN TRỌNG: phải RESET LẠI hết các thuộc tính hiệu ứng "sổ ra" dành cho PC (opacity/visibility/
       transform/pointer-events ở rule .tab-dropdown-menu phía trên) — display:contents KHÔNG tự huỷ
       các thuộc tính này, và visibility đặc biệt còn bị NÚT CON BÊN TRONG KẾ THỪA (visibility là thuộc
       tính có tính kế thừa) dù chính .tab-dropdown-menu không còn sinh ra khung nữa — nếu không reset,
       toàn bộ nút con (Hàng hoá, Tồn kho, Nhà cung cấp...) bị ẩn mất trên mobile dù chiếm đúng vị trí. */
    opacity:1!important;
    visibility:visible!important;
    pointer-events:auto!important;
    transform:none!important;
    position:static!important;
  }
  /* Trên PC, "Công cụ hệ thống"/"Cài đặt POS"... chỉ là dòng chữ nhỏ NẰM BÊN TRONG khung menu thả
     xuống (min-width:190px) nên đủ rõ nghĩa nhờ bối cảnh xung quanh. Trên mobile, khung đó không còn
     (đã display:contents flatten hết vào chung 1 danh sách dọc) — nếu giữ nguyên cỡ chữ 10px + màu
     xám nhạt như cũ, dòng chữ này trôi lơ lửng giữa các nút to, KHÔNG còn ai hiểu nó đang phân nhóm
     cho mấy nút NGAY DƯỚI nó. Làm nó thành 1 THANH TIÊU ĐỀ rõ ràng, đủ to, có màu nền — đúng vai trò
     "đầu mục" của 1 nhóm trong danh sách dọc, thay vì nhãn phụ nằm cạnh các nút như bên PC. */
  .tab-dropdown-section{
    font-size:12px!important;
    color:#fff!important;
    background:var(--primary-dark,#2d5a2f);
    padding:7px 10px!important;
    margin:8px -2px 4px!important;
    border-top:none!important;
    border-radius:5px;
  }
  .tab-dropdown-section:first-child{margin-top:8px!important}
  /* Khung con lồng cấp 2 (Công cụ hệ thống ▸/Cài đặt hệ thống ▸...) — mobile KHÔNG có "di chuột vào"
     nên phải "duỗi phẳng" LUÔN HIỆN SẴN, giống hệt cách .tab-dropdown-menu đã được duỗi phẳng ở trên,
     cùng lý do phải reset lại toàn bộ thuộc tính ẩn/hiện dành riêng cho hiệu ứng sổ ra trên PC. */
  .tab-dropdown-subgroup{display:contents}
  .tab-dropdown-submenu{
    display:contents!important;
    position:static!important;
    opacity:1!important;visibility:visible!important;pointer-events:auto!important;
  }
}

/* ===== TOOL SUB-TABS (tab con bên trong "🔧 Công cụ") =====
   Dùng chung style với .tab-btn nhưng nhỏ hơn 1 cấp, để phân biệt đây là tab CON, không phải tab
   chính — cho phép thêm nhiều công cụ mới sau này mà không phải sửa lại HTML/CSS. */
.tool-tab-bar{
  display:flex;align-items:stretch;gap:4px;flex-wrap:wrap;
  padding:8px 12px 0;
  border-bottom:1px solid var(--line2);
  flex-shrink:0;
}
.tool-tab-btn{
  border:1px solid var(--line2);
  border-bottom:none;
  background:#fff;
  color:var(--primary-dark);
  padding:6px 14px;
  font-size:12px;
  font-weight:600;
  border-radius:6px 6px 0 0;
  cursor:pointer;
  position:relative;
  top:1px;
}
.tool-tab-btn:hover{background:#e6f2e3}
.tool-tab-btn.active{
  background:var(--primary);
  border-color:var(--primary-dark);
  color:#fff;
  font-weight:700;
}
.tool-panel{display:none}
.tool-panel.active{display:block}
/* Tab CON bên trong "🏠 Quản lý phòng trọ" — CỐ TÌNH đặt tên class RIÊNG (không trùng .tool-tab-btn/
   .tool-panel) để switchToolTab() ở tab NGOÀI không bị nhầm lẫn quét trúng các tab con này. */
.rental-subtab-bar{
  display:flex;align-items:stretch;gap:4px;flex-wrap:wrap;
  padding:0 0 8px;margin-bottom:10px;
  border-bottom:2px solid var(--primary);
}
.rental-subtab-btn{
  border:1px solid var(--line2);
  background:#fff;color:var(--primary-dark);
  padding:6px 12px;font-size:11.5px;font-weight:600;
  border-radius:5px;cursor:pointer;
}
.rental-subtab-btn:hover{background:#e6f2e3}
.rental-subtab-btn.active{
  background:var(--primary);border-color:var(--primary-dark);
  color:#fff;font-weight:700;
}
.rental-subtab-panel{display:none}
.rental-subtab-panel.active{display:block}
@media(max-width:820px){
  .rental-subtab-btn{flex:1 1 auto}
}
@media(max-width:820px){
  .tool-tab-bar{flex-wrap:wrap}
  .tool-tab-btn{flex:1 1 auto}
}

/* ===== TAB "⚙️ Cài đặt" — chỉ hiện đúng 1 mục đang chọn (không có thanh nút chọn ngay trên trang,
   việc chuyển mục hoàn toàn qua dropdown "⚙️ Cài đặt ▾" ở thanh tab chính — xem index.html +
   switchSettingsTab()/openSettingsSection() trong app.js). */
.settings-panel{display:none;max-width:760px;margin:0 auto;padding:14px 4px}
.settings-panel.active{display:block}
.settings-panel-title{
  font-size:15px;font-weight:800;color:var(--primary-dark);
  padding-bottom:8px;margin-bottom:12px;
  border-bottom:2px solid var(--primary);
}

/* ===== LAYOUT ===== */
.app-shell{display:flex;flex-direction:column;height:100vh}
/* Khung TOP BAR + TAB BAR — co lại (ẩn) khi cuộn chuột xuống, hiện lại khi cuộn lên (xem app.js),
   để nhường thêm diện tích xem nội dung. max-height 400px đủ dư (kể cả khi tab-bar xuống hàng 3
   dòng trên màn hẹp) — CHỈ áp dụng ở desktop (>820px), trên mobile giữ nguyên hành vi cũ vì menu
   mobile dùng cơ chế "mobile-open" (position:fixed) riêng, không liên quan tới khung này. */
.nav-header{max-height:400px;overflow:hidden;transition:max-height .25s ease,opacity .2s ease}
@media(min-width:821px){
  .nav-header.nav-collapsed{max-height:0;opacity:0}
}
.app{
  flex:1;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  background:var(--bg);
}
.view{display:none;flex:1;overflow:hidden;flex-direction:column}
.view.active{display:flex}

/* Trang "In tem" (#labels) có 4 tab (Tem kệ / Tem SP / QC 1 SP / QC 9 SP), mỗi tab có thể cao hơn
   màn hình (nhiều tem, ảnh quảng cáo lớn...) — .view mặc định overflow:hidden nên bị cắt mất phần
   dưới, KHÔNG có thanh cuộn để xem hết. Đổi riêng #labels sang block + overflow-y:auto để luôn có
   thanh cuộn dọc khi cần, không ảnh hưởng các trang khác. */
#labels.view.active{
  display:block;
  overflow-y:auto;
  overflow-x:hidden;
}

/* Panel "🔍 Rà soát thiếu dữ liệu" (Danh mục hàng hóa) — kiểu DROPDOWN NỔI (như menu bấm-là-sổ-ra)
   thay vì chèn thẳng vào layout như trước: trước đây panel là 1 khối cố định BÊN TRÊN bảng hàng hóa,
   nên mở ra là chiếm mất diện tích của bảng (kể cả trên PC màn hình rộng, không riêng gì mobile).
   Giờ panel dùng position:absolute (position:relative đặt ở .aud-dropdown-wrap bọc quanh nút bấm) —
   nổi lên TRÊN bảng hàng hóa như 1 menu thả xuống thật sự, KHÔNG chiếm chỗ trong layout nên bảng
   hàng hóa luôn giữ nguyên kích thước dù panel đang mở hay đóng, đồng thời cũng tự giải quyết luôn
   vấn đề "bị che cứng, không cuộn" từng gặp trên mobile (panel không còn đẩy/ép layout nữa). Đóng khi
   bấm ra ngoài (xem closeProductAuditPanelIfOutside() ở app.js). */
.aud-dropdown-wrap{position:relative;display:inline-block}
.aud-dropdown{
  position:absolute;
  top:calc(100% + 4px);
  left:0;
  z-index:60;
  background:#fff;
  border:1px solid #c7d9c7;
  border-radius:8px;
  box-shadow:0 10px 28px rgba(0,0,0,.2);
  padding:10px 12px;
  width:560px;
  max-width:92vw;
  max-height:70vh;
  overflow-y:auto;
}
@media(max-width:820px){
  .aud-dropdown{
    left:50%;
    transform:translateX(-50%);
    width:94vw;
  }
}

/* ============================================================================
   TỐI ƯU MOBILE — layout "2 khung" (.two-pane): Nhập kho, Xuất/Bán, Nhà cung cấp, Chi phí.
   .two-pane vốn là CSS Grid 2 cột CỐ ĐỊNH (240px + phần còn lại) cho desktop — trên màn hình di
   động hẹp, 2 cột bị ép nằm CẠNH NHAU thay vì xếp chồng, khiến khung form nhập liệu bị bóp còn
   ~240px (nhãn + ô nhập chồng chéo, không dùng được), CỘNG THÊM .view mặc định overflow:hidden
   (thiết kế "1 màn hình cố định", xem lý do ở #labels bên trên) khiến không có cách nào cuộn xuống
   để xem hết form hay bảng lịch sử bên cạnh — đúng lỗi "form cứng đơ, không cuộn, không xem được
   hết" đã gặp. Fix: TRÊN MOBILE, xếp 2 khung CHỒNG DỌC (form trước, bảng lịch sử sau) + cho cuộn dọc
   toàn trang, thay vì ép 2 cột cố định + overflow:hidden như bên desktop. */
@media(max-width:820px){
  #purchase.view.active,
  #sales.view.active,
  #suppliers.view.active,
  #expenses.view.active{
    display:block;
    overflow-y:auto;
    overflow-x:hidden;
  }
  #purchase.view.active .two-pane,
  #sales.view.active .two-pane,
  #suppliers.view.active .two-pane,
  #expenses.view.active .two-pane{
    display:flex;
    flex-direction:column;
    overflow:visible;
    height:auto;
  }
  #purchase.view.active .two-pane .pane,
  #sales.view.active .two-pane .pane,
  #suppliers.view.active .two-pane .pane,
  #expenses.view.active .two-pane .pane{
    overflow:visible;
    flex:none;
  }
  #purchase.view.active .two-pane .pane .form-section,
  #sales.view.active .two-pane .pane .form-section,
  #suppliers.view.active .two-pane .pane .form-section,
  #expenses.view.active .two-pane .pane .form-section{
    overflow:visible;
    flex:none;
  }
  /* Bảng lịch sử bên dưới: giới hạn chiều cao + tự cuộn riêng trong khung đó, tránh trang dài vô tận
     nếu có hàng trăm/nghìn dòng lịch sử — vẫn xem được đầy đủ form phía trên trước khi cuộn tới. */
  #purchase.view.active .two-pane .pane .table-wrap,
  #sales.view.active .two-pane .pane .table-wrap,
  #suppliers.view.active .two-pane .pane .table-wrap,
  #expenses.view.active .two-pane .pane .table-wrap{
    flex:none;
    max-height:60vh;
  }
}

/* ===== SECTION TITLE BAR ===== */
.section-title{
  background:linear-gradient(180deg,#4a9a5a 0%,#316a3a 100%);
  color:#fff;
  font-size:13px;
  font-weight:700;
  padding:5px 12px;
  display:flex;align-items:center;gap:8px;
  border-bottom:1px solid #205a28;
  flex-shrink:0;
  flex-wrap:wrap; /* cho cả dòng tiêu đề tự xuống dòng nếu quá dài — không chỉ riêng title-actions,
                     tránh lặp lại lỗi tràn ngang mất nút bấm khi thanh công cụ có nhiều mục (VD:
                     tab Tồn kho sau khi thêm ô "Hiện cả SP không theo dõi tồn kho") */
  row-gap:4px;
}
.section-title .icon{font-size:14px}
.section-title .title-actions{
  margin-left:auto;
  display:flex;
  gap:4px;
  flex-wrap:wrap;
  min-width:0; /* QUAN TRỌNG: nếu không có dòng này, trình duyệt có thể tính chiều rộng "lý tưởng"
                  của title-actions là đủ chỗ cho TẤT CẢ mục nằm 1 hàng rồi mới tràn ra ngoài thay
                  vì chủ động xuống dòng — min-width:0 cho phép co lại đúng cách để flex-wrap thực
                  sự kích hoạt khi không đủ chỗ. */
}

/* ============================================================================
   TỐI ƯU MOBILE — Mục "In tem" (#labels)
   Toàn bộ app này thiết kế cho desktop, không có breakpoint mobile nào từ trước.
   Thanh công cụ mỗi tab (ô tìm SP + số lượng + các nút) rất dễ tràn ra ngoài màn
   hình điện thoại (đo thực tế: tràn tới ~280px ở khổ 390px) vì .title-actions
   không tự xuống dòng và các input bên trong có min-width cố định quá lớn.
   ========================================================================= */
@media(max-width:820px){
  #labels .section-title{flex-wrap:wrap;row-gap:6px;padding:8px 10px}
  #labels .section-title .title-actions{
    width:100%;margin-left:0;
    flex-wrap:wrap;
  }
  #labels .section-title .title-actions input,
  #labels .section-title .title-actions select{
    flex:1 1 130px;
    min-width:0!important;
    height:30px!important;
    font-size:13px!important;
  }
  #labels .section-title .title-actions .pos-btn{
    flex:1 1 auto;
    height:30px;
    font-size:12px;
    padding:4px 8px;
  }
  #labels .product-suggest-box{width:100%!important}

  /* Thanh tab con (Tem kệ / Tem SP / QC 1 SP / QC 9 SP / Ảnh Tem): cho cuộn ngang gọn thay vì
     chữ bị bóp quá nhỏ hoặc wrap lộn xộn nhiều hàng */
  #labels > div.no-print{
    flex-wrap:nowrap!important;
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  #labels > div.no-print::-webkit-scrollbar{display:none}
  #labels > div.no-print .pos-btn{flex:0 0 auto;white-space:nowrap;font-size:12px;padding:6px 10px}

  /* Tab "Ảnh Tem": 2 khung ảnh xếp dọc thay vì cạnh nhau cho vừa màn hình hẹp */
  #printPanel5 > div{flex-direction:column;align-items:center}
  #printPanel5 canvas{max-width:100%!important}
}


/* ===== POS BUTTONS ===== */
.pos-btn{
  border:1px solid #c4c0b4;
  background:var(--btn-bg);
  color:var(--text);
  padding:5px 12px;
  font-size:12px;
  border-radius:var(--radius);
  white-space:nowrap;
  box-shadow:0 1px 2px rgba(0,0,0,.06);
  transition:background .15s ease, box-shadow .15s ease, transform .08s ease, border-color .15s ease;
}
.pos-btn:hover{background:#d4e8d4;border-color:#b4d4b4;box-shadow:0 2px 5px rgba(0,0,0,.1)}
.pos-btn:active{transform:scale(.97);box-shadow:0 1px 1px rgba(0,0,0,.08)}
.pos-btn.primary{background:#d3ecd3;color:#004400;font-weight:700;border-color:#a8d4a8}
.pos-btn.danger{background:#fbdada;color:#880000;font-weight:700;border-color:#eeb8b8}
.pos-btn.accent{background:#fff3cc;color:#664400;font-weight:700;border-color:#e8d488}
.pos-btn.blue{background:#d6e6ff;color:#002288;font-weight:700;border-color:#a8c8f0}

/* ===== TWO PANE LAYOUT ===== */
.two-pane{
  display:grid;
  grid-template-columns:240px 1fr;
  gap:2px;
  flex:1;
  overflow:hidden;
  background:#808080;
  padding:4px;
}
.two-pane.wide-list{grid-template-columns:320px 1fr}
/* Riêng tab "Nhập kho" — cột trái (form "Thêm phiếu nhập kho") rộng hơn hẳn cột 240px mặc định
   (labels/ô nhập bị cắt/dồn chữ ở bề rộng đó) — vẫn giữ nguyên bố cục 2 cột CẠNH NHAU như các tab
   khác (không đẩy full lên trên/xuống dưới), chỉ đổi bề rộng cột trái. Mobile không đổi gì (vẫn
   xếp chồng dọc như cũ qua @media bên dưới). */
#purchase .two-pane{grid-template-columns:420px 1fr}
.pane{
  background:var(--panel2);
  border:2px solid;
  border-color:#808080 #fff #fff #808080;
  display:flex;flex-direction:column;
  overflow:hidden;
  min-height:0;
}
.pane-head{
  background:linear-gradient(180deg,#4a7a3f 0%,#316a30 100%);
  color:#fff;
  padding:4px 8px;
  font-size:12px;
  font-weight:700;
  display:flex;align-items:center;justify-content:space-between;
  flex-shrink:0;
}
.pane-head .pane-actions{display:flex;gap:3px}

/* ===== MINI LIST (left pane) ===== */
.mini-list-table{width:100%;border-collapse:collapse;flex:1}
.mini-list-table th{
  background:#4a7a3f;color:#fff;font-size:11px;
  padding:3px 5px;font-weight:700;text-align:left;
  position:sticky;top:0;z-index:1;
}
.mini-list-table td{
  padding:3px 5px;font-size:12px;border-bottom:1px solid #e0e0e0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:0;
}
.mini-list-table tr:nth-child(even) td{background:#f0f7f0}
.mini-list-table tr:hover td{background:#d0e8d0;cursor:pointer}
.mini-list-table tr.selected td{background:#316a72!important;color:#fff!important}
.mini-scroll{overflow:auto;flex:1}
.mini-list-wrap{display:flex;flex-direction:column;flex:1;overflow:hidden}

/* ===== DETAIL PANE ===== */
.detail-pane{padding:6px 8px;overflow:auto;flex:1}
.detail-section{
  border:1px solid var(--line2);
  margin-bottom:6px;
  background:#fff;
}
.detail-section-head{
  background:linear-gradient(180deg,#4a7a3f,#316a30);
  color:#fff;font-size:11px;font-weight:700;
  padding:3px 8px;display:flex;align-items:center;gap:5px;
}
.detail-section-head::before{content:"◆ ";font-size:10px}
.detail-grid{
  display:grid;
  grid-template-columns:repeat(2,1fr);
  gap:0;
}
.detail-grid.cols3{grid-template-columns:repeat(3,1fr)}
.detail-row{
  display:flex;align-items:center;
  border-bottom:1px solid #e0e0e0;
  min-height:26px;
}
.detail-row:last-child{border-bottom:none}
.detail-label{
  width:110px;flex-shrink:0;
  background:#e8f0e8;
  color:#225522;
  font-weight:700;font-size:11px;
  padding:3px 6px;
  border-right:1px solid var(--line2);
  display:flex;align-items:center;
}
.detail-label.required::before{content:"*";color:red;margin-right:2px}
.detail-value{flex:1;padding:2px 6px;display:flex;align-items:center;gap:4px}
.detail-value input,.detail-value select,.detail-value textarea{
  flex:1;border:1px solid #c4c0b4;padding:3px 7px;
  background:#fff;border-radius:var(--radius);height:26px;
  font-size:12px;outline:none;transition:border-color .15s ease, box-shadow .15s ease;
}
.detail-value input:focus,.detail-value select:focus,.detail-value textarea:focus{border-color:#5a9aa2;box-shadow:0 0 0 3px rgba(49,106,114,.12)}
.detail-value input:focus,.detail-value select:focus{
  border-color:#316a72;background:#f0f8ff;
}
.detail-value textarea{height:auto;resize:vertical}
.detail-value .unit{color:var(--muted);font-size:11px;white-space:nowrap}
.detail-value .pos-btn{height:22px;padding:0 6px;font-size:11px}
.read-val{font-weight:700;color:#003300;font-size:13px;padding:2px 6px}
.inline-note{color:var(--muted);font-size:11px;margin-left:4px}

/* ===== IMAGE BOX ===== */
.img-box{
  width:100%;height:140px;
  border:1px inset #808080;
  background:#e8e8e8;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
  flex-direction:column;gap:4px;
}
.img-box img{max-width:100%;max-height:130px;object-fit:contain}
.img-box .no-img{color:#888;font-size:11px}
.img-change-btn{
  width:100%;text-align:center;font-size:11px;padding:2px;
  border:1px solid var(--line2);background:#e8e8e8;
}

/* ===== ACTION BAR (top of detail) ===== */
.action-bar{
  background:#316a72;
  padding:4px 8px;
  display:flex;align-items:center;gap:4px;
  flex-shrink:0;
  border-bottom:1px solid #1a4a52;
}
.action-bar-title{
  color:#fff;font-size:13px;font-weight:700;
  margin-right:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.action-bar .pos-btn{height:24px;padding:0 10px;font-size:12px}

/* ===== TABLE VIEW (full width) ===== */
.full-pane{
  background:var(--panel2);
  border:2px solid;
  border-color:#808080 #fff #fff #808080;
  display:flex;flex-direction:column;
  overflow:hidden;flex:1;
}
.table-toolbar{
  background:#e0e0d0;
  padding:4px 8px;
  display:flex;align-items:center;gap:6px;
  border-bottom:1px solid var(--line2);
  flex-shrink:0;
  flex-wrap:wrap;
}
.table-toolbar input,.table-toolbar select{
  height:26px;padding:2px 7px;font-size:11px;
  border:1px solid #c4c0b4;background:#fff;border-radius:var(--radius);
  transition:border-color .15s ease, box-shadow .15s ease;
}
.table-toolbar input:focus,.table-toolbar select:focus{border-color:#5a9aa2;box-shadow:0 0 0 3px rgba(49,106,114,.12);outline:none}
.table-toolbar .search{min-width:150px}
.table-wrap{overflow:auto;flex:1}

/* ── Popup xem nhanh "Chuyển tiền"/"Gửi hàng" ở mục Khách hàng — xem giải thích ở
   showCustHoverTooltip() trong app.js (dùng position:fixed, gắn ra ngoài <body> để không bị bảng
   cuộn cắt mất). ── */
.cust-hover-trigger{cursor:default;border-bottom:1px dotted #999}
.cust-hover-popup{
  display:none;position:fixed;z-index:9999;
  background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 4px 16px rgba(0,0,0,.22);
  padding:8px 10px;min-width:200px;max-width:320px;
  font-size:11px;line-height:1.5;color:#222;text-align:left;
}
.cht-row{padding:4px 0;border-bottom:1px solid #eee}
.cht-row:last-child{border-bottom:none;padding-bottom:0}
.cht-sub{color:#777;font-size:10px}
.cht-row-top{display:flex;align-items:center;justify-content:space-between;gap:6px}
.cht-copy-btn{
  flex-shrink:0;border:1px solid #bcd;background:#eef4ff;color:#1565c0;
  border-radius:3px;font-size:10px;padding:2px 6px;cursor:pointer;
  transition:background .15s ease;
}
.cht-copy-btn:hover{background:#dcebff}
.cht-copy-btn:disabled{background:#e8f5e9;border-color:#a5d6a7;color:#2e7d32;cursor:default}

table{width:100%;border-collapse:collapse;background:#fff;min-width:0}
th{
  position:sticky;top:0;
  background:#4a7a3f;color:#fff;
  font-size:11px;font-weight:700;text-transform:none;
  padding:4px 6px;border-right:1px solid #316a30;
  letter-spacing:0;z-index:1;text-align:left;white-space:nowrap;
}
td{
  padding:3px 6px;border-bottom:1px solid #e0e0e0;
  font-size:12px;vertical-align:middle;text-align:left;
  white-space:nowrap;
}
tbody tr:nth-child(even) td{background:#f0f7f0}
tbody tr:hover td{background:#d0e8d0;cursor:pointer}
tbody tr.selected td{background:#316a72!important;color:#fff}
td.num{text-align:right;font-variant-numeric:tabular-nums}

/* ===== BADGES ===== */
.badge{display:inline-block;padding:1px 6px;font-size:11px;font-weight:700;border:1px solid}
.badge.ok{background:#ccffcc;color:#004400;border-color:#009900}
.badge.low{background:#ffffcc;color:#664400;border-color:#cc8800}
.badge.out{background:#ffcccc;color:#880000;border-color:#cc0000}

/* ===== ACTION BUTTONS IN TABLE ===== */
.action-btn{
  border:1px solid #c4c0b4;
  background:#eee;padding:3px 8px;font-size:11px;
  border-radius:5px;cursor:pointer;
  transition:background .15s ease, transform .08s ease;
}
.action-btn:hover{background:#e0e0e0}
.action-btn:active{transform:scale(.95)}
.action-btn.danger{background:#ffcccc;color:#880000}

/* ===== PRODUCT THUMB ===== */
.product-thumb{width:36px;height:36px;object-fit:cover;border:1px solid var(--line2);background:#f0f0f0;display:block}
.image-empty{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border:1px dashed var(--line2);color:#aaa;font-size:10px;background:#f8f8f8}

/* ===== FORM (purchase/sales/supplier) ===== */
.form-section{padding:6px;display:flex;flex-direction:column;gap:0;overflow-y:auto;flex:1}
.form-row{display:flex;align-items:center;border-bottom:1px solid #ddd;min-height:26px}
.form-lbl{width:120px;flex-shrink:0;background:#e8f0e8;color:#225522;font-weight:700;font-size:11px;padding:2px 6px;border-right:1px solid #ccc;display:flex;align-items:center}
.form-lbl.req::before{content:"*";color:red;margin-right:2px}
.form-ctrl{flex:1;padding:2px 4px;display:flex;align-items:center;gap:4px;position:relative}

/* Khung gợi ý sản phẩm tự xây (thay cho datalist mặc định) — hỗ trợ bỏ dấu + tìm cả ghi chú */
.product-suggest-box{
  display:none;position:absolute;left:0;right:0;top:100%;z-index:950;
  background:#fff;border:1px solid #808080;box-shadow:2px 2px 6px rgba(0,0,0,.3);
  max-height:220px;overflow-y:auto;font-size:11px;
  -webkit-overflow-scrolling:touch;touch-action:pan-y;overscroll-behavior:contain;
}
.product-suggest-box.open{display:block}
.product-suggest-item{padding:4px 8px;cursor:pointer;border-bottom:1px solid #eee;display:flex;justify-content:space-between;gap:8px;align-items:center}
.product-suggest-item:hover{background:#b8e6c8}
.product-suggest-item .psi-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.product-suggest-item .psi-name b{color:#1b7a3e}
.product-suggest-item .psi-note{color:#888;font-size:10px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.product-suggest-item .psi-price{color:#c62828;font-weight:700;white-space:nowrap}
.product-suggest-empty{padding:6px 8px;color:#999;font-style:italic}
/* Panel "🔍 Rà soát thiếu dữ liệu" (Danh mục hàng hóa) — dạng "chip" gọn thay vì bảng 12 cột × 2
   hàng trước đây: bảng cũ dù đúng chức năng nhưng chiếm QUÁ NHIỀU chiều cao (thead + 2 hàng + chú
   thích dài), khiến diện tích còn lại cho bảng hàng hóa bên dưới bị bóp nhỏ hẳn đi trên PC (không
   chỉ riêng mobile). Chip tận dụng chiều RỘNG màn hình (thường dư giả hơn chiều cao) — 12 trường tự
   xuống dòng gọn trong 1-3 dòng thay vì cả một bảng cao. Phần chú thích dài chuyển vào <details> thu
   gọn sẵn, chỉ bung ra khi bấm xem, tiết kiệm thêm khoảng trống. Giữ NGUYÊN các id checkbox cũ
   (prodAud...Has/No) nên không cần sửa gì ở phần JS lọc (applyProductAuditFilters). */
.aud-chip-row{display:flex;flex-wrap:wrap;gap:6px}
.aud-chip{
  display:inline-flex;align-items:center;gap:6px;
  border:1px solid #cfe0cf;border-radius:4px;background:#f7faf7;
  padding:2px 8px;font-size:11px;white-space:nowrap;
}
.aud-chip b{color:#225522;font-weight:700}
.aud-chip label{display:inline-flex;align-items:center;gap:2px;cursor:pointer;color:#444}
.aud-chip input[type="checkbox"]{width:13px;height:13px;margin:0}
.form-ctrl input,.form-ctrl select,.form-ctrl textarea{
  flex:1;border:1px solid #c4c0b4;padding:3px 7px;height:26px;
  background:#fff;border-radius:var(--radius);font-size:12px;outline:none;
  transition:border-color .15s ease, box-shadow .15s ease;
}
.form-ctrl input:focus,.form-ctrl select:focus,.form-ctrl textarea:focus{background:#f8fcff;border-color:#5a9aa2;box-shadow:0 0 0 3px rgba(49,106,114,.12)}
.form-ctrl textarea{height:auto;resize:vertical}

/* ===== Ô "Ghi chú" hàng hoá — tự đổi màu ĐỎ NGHIÊNG ngay khi gõ phần trong dấu "..." =====
   HTML <textarea> gốc KHÔNG hỗ trợ tô màu 1 phần chữ (chỉ hiện 1 màu đồng nhất) — kỹ thuật ở đây là
   "lớp phủ" (hay dùng cho ô soạn code có tô màu cú pháp): 1 <div id="productNoteBackdrop"> nằm PHÍA
   SAU, dựng lại y hệt nội dung nhưng CÓ tô màu (qua formatNoteForDisplay() trong app.js); <textarea>
   thật nằm ĐÈ LÊN TRÊN nhưng chữ trong suốt (color:transparent) — người dùng vẫn gõ/xoá/bôi đen bình
   thường ở lớp trên (chỉ có con trỏ nhấp nháy còn thấy được, qua caret-color), còn MÀU CHỮ thật sự
   nhìn thấy là do lớp dưới hiện ra xuyên qua. 2 lớp dùng CHUNG 1 bộ font/cỡ chữ/khoảng đệm/viền để
   luôn khớp pixel-để-pixel — lệch bất kỳ thông số nào trong 2 lớp cũng làm chữ hiện sai vị trí.
   QUAN TRỌNG: đây CHỈ là hiệu ứng hiển thị — dữ liệu thật sự lưu xuống server vẫn 100% là chữ thường
   (nguyên văn có dấu ngoặc kép) y hệt như <textarea> thường, KHÔNG ảnh hưởng gì tới lưu trữ/tìm kiếm/
   in tem/hiển thị nơi khác — các chỗ đó đọc thẳng giá trị .value của textarea như trước giờ. */
.note-editor-wrap{position:relative;height:46px;width:100%;flex:1}
.form-ctrl .note-editor-backdrop,
.form-ctrl .note-editor-textarea{
  position:absolute!important;inset:0!important;margin:0!important;box-sizing:border-box!important;
  padding:2px 4px!important;font-size:12px;line-height:1.4;height:auto!important;
  font-family:"Be Vietnam Pro","Segoe UI","Malgun Gothic",Arial,sans-serif;
  white-space:pre-wrap;word-wrap:break-word;overflow-wrap:break-word;
  border:1px solid #c4c0b4!important;border-radius:var(--radius)!important;
}
.form-ctrl .note-editor-backdrop{
  background:#fff;color:#222;overflow:hidden;pointer-events:none;z-index:1;
}
.form-ctrl .note-editor-textarea{
  z-index:2;background:transparent!important;color:transparent!important;caret-color:#222;
  resize:none!important;overflow:auto;outline:none;flex:none!important;
}
.note-editor-wrap:focus-within .note-editor-backdrop{background:#f8fcff;border-color:#5a9aa2!important}
.note-editor-wrap:focus-within .note-editor-textarea{border-color:#5a9aa2!important}

/* Nút "📷 Quét" bằng camera cạnh các ô tìm/quét hàng hóa (Sản phẩm ở Nhập kho/Xuất-Bán, Tìm hàng hóa
   ở Danh mục) — CHỈ hiện trên MOBILE. Trên desktop nhân viên thường dùng máy quét mã vạch USB (tự gõ
   như bàn phím + Enter vào thẳng ô input) nên không cần thêm nút camera choán chỗ. Xem
   openBarcodeScanner()/closeBarcodeScanner() trong app.js — dùng thư viện html5-qrcode (CDN, xem
   index.html) hỗ trợ hầu hết mã vạch/QR thông dụng hiện nay. */
.barcode-scan-btn{display:none;flex-shrink:0;cursor:pointer}
.form-ctrl .barcode-scan-btn{
  height:26px;width:30px;padding:0;
  border:1px solid #c4c0b4;background:#fff;border-radius:var(--radius);
  font-size:12px;line-height:1;
  align-items:center;justify-content:center;
}
@media(max-width:820px){
  .barcode-scan-btn{display:inline-flex}
  .form-ctrl .barcode-scan-btn{height:32px;width:38px;font-size:15px}
}

/* ── Dialog quét mã vạch FULL MÀN HÌNH ────────────────────────────────────────────────────────
   Camera chiếm TRỌN màn hình (không còn hộp thoại nhỏ như trước) — dễ căn mã vạch hơn hẳn trên
   điện thoại, giống cảm giác các app quét mã vạch chuyên dụng. */
.bc-fullscreen-dialog{
  border:none;padding:0;margin:0;width:100vw;height:100vh;max-width:none;max-height:none;
  background:#000;inset:0;
}
.bc-fullscreen-dialog::backdrop{background:#000}
.bc-viewport{position:absolute;inset:0;width:100%;height:100%;background:#000;overflow:hidden}
.bc-viewport video{width:100% !important;height:100% !important;object-fit:cover !important}
/* QUAN TRỌNG: KHÔNG giới hạn vùng quét (đã bỏ "qrbox" ở app.js — quét TOÀN BỘ khung hình), nên
   thư viện KHÔNG còn vẽ khung mờ/viền nào lên video nữa — trước đây CỐ TÌNH không tự vẽ thêm khung
   trang trí nào đè lên video, để tránh lặp lại 2 lỗi đã gặp:
     (1) Vạch trang trí tự chạy animation KHÔNG khớp vùng quét thật → người dùng đưa mã vạch theo
         vạch trang trí, sai vị trí quét thật, không bao giờ quét được dù camera rõ nét.
     (2) Đổi màu border của khung "qr-shaded-region" (kỹ thuật vẽ khung mờ của thư viện dùng
         border RẤT DÀY để tạo hiệu ứng che mờ xung quanh) → vô tình biến cả MẢNG LỚN thành màu đỏ
         đặc kín gần hết màn hình, che mất luôn hình ảnh camera thật, rất khó dùng.
   .bc-guide-box (thêm sau) KHÁC HẲN 2 lỗi trên: đây KHÔNG PHẢI vùng giới hạn quét giả (detector vẫn
   quét toàn khung hình, đặt mã vạch ngoài khung này vẫn đọc được bình thường) — mà là chỉ dấu THẬT,
   TRÙNG ĐÚNG vùng camera đang ưu tiên lấy nét/đo sáng (xem applyFocusRegion() ở app.js), giúp người
   dùng biết nên đưa mã vạch vào đâu để camera nét NHANH nhất. Cố tình vẽ MỎNG/TRONG SUỐT (chỉ viền +
   4 góc, không tô nền/không border dày) để không lặp lại lỗi (2), và không chạy animation lệch pha
   để không lặp lại lỗi (1). */
.bc-guide-box{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:min(78vw,520px); height:min(38vw,220px); max-height:34vh;
  border:2px solid rgba(255,255,255,.85); border-radius:14px;
  pointer-events:none; z-index:4;
}
.bc-guide-box::before,.bc-guide-box::after{
  content:""; position:absolute; width:22px; height:22px; border:3px solid #fff;
}
.bc-guide-box::before{ top:-3px; left:-3px; border-right:none; border-bottom:none; border-top-left-radius:10px; }
.bc-guide-box::after{ bottom:-3px; right:-3px; border-left:none; border-top:none; border-bottom-right-radius:10px; }
.bc-close-btn{
  position:absolute;top:calc(env(safe-area-inset-top,0px) + 14px);right:14px;z-index:5;
  width:38px;height:38px;border-radius:50%;border:none;background:rgba(0,0,0,.5);
  color:#fff;font-size:18px;cursor:pointer;
}
.bc-status{
  position:absolute;left:0;right:0;bottom:calc(env(safe-area-inset-bottom,0px) + 24px);z-index:5;
  text-align:center;color:#fff;font-size:13px;font-weight:600;
  text-shadow:0 1px 3px rgba(0,0,0,.7);padding:0 20px;
}

/* ── Chọn vùng sản phẩm bằng cách chạm nối điểm (Polygon Lasso) — full màn hình, tối ưu di động ── */
/* QUAN TRỌNG: dùng flexbox CỘT (không dùng position:absolute chồng lên nhau như .bc-fullscreen-dialog
   gốc) — để phần ảnh CHỈ chiếm đúng khoảng trống còn lại giữa thanh hướng dẫn (trên) và thanh nút
   thao tác (dưới), không bị 2 thanh đó ĐÈ CHỒNG lên ảnh (trước đây cả 3 phần cùng position:absolute
   inset:0 nên ảnh phóng to tràn ra sau lưng 2 thanh, mất chỗ để chạm điểm gần mép trên/dưới). */
#polyCropDialog[open]{display:flex;flex-direction:column}
.poly-crop-head{
  position:static;flex:0 0 auto;
  padding:calc(env(safe-area-inset-top,0px) + 10px) 12px 8px 12px;
  background:rgba(0,0,0,.75);color:#fff;font-size:12px;line-height:1.4;
  display:flex;align-items:center;gap:10px;
}
.poly-crop-head span{flex:1 1 auto}
.poly-crop-head .bc-close-btn{flex:0 0 auto;position:static!important}
.poly-crop-canvas-wrap{
  position:static;flex:1 1 auto;min-height:0;
  display:flex;align-items:center;justify-content:center;
  background:#1a1a1a;overflow:auto; /* auto (không phải hidden) — cho phép CUỘN để xem hết ảnh khi phóng to hơn khung vừa khít */
}
#polyCropCanvas{touch-action:none;-webkit-user-select:none;user-select:none;max-width:100%;max-height:100%}
.poly-crop-toolbar{
  position:static;flex:0 0 auto;
  padding:8px 10px calc(env(safe-area-inset-bottom,0px) + 10px);
  background:rgba(0,0,0,.75);display:flex;gap:8px;justify-content:center;
}
.poly-crop-toolbar .pos-btn{font-size:13px;padding:8px 14px;font-weight:700}

.form-section-title{
  background:#4a7a3f;color:#fff;font-size:11px;font-weight:700;
  padding:3px 8px;margin-bottom:0;
}
.form-actions{padding:6px;display:flex;gap:4px;justify-content:flex-end;background:#e8e8e8;border-top:1px solid var(--line2);border-radius:0 0 11px 11px}

/* ===== KPI DASHBOARD ===== */
.kpi-grid{display:flex;gap:6px;padding:6px;flex-wrap:wrap;flex-shrink:0}
.kpi{
  background:#fff;
  border:2px solid;border-color:#808080 #fff #fff #808080;
  padding:6px 10px;min-width:130px;
}
.kpi span{display:block;color:#225522;font-size:11px;font-weight:700}
.kpi strong{display:block;font-size:18px;font-weight:700;color:#000;margin:2px 0}
.kpi em{font-style:normal;color:#888;font-size:10px}
.kpi.warn{background:#fff8e0;border-color:#cc8800 #ffe0a0 #ffe0a0 #cc8800}
.dashboard-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:0 4px 4px;flex:1;overflow:hidden}
.dash-panel{
  background:#fff;
  border:2px solid;border-color:#808080 #fff #fff #808080;
  display:flex;flex-direction:column;overflow:hidden;
}
.dash-panel-head{
  background:#4a7a3f;color:#fff;
  font-size:12px;font-weight:700;
  padding:3px 8px;display:flex;align-items:center;justify-content:space-between;
  flex-shrink:0;
}
.dash-body{overflow:auto;flex:1;padding:4px}
.bar-chart{display:flex;align-items:flex-end;gap:6px;min-height:200px;padding:8px 4px 0;border-bottom:1px solid #ddd}
.bar{flex:1;display:grid;align-items:end;gap:4px;text-align:center;color:#555;font-size:10px;min-width:30px}
.bar-fill{border-radius:2px 2px 0 0;background:linear-gradient(180deg,#4a7a3f,#88cc88);min-height:4px}
.mini-item{
  display:flex;align-items:center;justify-content:space-between;
  border-bottom:1px solid #eee;padding:4px 2px;gap:8px;
}
.mini-item strong{font-size:12px}
.mini-item span{color:#888;font-size:11px}

/* ===== LABEL / PRINT ===== */
/* ===== TEM / IN TEM ===== */

/* Khung bao ngoài chứa NHIỀU trang .tem-sheet (mỗi trang 21 tem) — xem renderLabels() trong app.js.
   Trên MÀN HÌNH: xếp dọc, có khoảng cách giữa các trang cho dễ phân biệt lúc xem trước.
   Lúc IN: mỗi .tem-sheet tự ngắt sang trang A4 riêng (xem @media print bên dưới). */
.label-sheet-pages{display:flex;flex-direction:column;gap:16px}
.label-sheet-pages .tem-sheet{box-shadow:0 1px 4px rgba(0,0,0,.15)}
/* Thanh nhỏ trên đầu mỗi trang tem (chỉ hiện trên màn hình, ẩn khi in nhờ .no-print) — cho phép
   in RIÊNG từng trang thay vì luôn phải in cả hàng chờ. Xem printLabelPage() trong app.js. */
.tem-page-bar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:4px 8px;background:#e8e4da;border:1px solid #bbb;border-radius:3px;font-size:11px;font-weight:700;color:#555}
.tem-page-bar .pos-btn.small{font-size:10.5px;padding:3px 8px}

/* Sheet: 3 cột × 7 hàng = 21 tem/trang A4 — khung xem trước giờ ĐÚNG TỈ LỆ khổ A4 thật (210:297),
   thu nhỏ lại như xem trước 1 trang giấy thật (giống Word/Google Docs), thay vì kéo giãn hết cỡ
   ngang màn hình như trước — max-width:100% để vẫn co lại vừa trên màn hình hẹp/mobile. */
.tem-sheet{
  background:#fff;
  padding:6px;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:1fr;
  column-gap:4px;
  row-gap:0;
  width:210mm;
  max-width:100%;
  aspect-ratio:210/297;
  margin:0 auto;
  box-sizing:border-box;
}

.tem{
  border:1px dashed #aaa;
  padding:4px 5px 4px;
  display:flex;
  flex-direction:column;
  gap:0;
  overflow:hidden;
  box-sizing:border-box;
  background:#fff;
}
.tem-empty{background:#f5f5f5;border-style:dotted}

/* ── Tem V3330 (프린텍/printec.co.kr) — khung xem trước ĐÚNG TỈ LỆ khổ A4 thật (210:297), thu nhỏ
   lại như xem trước 1 trang giấy thật thay vì kéo giãn hết cỡ ngang màn hình. Vì cả khung đã đúng
   tỉ lệ A4 + grid 3×7 đều nhau, từng tem con tự nhiên ra đúng gần tỉ lệ tem thật (63.5:38.1) luôn,
   không cần ép aspect-ratio riêng cho từng tem nữa. ── */
.v3330-sheet-pages{display:flex;flex-direction:column;gap:16px}
.v3330-sheet-pages .v3330-sheet{box-shadow:0 1px 4px rgba(0,0,0,.15)}
.v3330-sheet{
  background:#fff;
  padding:6px;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:1fr;
  column-gap:4px;
  row-gap:0;
  width:210mm;
  max-width:100%;
  aspect-ratio:210/297;
  margin:0 auto;
  box-sizing:border-box;
}
.v3330-tem{
  border:1px dashed #aaa;
  padding:4px 6px;
  display:flex;
  flex-direction:column;
  overflow:hidden;
  box-sizing:border-box;
  background:#fff;
}
.v3330-tem-empty{background:#f5f5f5;border-style:dotted}
.v3330-tem-name{font-weight:700;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center;display:block;margin:0 2mm 3px 2mm}
.v3330-tem-body{flex:1;min-height:0;width:100%;display:flex;flex-direction:row;gap:4px}
.v3330-tem-img-col{width:38%;flex-shrink:0;overflow:hidden;display:flex;align-items:stretch;background:transparent}
.v3330-tem-img{width:100%;height:100%;object-fit:cover;object-position:center;display:block;border-radius:3px}
.v3330-tem-right{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:space-between;gap:1px}
.v3330-tem-price{font-weight:700;font-size:18px;color:#c8181e;text-align:right}
.v3330-tem-meta-row{display:flex;flex-direction:row;justify-content:space-between;align-items:center}
.v3330-tem-loc{font-size:10px;color:#444;font-weight:600}
.v3330-tem-id{font-size:10px;color:#444;font-weight:600}
.v3330-tem-bc-wrap{display:flex;flex-direction:column;align-items:center}
.v3330-barcode-text{font-size:10px;color:#555}
.v3330-tem-shop{background:#4a7a3f;color:#fff;text-align:center;font-size:9px;padding:1px 2px;flex-shrink:0;margin-top:2px}

/* ── Nhãn V3330 — CÙNG khổ giấy/tỉ lệ tem thật với Tem V3330 ở trên (chỉ copy nguyên khối CSS đã
   kiểm chứng chạy đúng), nhưng nội dung mỗi ô chỉ có 3 DÒNG CHỮ đơn giản, căn giữa, tự co (scaleX)
   riêng từng dòng để không bao giờ tràn — không có ảnh/mã vạch dạng vạch kẻ. ── */
.v3330n-sheet-pages{display:flex;flex-direction:column;gap:16px}
.v3330n-sheet-pages .v3330n-sheet{box-shadow:0 1px 4px rgba(0,0,0,.15)}
.v3330n-sheet{
  background:#fff;
  padding:6px;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:1fr;
  column-gap:4px;
  row-gap:0;
  width:210mm;
  max-width:100%;
  aspect-ratio:210/297;
  margin:0 auto;
  box-sizing:border-box;
}
.v3330n-tem{
  border:1px dashed #aaa;
  padding:4px 6px;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:3px;
  overflow:hidden;
  box-sizing:border-box;
  background:#fff;
}
.v3330n-tem-empty{background:#f5f5f5;border-style:dotted}
.v3330n-line{white-space:nowrap;overflow:visible;text-align:center;transform-origin:center center;display:block;max-width:100%}
.v3330n-line-name{font-weight:700;font-size:14px;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 12px);margin:0 auto}
.v3330n-bc-wrap{display:flex;flex-direction:column;align-items:center;gap:1px}
.v3330n-line-barcode{font-size:12px;color:#555;font-family:monospace}
.v3330n-line-price{font-weight:800;font-size:18px;color:#c8181e}
.v3330n-line-web{font-weight:600;font-size:11px;color:#4a7a3f}

/* NHÃN V3410 — NHÂN BẢN Y HỆT khối ".v3330n-*" ở trên, chỉ đổi 3 cột → 4 cột (khớp đúng 47×26,9mm,
   4×10=40 ô/trang thay vì 63.5×38.1mm, 3×7=21 ô/trang của V3330). */
.v3410-sheet-pages{display:flex;flex-direction:column;gap:16px}
.v3410-sheet-pages .v3410-sheet{box-shadow:0 1px 4px rgba(0,0,0,.15)}
.v3410-sheet{
  background:#fff;
  padding:6px;
  display:grid;
  grid-template-columns:repeat(4,1fr);
  grid-auto-rows:1fr;
  column-gap:4px;
  row-gap:0;
  width:210mm;
  max-width:100%;
  aspect-ratio:210/297;
  margin:0 auto;
  box-sizing:border-box;
}
.v3410-tem{
  border:1px dashed #aaa;
  padding:3px 4px;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:2px;
  overflow:hidden;
  box-sizing:border-box;
  background:#fff;
}
.v3410-tem-empty{background:#f5f5f5;border-style:dotted}
.v3410-line{white-space:nowrap;overflow:visible;text-align:center;transform-origin:center center;display:block;max-width:100%}
.v3410-line-name{font-weight:700;font-size:11px;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 10px);margin:0 auto}
.v3410-bc-wrap{display:flex;flex-direction:column;align-items:center;gap:1px}
.v3410-line-barcode{font-size:14px;color:#555;font-family:monospace;width:75%;display:block;margin:0 auto;text-align:justify;text-align-last:justify;text-justify:inter-character}
.v3410-line-price{font-weight:800;font-size:18px;color:#c8181e}
.v3410-line-web{font-weight:600;font-size:9px;color:#4a7a3f}

/* ── Dòng 1: Tên SP — căn giữa, 1 dòng, auto font ── */
.tem-name{
  font-weight:700;
  font-size:12px; /* CỠ CHỮ CỐ ĐỊNH — không tự co nhỏ nữa dù tên dài cỡ nào */
  line-height:1.25;
  white-space:nowrap;
  overflow:hidden; /* thừa thì CẮT BỎ, không tràn ra ngoài */
  text-overflow:ellipsis; /* hiện "..." ở chỗ bị cắt */
  text-align:center;
  flex-shrink:0;
  margin:0 2mm 3px 2mm; /* cách lề trái/phải đúng 2mm */
  box-sizing:border-box;
  display:block;
}

/* ── Body: ảnh trái | dữ liệu phải ── */
.tem-body{
  flex:1;
  min-height:0;
  display:flex;
  flex-direction:row;
  gap:4px;
}

/* Ảnh trái: chiếm 40% chiều ngang, tràn kín chiều cao body */
.tem-img-col{
  width:40%;
  flex-shrink:0;
  overflow:hidden;
  display:flex;
  align-items:stretch;
  background:transparent; /* trong suốt khi không có ảnh */
}
.tem-product-img{
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  display:block;
}

/* Dữ liệu phải */
.tem-right{
  flex:1;
  min-width:0;
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  gap:1px;
}
.tem-price{
  font-weight:700;
  font-size:17px;
  color:#c8181e;
  line-height:1.15;
  flex-shrink:0;
  text-align:right;
}
.tem-meta-row{
  display:flex;
  flex-direction:row;
  justify-content:space-between;
  align-items:center;
  flex-shrink:0;
}
.tem-loc{font-size:9px;color:#444;font-weight:600;line-height:1.3}
.tem-id{font-size:9px;color:#444;font-weight:600;line-height:1.3}
.tem-bc-wrap{
  flex:1;
  min-height:0;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
}

/* ── Footer: tên shop ── */
.tem-shop{
  background:#4a7a3f;
  color:#fff;
  text-align:center;
  font-size:8px;
  padding:1px 2px;
  flex-shrink:0;
  margin-top:2px;
}

/* ── Barcode SVG ── */
.barcode{height:18px;display:flex;gap:1px;align-items:stretch;margin:0 0 1px}
svg.barcode{width:100%;height:20px;display:block;fill:#111}
.barcode span{display:block;background:#111;min-width:1px}
.barcode-text{text-align:center;font-size:8px;letter-spacing:.04em;color:#111}

/* ===== MISC ===== */
.empty{color:#888;background:#f8f8f0;border:1px dashed #ccc;padding:12px;text-align:center;font-size:12px}
.hidden{display:none!important}
.report-list{display:grid;gap:0}
.report-row{display:flex;justify-content:space-between;padding:5px 8px;border-bottom:1px solid #eee}
.report-row strong{font-variant-numeric:tabular-nums;font-weight:700}
.backup-actions{display:grid;gap:8px;padding:8px}
.rcpt-tpl-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px 10px}

/* Danh sách "Loại hoá đơn" (như Template List của OKPOS) — xem renderReceiptTemplateTypeList() */
.rcpt-type-panel{background:var(--panel);border:1px solid var(--line2);border-radius:8px;padding:8px;margin-bottom:12px}
.rcpt-type-panel-head{display:flex;align-items:center;justify-content:space-between;font-size:11.5px;font-weight:800;color:var(--primary-dark);margin-bottom:6px}
.rcpt-type-list{display:flex;flex-direction:column;gap:3px;max-height:180px;overflow-y:auto}
.rcpt-type-row{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border:1.5px solid var(--line2);border-radius:7px;background:#fff;cursor:pointer;font-size:12px}
.rcpt-type-row:hover{background:#b8e6c8}
.rcpt-type-row.selected{border-color:var(--primary);background:#eaf7ee;font-weight:700}
.rcpt-type-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rcpt-type-badge{font-size:10px;font-weight:700;color:#1a6b3a}
.rcpt-type-actions{display:flex;gap:2px;flex-shrink:0}
.rcpt-type-actions button{border:none;background:transparent;cursor:pointer;font-size:12px;padding:2px 4px;border-radius:5px}
.rcpt-type-actions button:hover{background:rgba(0,0,0,.08)}

/* ===== Chế độ NÂNG CAO của "🖨️ Mẫu in hoá đơn" — 3 cột kiểu NICE POS (Danh sách thẻ / Soạn nội
   dung / Xem trước) — xem toggleReceiptDesignMode(), insertReceiptTag(), renderReceiptPreview()
   trong app.js. Toàn bộ chỉ là bản THIẾT KẾ (soạn text + xem trước bằng dữ liệu mẫu) — không đụng gì
   tới việc IN THẬT (nằm ở pos.html, đọc mẫu ĐANG DÙNG trong state.settings.receiptTemplates qua
   activeReceiptTemplateId — xem getPosReceiptTemplate() trong pos.html). */
.rcpt-designer{display:grid;grid-template-columns:200px 1fr 220px;gap:10px;align-items:start}
.rcpt-designer-col{background:var(--panel);border:1px solid var(--line2);border-radius:8px;padding:8px;min-width:0}
.rcpt-designer-head{font-size:11px;font-weight:800;color:var(--primary-dark);margin-bottom:6px}
.rcpt-tag-list{display:flex;flex-direction:column;gap:3px;max-height:360px;overflow-y:auto}
/* Bảng kết quả "Phân tích phiếu nhập" — tô màu riêng theo CẶP cột để dễ phân biệt nhóm GIÁ NHẬP
   (Giá nhập cũ + Đơn giá mới) với nhóm GIÁ BÁN (Giá bán cũ + Giá bán mới), tránh nhìn nhầm 4 cột
   giá tiền liền nhau. Áp cho cả <th> (tiêu đề) lẫn <td> (từng dòng dữ liệu). */
/* Tiêu đề cột tô màu ĐẬM + chữ trắng (dễ đọc, nổi bật) để phân nhóm — Ô DỮ LIỆU từng dòng KHÔNG tô
   nền nữa (trước đây tô nền nhạt cho cả ô dữ liệu làm khó đọc số/chữ bên trong, nhất là khi đan xen
   màu vằn của bảng) — chỉ giữ 1 viền trái mảnh màu tương ứng để vẫn nhận ra được đây là cột nhóm nào
   mà không ảnh hưởng độ rõ của nội dung. */
th.invscan-col-nhap{background:#4a90d9;color:#fff}
th.invscan-col-ban{background:#e8973f;color:#fff}
td.invscan-col-nhap{border-left:3px solid #4a90d9}
td.invscan-col-ban{border-left:3px solid #e8973f}

/* Hàng "🔗 SP liên quan" trong bảng "Phân tích phiếu nhập" — nền nhạt hơn hàng chính, không có viền
   dưới đậm giữa các hàng con với nhau (liền mạch thành 1 khối), phân biệt rõ với hàng chính phía trên. */
.invscan-related-row td, .invscan-related-header td{background:#fafcfa!important;border-bottom:1px solid #e0ece0}
.invscan-related-row:last-of-type td{border-bottom:2px solid #ccc}

/* Nút "+" gọn nhẹ ở cuối mỗi dòng bảng "Phân tích phiếu nhập" — bấm ra menu nhỏ 2 lựa chọn (thêm SP
   mới / thêm vào ghi chú làm từ khoá). Xem renderInvoiceScanActionMenu() trong app.js. */
.invscan-action{position:relative;display:inline-block}
.invscan-action-btn{
  padding:2px 9px!important;font-size:14px!important;font-weight:800;line-height:1.2;
}
.invscan-action-menu{
  display:none;position:fixed;z-index:960;
  min-width:190px;background:#fff;border:1px solid #808080;border-radius:4px;
  box-shadow:2px 2px 6px rgba(0,0,0,.3);padding:3px;flex-direction:column;gap:2px;
}
.invscan-action-menu.open{display:flex}
.invscan-action-menu button{
  text-align:left;border:none;background:#fff;border-radius:3px;
  padding:6px 8px;font-size:11px;cursor:pointer;white-space:nowrap;
}
.invscan-action-menu button:hover:not(:disabled){background:#e6f2e3}
.invscan-action-menu button:disabled{color:#aaa;cursor:not-allowed;background:#f5f5f5}

.rcpt-tag-btn{
  display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  text-align:left;border:1px solid var(--line2);background:#fff;border-radius:5px;
  padding:4px 7px;cursor:pointer;font-family:monospace;font-size:11px;font-weight:700;color:var(--primary-dark);
}
.rcpt-tag-btn:hover{background:#e6f2e3;border-color:var(--primary)}
.rcpt-tag-btn span{font-family:inherit;font-weight:400;font-size:9.5px;color:var(--muted)}
.rcpt-edit-textarea{
  width:100%;min-height:360px;resize:vertical;
  font-family:monospace;font-size:12.5px;line-height:1.5;
  border:1px solid var(--line2);border-radius:6px;padding:8px;box-sizing:border-box;
}
.rcpt-preview-col{display:flex;flex-direction:column}
.rcpt-preview-paper{
  background:#fff;border:1px solid var(--line2);border-radius:4px;
  padding:10px 8px;max-height:360px;overflow-y:auto;
  box-shadow:0 2px 6px rgba(0,0,0,.1);
}
.rcpt-preview-paper #rcptPreview{
  font-family:monospace;font-size:11px;line-height:1.5;color:#111;
  white-space:pre-wrap;word-break:break-word;
}
@media(max-width:820px){
  .rcpt-designer{grid-template-columns:1fr}
  .rcpt-tag-list{max-height:160px}
}

/* Khối "Sửa chữ nhãn có sẵn" + "Thẻ tự đặt riêng" — nằm dưới khung 3 cột, chỉ hiện ở chế độ nâng cao */
.rcpt-custom-block{margin-top:14px;padding-top:12px;border-top:1px dashed var(--line2)}
.rcpt-label-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px 10px}
.rcpt-label-grid label{display:flex;flex-direction:column;gap:2px;font-size:11px;color:var(--muted);font-weight:600}
.rcpt-label-grid input{padding:5px 7px;border:1px solid var(--line2);border-radius:5px;font-size:12px}
.rcpt-custom-tag-rows{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.rcpt-custom-tag-row{display:grid;grid-template-columns:auto 1fr 1fr auto;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--line2);border-radius:6px;padding:6px 8px}
.rcpt-custom-tag-row .rcpt-tag-preview-key{font-family:monospace;font-weight:700;font-size:11px;color:var(--primary-dark);white-space:nowrap}
.rcpt-custom-tag-row input{padding:5px 7px;border:1px solid var(--line2);border-radius:5px;font-size:12px;min-width:0}
@media(max-width:820px){
  .rcpt-label-grid{grid-template-columns:1fr 1fr}
  .rcpt-custom-tag-row{grid-template-columns:1fr}
}
.chk-row{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--text);cursor:pointer;padding:3px 0}
.chk-row input[type="checkbox"]{width:15px;height:15px;cursor:pointer;flex-shrink:0}
/* Danh sách "sổ ra" (accordion) ở Cài đặt — mỗi mục chỉ hiện tiêu đề, bấm vào mới xổ nội dung ra,
   tránh tình trạng TẤT CẢ mục hiện cùng lúc chồng chéo lên nhau như bố cục lưới 2 cột cũ. */
.acc-list{display:flex;flex-direction:column;gap:6px;max-width:760px;margin:0 auto;padding:4px}
/* Tiêu đề nhóm trong trang "Cài đặt" (VD "🖥️ Cài đặt hệ thống" / "🧾 Cài đặt POS") — chỉ để phân
   tách trực quan, không bấm được, khớp với cách nhóm 2 mục tương ứng trong dropdown "⚙️ Cài đặt ▾"
   trên thanh tab (xem index.html + openSettingsSection() trong app.js). */
.acc-group-title{
  font-size:12px;font-weight:800;color:var(--primary-dark);text-transform:uppercase;letter-spacing:.05em;
  padding:14px 4px 2px;
  border-bottom:2px solid var(--primary);
  margin-bottom:2px;
}
.acc-group-title:first-child{padding-top:4px}
.acc-item{background:var(--panel);border:1px solid var(--line2);border-radius:8px;overflow:hidden}
.acc-header{
  width:100%;text-align:left;background:var(--panel2,#f7f8fa);border:none;cursor:pointer;
  padding:12px 14px;font-size:13.5px;font-weight:700;color:var(--text);
  display:flex;align-items:center;gap:8px;
}
.acc-header:hover{background:var(--line2)}
.acc-arrow{display:inline-block;font-size:10px;transition:transform .15s ease;color:var(--muted)}
.acc-item.open .acc-arrow{transform:rotate(90deg)}
.acc-body{max-height:0;overflow:hidden;transition:max-height .25s ease;padding:0 14px}
.acc-item.open .acc-body{max-height:3000px;padding:12px 14px 16px}
.file-btn{
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--primary);padding:4px 10px;
  font-weight:700;color:var(--primary);background:#e8f5e8;cursor:pointer;
}
.file-btn input{display:none}
.muted{color:#888;line-height:1.5;font-size:11px;padding:8px}
.warning-box{border:1px solid #cc8800;background:#fff8cc;color:#664400;padding:6px;font-weight:700;font-size:11px}

/* ===== DIALOG ===== */
dialog{
  border:1px solid #c4c0b4;
  border-radius:12px;padding:0;
  box-shadow:0 12px 32px rgba(0,0,0,.22);
  width:min(860px,calc(100vw - 20px));
}
dialog::backdrop{background:rgba(0,0,0,.35)}
.dialog-card{padding:0;background:#ece9d8}
.dialog-head{
  background:linear-gradient(180deg,#316a72,#1a4a52);
  color:#fff;font-size:13px;font-weight:700;
  padding:5px 10px;
  display:flex;justify-content:space-between;align-items:center;
  border-radius:11px 11px 0 0;
}
.dialog-head h2{margin:0;font-size:13px;color:#fff}
.icon-btn{border:1px solid #c4c0b4;background:#eee;width:24px;height:24px;font-size:16px;line-height:1;padding:0;border-radius:6px;cursor:pointer;transition:background .15s ease}
.icon-btn:hover{background:#ddd}
.dialog-body{padding:8px;display:grid;grid-template-columns:1fr 200px;gap:8px}
.dialog-actions{display:flex;justify-content:flex-end;gap:6px;padding:6px 8px;border-top:1px solid var(--line2);background:#e0e0d4;border-radius:0 0 11px 11px}
.dialog-form-grid{display:flex;flex-direction:column;gap:0}
.product-image-box{
  border:2px inset #808080;background:#e8e8e8;padding:0;
  display:flex;flex-direction:column;
}
.image-preview-wrap{flex:1;display:flex;align-items:center;justify-content:center;min-height:120px;background:#c8c8c8}
.product-image-preview{max-width:100%;max-height:120px;object-fit:contain}
.img-upload-note{font-size:10px;color:#666;padding:4px;text-align:center;border-top:1px solid #ccc}
.form{display:flex;flex-direction:column;gap:0}
.form label{display:flex;align-items:center;border-bottom:1px solid #ddd;min-height:26px}
.form label > span, .form label > :first-child:not(input):not(select):not(textarea){
  min-width:110px;flex-shrink:0;
  background:#e8f0e8;color:#225522;font-weight:700;font-size:11px;
  padding:2px 6px;border-right:1px solid #ccc;align-self:stretch;
  display:flex;align-items:center;
}
.form label input,.form label select,.form label textarea{
  flex:1;border:none;border-bottom:none;padding:2px 4px;
  background:transparent;height:22px;font-size:12px;outline:none;
}
.form label input:focus,.form label select:focus{background:#f0f8ff}
.form .span-2{grid-column:auto}
.form textarea{height:auto;resize:vertical}
.qty-input{width:70px}

/* ===== STATUS BAR ===== */
.statusbar{
  background:#c0c0c0;
  border-top:1px solid #808080;
  padding:2px 8px;
  font-size:11px;color:#333;
  display:flex;align-items:center;gap:12px;
  flex-shrink:0;
}
.statusbar span{display:flex;align-items:center;gap:4px}

/* ===== SCROLLBARS ===== */
::-webkit-scrollbar{width:12px;height:12px}
::-webkit-scrollbar-track{background:#d4d0c8}
::-webkit-scrollbar-thumb{background:#a8a8a0;border-radius:6px}

/* ===== PRINT ===== */
/* ── ĐƠN HÀNG: badge trạng thái + tab lọc ── */
.order-status-badge{
  display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;
  white-space:nowrap;
}
.order-status-badge.st-pending{background:#fff3cc;color:#8a5a00}
.order-status-badge.st-waiting{background:#d6e8ff;color:#0b4fa0}
.order-status-badge.st-delivered{background:#e0e0e0;color:#1a1a1a}
.order-status-badge.st-cancelled{background:#ffd6d6;color:#a10000}

/* Chấm màu bằng CSS thuần — tránh lỗi font không hiện được emoji tròn màu trên 1 số máy Windows */
.st-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px;vertical-align:middle;flex-shrink:0}
.dot-pending{background:#c77700}
.dot-waiting{background:#1f7ae0}
.dot-delivered{background:#333}
.dot-cancelled{background:#d32f2f}

/* ── Huy hiệu đếm số đơn hàng chờ xác nhận trên tab ── */
.nav-badge{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:16px;height:16px;padding:0 4px;margin-left:5px;
  background:#e02020;color:#fff;border-radius:9px;font-size:10px;font-weight:800;
  vertical-align:middle;line-height:1;
  animation:navBadgePulse 1.4s infinite;
}
@keyframes navBadgePulse{
  0%,100%{box-shadow:0 0 0 0 rgba(224,32,32,.55)}
  50%{box-shadow:0 0 0 4px rgba(224,32,32,0)}
}

.order-status-tabs{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.order-status-tab{
  display:inline-flex;align-items:center;
  padding:7px 14px;border-radius:16px;font-size:12px;font-weight:700;cursor:pointer;
  white-space:nowrap;user-select:none;
  border:1.5px solid transparent;
  background:#eeece3;color:#444;
  transition:transform .1s,box-shadow .12s,filter .12s;
}
.order-status-tab:hover{filter:brightness(0.96);transform:translateY(-1px)}
.order-status-tab:active{transform:translateY(0)}

/* Màu riêng cho từng trạng thái — nhạt khi chưa chọn, đậm rực khi đang chọn */
.order-status-tab[data-status=""]{background:#e4e2d8;color:#333;border-color:#c9c6b8}
.order-status-tab[data-status=""].active{background:#3a3a3a;color:#fff;border-color:#222}

.order-status-tab[data-status="pending"]{background:#fff2cc;color:#8a5a00;border-color:#f0d080}
.order-status-tab[data-status="pending"].active{background:#e6a100;color:#fff;border-color:#a06e00}

.order-status-tab[data-status="waiting"]{background:#dbeaff;color:#0b4fa0;border-color:#a9cdf5}
.order-status-tab[data-status="waiting"].active{background:#1f7ae0;color:#fff;border-color:#0b4fa0}

.order-status-tab[data-status="delivered"]{background:#e6e6e6;color:#333;border-color:#c4c4c4}
.order-status-tab[data-status="delivered"].active{background:#333;color:#fff;border-color:#111}

.order-status-tab[data-status="cancelled"]{background:#ffdddd;color:#a10000;border-color:#f3aaaa}
.order-status-tab[data-status="cancelled"].active{background:#d32f2f;color:#fff;border-color:#8f0000}

.order-status-tab.active{box-shadow:0 2px 5px rgba(0,0,0,.25);border-width:1.5px}
.order-status-tab.active .st-dot{background:#fff!important;box-shadow:0 0 0 1px rgba(0,0,0,.15)}

@media print{
  @page{
    size:A4 portrait;
    margin:5mm;
  }
  /* CHÚ Ý — riêng khi in "📐 Tem V3330": bắt buộc phải đổi "Margins" trong hộp thoại in của Chrome
     sang "None" (thay vì "Default") TRƯỚC khi bấm In — xem 4 bước trong hướng dẫn đã gửi. @page ở
     trên vẫn còn khai lề 5mm (dùng chung, KHÔNG đổi để khỏi ảnh hưởng "🏷️ Tem kệ"/in đơn hàng) —
     đã thử tách riêng bằng "trang có tên" (named page) nhưng bị lỗi tạo thêm trang trắng thừa (Chrome
     chưa hỗ trợ tốt), nên bỏ cách đó — quay lại cách đơn giản: người dùng tự chọn Margins:"None"
     trong hộp thoại in, CSS bên dưới tính lề đúng cho trường hợp lề trang = 0. */
  *{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  body{background:#fff;overflow:visible;margin:0;padding:0}
  .tab-bar,.topbar,.statusbar,.no-print,.mobile-nav-toggle,.view:not(#labels):not(#orderPrint){display:none!important}
  dialog{display:none!important}
  .app-shell,.app{display:block!important;height:auto;overflow:visible}
  #labels{
    display:block!important;
    height:auto;
    overflow:visible;
    padding:0;margin:0;
  }
  #orderPrint{
    display:block!important;
    height:auto;
    overflow:visible;
    padding:0;margin:0;
  }
  .order-print-sheet{
    width:100%;
    padding:0;
    color:#000;
  }
  /* Sheet: 3 cột × 6 hàng trên A4 297mm - 10mm margin = 287mm cao
     Mỗi tem: (287mm - 5×2mm gap) / 6 = (287-10)/6 = 46.17mm → dùng 46mm
     Rộng: (210mm - 10mm margin - 2×2mm gap) / 3 = (198-4)/3 = 64.67mm → dùng 64mm */
  #labelSheet{
    display:block!important;
    margin:0;padding:0;
    width:100%;
  }
  .label-sheet-pages{display:block!important;gap:0!important} /* huỷ flex+gap của màn hình lúc in — mỗi trang tự ngắt bằng break-after:page ở dưới, không cần khoảng cách */
  /* Mỗi trang .tem-sheet (21 tem) tự ngắt sang 1 trang A4 RIÊNG — trước đây style này gắn thẳng vào
     #labelSheet (số ít, chỉ 1 trang cố định); giờ có thể có NHIỀU trang .tem-sheet nên đổi sang
     class, áp dụng đều cho mọi trang. break-after:page ngắt trang sau MỖI sheet, trừ sheet CUỐI
     CÙNG (:last-child) để không tạo ra 1 trang trắng thừa ở cuối. */
  .tem-sheet{
    display:grid!important;
    aspect-ratio:auto!important; /* HỦY tỉ lệ A4 chỉ dành cho xem trước màn hình — lúc in phải để chiều cao tự nhiên theo đúng nội dung thật, không ép theo tỉ lệ nào cả (nếu để lọt, chiều cao sẽ bị đẩy sai lệch khỏi số liệu đã tính đúng) */
    border:0!important;
    box-shadow:none!important;
    margin:0;padding:0;
    width:100%;
    grid-template-columns:repeat(3,1fr);
    gap:0; /* Liền kề nhau để dễ cắt */
    break-after:page;
    page-break-after:always; /* tương thích trình duyệt cũ hơn chưa hỗ trợ break-after */
  }
  .tem-sheet:last-child{
    break-after:auto;
    page-break-after:auto;
  }
  .tem{
    break-inside:avoid;
    height:39mm; /* 7 hàng */
    border:0.3mm solid #999!important; /* Đường kẻ mỏng làm đường cắt */
    overflow:hidden;
    padding:1.5mm 2mm 1mm 2mm;
    box-sizing:border-box;
  }
  .tem-empty{border:none!important;background:#fff!important}
  .tem-img-col{background:transparent!important}
  .tem-name{
    font-size:8pt; /* CỠ CHỮ CỐ ĐỊNH — không tự co nhỏ nữa dù tên dài cỡ nào */
    margin:0 2mm 1mm 2mm; /* cách lề trái/phải đúng 2mm */
    white-space:nowrap !important;
    overflow:hidden !important; /* thừa thì CẮT BỎ, không tràn ra ngoài */
    text-overflow:ellipsis; /* hiện "..." ở chỗ bị cắt */
    text-align:center;
    display:block;
  }
  .tem-price{font-size:13pt}
  .tem-loc,.tem-id,.barcode-text{font-size:6.5pt}
  svg.barcode{fill:#000!important;height:12mm}
  .tem-shop{
    background:#4a7a3f!important;
    font-size:6pt;
    padding:0.5mm;
    margin-top:1mm;
  }
  .tem-product-img{object-fit:cover;width:100%;height:100%}

  /* ═══════════════════════════════════════════════════════════════════════════════════════════
     TEM V3330 (프린텍/printec.co.kr) — HOÀN TOÀN TÁCH BIỆT với .tem-sheet/.tem của "🏷️ Tem kệ" ở
     trên (không đụng gì tới nhau, dùng @page riêng tên "v3330page" ở trên).
     Khổ giấy: A4 THẬT (210×297mm) — đã kiểm chứng chéo: "tiêu chuẩn 199,9×289,05mm" bên trang
     printec.co.kr chỉ là vùng in AN TOÀN nằm GIỮA khổ A4, quy đổi ra đúng cùng 1 số lề như số liệu
     gốc (xem phép tính ở trên) — không phải khổ giấy khác. Tem 63,5×38,1mm, 21 tem/tờ (3×7), cách
     ngang 2,5mm, không cách dọc — khớp ở MỌI nguồn tìm được.
     Lề TRÁI/TRÊN (nơi neo vị trí tem, không được đổi): 7.25mm / 15.15mm — ĐÚNG số liệu chuẩn.
     Lề PHẢI/DƯỚI: cố tình bớt hơn số chuẩn (2mm / 3mm thay vì 7.25mm/15.15mm) làm khoảng đệm an
     toàn — máy in Canon G3010 (và nhiều máy in phun khác) vẫn giữ 1 khoảng hẹp không in được ở mép
     dù phần mềm đã đặt lề = 0 (giới hạn phần cứng đầu in/con lăn, không sửa được bằng CSS). Bớt lề
     ở 2 cạnh KHÔNG có tem nào (chỉ là khoảng trắng thừa) hoàn toàn AN TOÀN — không ảnh hưởng vị trí
     bất kỳ tem nào, vì tem luôn neo từ cạnh trái/trên xuống. */
  .v3330-sheet-pages{display:block!important;gap:0!important}
  .v3330-sheet{
    /* ĐỔI SANG FLOAT thay vì display:grid — đã kiểm chứng (đo bằng DevTools "Emulate CSS print")
       chiều cao tính đúng 100% chính xác (284.85mm, khớp số đã tính), NHƯNG hộp thoại in thật của
       Chrome vẫn tự tách sai thành 3 trang — nguyên nhân là CHROME CÓ BUG khi PHÂN TRANG IN với
       CSS Grid (display:grid), grid vốn không phải layout được thiết kế tốt cho việc ngắt trang in.
       Float là cách xếp CỔ ĐIỂN nhưng được hỗ trợ ngắt trang ổn định tuyệt đối, các công cụ in tem
       chuyên nghiệp vẫn dùng cách này — giữ NGUYÊN 100% kích thước/lề/khoảng cách đã tính đúng, chỉ
       đổi CƠ CHẾ XẾP (từ grid sang float), không ảnh hưởng gì tới vị trí từng tem. */
    display:block!important;
    box-shadow:none!important; /* Hiệu ứng đổ bóng chỉ dành cho MÀN HÌNH (xem trước dạng "trang giấy nổi khối") chưa bị hủy khi in — bóng đổ có lệch xuống dưới (0 1px 4px) nên hiện ra đúng thành 1 vệt xám mờ ở cuối trang lúc in thật */
    aspect-ratio:auto!important; /* QUAN TRỌNG — nếu để lọt tỉ lệ A4 (chỉ dành riêng cho xem trước màn hình) sang đây, chiều cao sẽ bị ép về ~297mm, XOÁ MẤT khoảng đệm an toàn đã đo đạc kỹ để né lỗi tràn/lệch trang lúc in (xem giải thích phía trên) */
    margin:0;
    width:210mm;
    padding:14.60mm 2mm 13.7mm 4.05mm; /* Lề DƯỚI tăng lên 15.7mm để tổng chiều cao khớp ĐÚNG 297mm (mép giấy A4 thật) — trước đây cố tình để dư 3mm (thay vì 15.7mm) làm khoảng đệm né lỗi tràn trang, nhưng đó lại tạo ra 1 "ranh giới nội dung" giữa trang (kết thúc ở ~284mm) gây ra vệt xám mờ khi in. Giờ kéo khung nội dung dài hết tới đúng mép giấy thật, không còn ranh giới giữa trang nào nữa. Lề TRÁI/TRÊN (4.05mm/14.60mm) giữ NGUYÊN 100% — không đổi, không ảnh hưởng gì tới vị trí từng tem đã hiệu chỉnh đúng. */
    box-sizing:border-box; /* THIẾU DÒNG NÀY LÀ NGUYÊN NHÂN THẬT gây ra lớp phủ xám — không có nó, padding bị CỘNG THÊM vào 210mm (thay vì nằm bên trong), khiến tổng bề rộng thực tế = 216.05mm, TRÀN RA NGOÀI khổ giấy A4 thật (210mm) */
    /* Đổi từ overflow:hidden sang "clearfix" (::after bên dưới) để CHỨA các ô float bên trong —
       overflow:hidden tạo ra 1 đường CẮT (clip boundary) đúng ngay mép cuối nội dung, nghi là
       nguyên nhân tạo vệt xám mờ khi in thật. Clearfix không cắt gì cả, chỉ "ép" khung cha tự cao
       lên đúng bằng nội dung float bên trong — sạch hơn, không có đường cắt nào. */
    break-after:page;
    page-break-after:always;
  }
  .v3330-sheet::after{ content:""; display:table; clear:both; }
  .v3330-sheet:last-child{
    break-after:auto;
    page-break-after:auto;
  }
  .v3330-tem{
    float:left;
    break-inside:avoid;
    width:63.5mm;
    height:38.1mm;
    margin:0 2.5mm 0 0; /* cách ngang 2.5mm sang tem kế tiếp — tem thứ 3 mỗi hàng sẽ bỏ margin này (xem dưới) */
    border:none!important; /* KHÔNG in viền/đường kẻ nào cả — chỉ in đúng nội dung tem, theo yêu cầu (nếu dùng tờ V3330 thật đã có sẵn đường cắt riêng, không cần web in thêm viền chồng lên) */
    overflow:hidden;
    padding:1.2mm 1.5mm;
    box-sizing:border-box;
    display:flex;
    flex-direction:column;
  }
  .v3330-tem:nth-child(3n){ margin-right:0; } /* tem cuối mỗi hàng (thứ 3/6/9...) không cần khoảng cách sau nó */
  .v3330-tem:nth-child(3n+1){ clear:left; } /* tem đầu mỗi hàng mới (thứ 1/4/7...) phải "clear" để chắc chắn xuống đúng hàng, không bị đẩy lên chen hàng trước */
  .v3330-tem-empty{border:none!important;background:#fff!important}
  .v3330-tem-name{
    font-weight:700;
    font-size:8.5pt; /* CỠ CHỮ CỐ ĐỊNH — không tự co nhỏ nữa dù tên dài cỡ nào */
    white-space:nowrap!important;
    overflow:hidden!important; /* thừa thì CẮT BỎ, không tràn ra ngoài */
    text-overflow:ellipsis; /* hiện "..." ở chỗ bị cắt, để biết tên đã bị rút gọn chứ không phải tên thật đầy đủ chỉ có vậy */
    text-align:center;
    display:block;
    margin:0 2mm 0.8mm 2mm; /* cách lề trái/phải đúng 2mm */
    flex-shrink:0;
  }
  .v3330-tem-body{flex:1;min-height:0;width:100%;display:flex;flex-direction:row;gap:1.2mm}
  .v3330-tem-img-col{width:38%;flex-shrink:0;overflow:hidden;display:flex;align-items:stretch;background:transparent!important}
  .v3330-tem-img{width:100%;height:100%;object-fit:cover;object-position:center;display:block}
  .v3330-tem-right{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:space-between}
  .v3330-tem-price{font-weight:700;font-size:10pt;color:#c8181e;text-align:right}
  .v3330-tem-meta-row{display:flex;flex-direction:row;justify-content:space-between;align-items:center}
  .v3330-tem-loc,.v3330-tem-id{font-size:6pt;color:#444;font-weight:600}
  .v3330-tem-bc-wrap{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;flex:1;min-height:0}
  .v3330-tem-bc-wrap svg.barcode{fill:#000!important;height:12mm} /* to bằng Tem kệ (12mm) theo yêu cầu */
  .v3330-barcode-text{font-size:6pt}
  .v3330-tem-shop{background:#4a7a3f!important;color:#fff;text-align:center;font-size:5.5pt;padding:0.4mm;flex-shrink:0;margin-top:0.5mm}

  /* ═══════════════════════════════════════════════════════════════════════════════════════════
     NHÃN V3330 — copy Y HỆT khối CSS "Tem V3330" ở trên (đã kiểm chứng chạy đúng — dùng FLOAT thay
     vì CSS Grid để né bug ngắt trang của Chrome, xem giải thích đầy đủ ở khối .v3330-sheet phía
     trên), chỉ khác nội dung bên trong mỗi ô: 3 dòng chữ đơn giản thay vì ảnh/mã vạch/giá đầy đủ. */
  .v3330n-sheet-pages{display:block!important;gap:0!important}
  .v3330n-sheet{
    display:block!important;
    box-shadow:none!important; /* xem giải thích ở khối .v3330-sheet phía trên, cùng lỗi/cùng cách sửa */
    aspect-ratio:auto!important; /* QUAN TRỌNG — xem giải thích ở khối .v3330-sheet phía trên, cùng lỗi/cùng cách sửa */
    margin:0;
    width:210mm;
    padding:14.60mm 2mm 13.7mm 4.05mm; /* Lề DƯỚI tăng lên 15.7mm để tổng chiều cao khớp ĐÚNG 297mm — xem giải thích đầy đủ ở khối .v3330-sheet phía trên. Lề trái/trên giữ nguyên, không đổi vị trí tem. */
    box-sizing:border-box;
    break-after:page;
    page-break-after:always;
  }
  .v3330n-sheet::after{ content:""; display:table; clear:both; }
  .v3330n-sheet:last-child{
    break-after:auto;
    page-break-after:auto;
  }
  .v3330n-tem{
    float:left;
    break-inside:avoid;
    width:63.5mm;
    height:38.1mm;
    margin:0 2.5mm 0 0;
    border:none!important; /* KHÔNG in viền nào cả — theo yêu cầu, chỉ in đúng nội dung tem */
    overflow:hidden;
    padding:1.2mm 1.5mm;
    box-sizing:border-box;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:0.8mm;
  }
  .v3330n-tem:nth-child(3n){ margin-right:0; }
  .v3330n-tem:nth-child(3n+1){ clear:left; }
  .v3330n-tem-empty{border:none!important;background:#fff!important}
  .v3330n-line{
    white-space:nowrap!important;
    overflow:visible!important;
    text-align:center;
    transform-origin:center center;
    display:block;
    max-width:100%;
  }
  .v3330n-line-name{
    font-weight:700;
    font-size:10pt; /* CỠ CHỮ CỐ ĐỊNH — không tự co nhỏ nữa dù tên dài cỡ nào */
    overflow:hidden!important; /* thừa thì CẮT BỎ, không tràn ra ngoài */
    text-overflow:ellipsis; /* hiện "..." ở chỗ bị cắt */
    max-width:calc(100% - 4mm)!important; /* cách lề trái/phải đúng 2mm mỗi bên (2mm × 2 = 4mm) */
    margin:0 auto; /* căn giữa trong bề rộng còn lại sau khi trừ lề */
  }
  .v3330n-bc-wrap{display:flex;flex-direction:column;align-items:center;gap:0.3mm;width:100%}
  /* Mã vạch GIÃN RA hết chiều ngang ô (63.5mm), cách lề mỗi bên đúng 2mm — trước đây không đặt
     width tường minh nên trình duyệt tự co theo đúng tỉ lệ viewBox gốc (95:30), ra mã vạch hẹp hơn
     hẳn so với bề ngang thật của ô. viewBox có preserveAspectRatio="none" (xem barcodeSVG() trong
     app.js) nên đặt width tường minh sẽ tự GIÃN/CO đúng theo width đó, không bị méo lo gì. */
  .v3330n-bc-wrap svg.barcode{fill:#000!important;height:12mm;width:59.5mm;display:block;margin:0 auto}
  .v3330n-line-barcode{font-size:6.5pt;color:#000;font-family:monospace}
  .v3330n-line-price{font-weight:800;font-size:13pt;color:#c8181e}
  .v3330n-line-web{font-weight:600;font-size:9pt;color:#4a7a3f} /* to hơn trước (7.5pt -> 9pt) */

  /* ═══════════════════════════════════════════════════════════════════════════════════════════
     NHÃN V3410 — ĐỔI HẲN cách dàn ô khi in thật sang CSS GRID (thay vì float+clear+nth-child như
     trước) — LỖI ĐÃ GẶP THẬT: bản xem trước trên MÀN HÌNH dùng CSS Grid (display:grid ở khối không
     in phía trên) nên LUÔN đúng vị trí; còn bản IN THẬT trước đây dùng float — kiểu dàn ô này cực dễ
     bị lệch tích lũy khi có sai số làm tròn dù chỉ rất nhỏ (từng gặp: 1 nhãn đặt ở ô số 4 trên màn
     hình lại in ra ở ô số 5 của TRANG 2!) vì mỗi phần tử phải tự tính đúng "có đủ chỗ trên hàng hiện
     tại không" — sai 1 lần là dồn sai cho toàn bộ các hàng phía sau. CSS Grid định vị theo LƯỚI CỐ
     ĐỊNH ngay từ đầu (đủ 4 cột × 10 hàng khai báo rõ ràng), không có bước "tính xem còn chỗ hay
     không" nào để bị lệch — cùng cách dàn ô ĐÃ DÙNG ĐÚNG cho bản xem trước, giờ áp dụng luôn cho bản
     in thật, đảm bảo 2 bản khớp nhau tuyệt đối. */
  .v3410-sheet-pages{display:block!important;gap:0!important}
  .v3410-sheet{
    display:grid!important;
    grid-template-columns:repeat(4, 47mm);
    grid-auto-rows:26.9mm;
    /* Số đo THẬT bằng thước trên tờ giấy tem thật — KHÔNG BAO GIỜ được đổi giá trị này, vì đây là
       khoảng cách vật lý CỐ ĐỊNH giữa các ô tem thật đã cắt sẵn trên giấy, đổi số này sẽ làm lưới in
       không còn khớp với kết cấu tem thật nữa (khác hẳn với lề trang, vốn chỉ là vị trí toàn khối
       lưới trên trang, có thể dịch chuyển tự do mà không ảnh hưởng gì tới kết cấu bên trong lưới). */
    column-gap:2.4mm;
    row-gap:0; /* các hàng sát nhau, không giãn cách dọc */
    box-shadow:none!important;
    aspect-ratio:auto!important;
    margin:0;
    width:210mm;
    /* Theo ảnh chụp thật: tâm nhãn đang lệch TRÁI khoảng 2mm so với tâm ô tem thật — dịch PHẢI 2mm
       để bù lại: 5.27 + 2 = 7.27mm. Lề trên/phải/dưới giữ nguyên. */
    padding:13mm 6.5mm 12mm 7.27mm;
    box-sizing:border-box;
    break-after:page;
    page-break-after:always;
  }
  .v3410-sheet:last-child{
    break-after:auto;
    page-break-after:auto;
  }
  .v3410-tem{
    /* KHÔNG còn float/margin/clear — Grid tự đặt đúng vị trí theo thứ tự trong HTML, không cần tính
       toán gì thêm ở đây cả. */
    break-inside:avoid;
    border:none!important;
    overflow:hidden;
    padding:1mm 1.2mm;
    box-sizing:border-box;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:0.6mm;
  }
  .v3410-tem-empty{border:none!important;background:#fff!important}
  .v3410-line{
    white-space:nowrap!important;
    overflow:visible!important;
    text-align:center;
    transform-origin:center center;
    display:block;
    max-width:100%;
  }
  .v3410-line-name{
    font-weight:700;
    font-size:7.5pt; /* CỠ CHỮ CỐ ĐỊNH, thu nhỏ theo đúng tỉ lệ ô nhỏ hơn V3330 — không tự co nhỏ nữa dù tên dài cỡ nào */
    overflow:hidden!important;
    text-overflow:ellipsis;
    max-width:calc(100% - 3mm)!important; /* cách lề trái/phải đúng 1.5mm mỗi bên */
    margin:0 auto;
  }
  .v3410-bc-wrap{display:flex;flex-direction:column;align-items:center;gap:0.2mm;width:100%}
  /* Mã vạch GIÃN RA hết chiều ngang ô (47mm), cách lề mỗi bên đúng 2mm — CÙNG lý do/cách làm với
     V3330 ở trên. */
  /* Mã vạch — THEO YÊU CẦU: cách đều lề trái/phải của TEM đúng 2mm, không quan tâm kích thước cụ
     thể là bao nhiêu (chỉ cần đúng khoảng cách 2mm) — với ô rộng 47mm, padding sẵn có 1,2mm mỗi bên,
     cần thêm đúng 0,8mm lề tự động mỗi bên nữa mới đủ 2mm tổng, ra đúng width=43mm. LƯU Ý: đây CHÍNH
     LÀ con số đã từng gây lỗi "cắt mất 1 vạch mã vạch bên phải" trước đó — nếu lỗi đó lặp lại, nhiều
     khả năng nguyên nhân KHÔNG nằm ở khoảng cách trong ô này, mà ở lề TRANG (margin của .v3410-sheet)
     chưa khớp tuyệt đối với máy in thật — cần đo lại lề trang, không phải giảm mã vạch xuống nữa. */
  .v3410-bc-wrap svg.barcode{fill:#000!important;height:8.5mm;width:43mm;display:block;margin:0 auto}
  /* Số mã vạch — TO HƠN (5pt -> 7pt) và GIÃN RA cho dài bằng đúng 3/4 chiều rộng mã vạch (43mm ×
     0.75 = 32.25mm) — dùng text-justify:inter-character (giãn khoảng cách giữa TỪNG KÝ TỰ, không
     chỉ giữa các từ cách nhau bằng dấu cách — cần thiết vì chuỗi số mã vạch không có dấu cách nào cả)
     kết hợp text-align-last:justify (bắt buộc phải có, vì text-align:justify mặc định CHỈ áp dụng
     cho các dòng KHÔNG PHẢI dòng cuối/dòng duy nhất — ở đây chỉ có 1 dòng nên luôn là "dòng cuối",
     nếu thiếu text-align-last thì justify không có tác dụng gì cả). */
  .v3410-line-barcode{font-size:7pt;color:#000;font-family:monospace;width:32.25mm;display:block;margin:0 auto;text-align:justify;text-align-last:justify;text-justify:inter-character}
  .v3410-line-price{font-weight:800;font-size:12pt;color:#c8181e} /* to hơn (10pt -> 12pt) */
  .v3410-line-web{font-weight:600;font-size:7pt;color:#4a7a3f} /* to hơn trước (6pt -> 7pt) */
}

/* ===== DASHBOARD ===== */
.db-wrap{display:grid;grid-template-columns:190px 1fr 148px;gap:3px;padding:4px;flex:1;overflow:hidden;height:100%}
.db-left{display:flex;flex-direction:column;gap:2px;overflow:auto}
.db-kpi-head{background:#1a4080;color:#fff;font-size:10px;font-weight:700;padding:4px 8px;text-align:center;letter-spacing:.06em;flex-shrink:0}
.db-kpi{display:flex;align-items:center;gap:7px;padding:5px 7px;border:1px solid rgba(0,0,0,.1);flex-shrink:0}
.db-kpi.c-blue{background:#2196f3;border-left:3px solid #1565c0}
.db-kpi.c-green{background:#43a047;border-left:3px solid #1b5e20}
.db-kpi.c-orange{background:#fb8c00;border-left:3px solid #bf360c}
.db-kpi.c-purple{background:#8e24aa;border-left:3px solid #4a148c}
.db-kpi.c-teal{background:#00838f;border-left:3px solid #004d40}
.db-kpi.c-red{background:#e53935;border-left:3px solid #b71c1c}
.db-kpi.c-gray{background:#546e7a;border-left:3px solid #263238}
.db-kpi-ico{font-size:18px;flex-shrink:0;line-height:1}
.db-kpi-lbl{font-size:9px;font-weight:700;color:rgba(255,255,255,.9);letter-spacing:.02em}
.db-kpi-val{font-size:13px;font-weight:700;color:#fff;line-height:1.15}
.db-kpi-sub{font-size:9px;color:rgba(255,255,255,.8)}
.db-center{display:flex;flex-direction:column;gap:3px;overflow:auto;min-width:0}
.db-charts-row{display:grid;grid-template-columns:repeat(3,1fr);gap:3px;flex-shrink:0}
.db-mid-row{display:grid;grid-template-columns:repeat(3,1fr);gap:3px;flex-shrink:0}
.db-chart-card{background:#fff;border:2px solid;border-color:#808080 #fff #fff #808080;padding:5px;min-width:0}
.db-chart-title{font-size:10px;font-weight:700;color:#1a4080;text-align:center;border-bottom:1px solid #eee;padding-bottom:2px;margin-bottom:3px}
.db-rank-row{display:flex;align-items:center;gap:3px;padding:2px 0;border-bottom:1px solid #f0f0f0;font-size:10px}
.db-rank-num{width:13px;color:#888;flex-shrink:0;font-weight:700;font-size:9px}
.db-rank-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:10px}
.db-rank-bar-wrap{width:70px;background:#e8e8e8;height:7px;flex-shrink:0}
.db-rank-bar{height:7px;background:#2196f3}
.db-rank-bar.red{background:#e53935}
.db-rank-val{width:28px;text-align:right;font-weight:700;font-size:10px;flex-shrink:0}
.db-donut-legend{display:flex;flex-wrap:wrap;gap:2px 6px;margin-top:3px;font-size:9px}
.db-dl-item{display:flex;align-items:center;gap:2px}
.db-dl-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.db-recent-head{font-size:10px;font-weight:700;color:#1a4080;border-bottom:2px solid #2196f3;padding-bottom:2px;margin-bottom:4px}
.db-recent-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.db-import-lbl{color:#1a6090;font-size:10px;font-weight:700;margin-bottom:2px}
.db-export-lbl{color:#c62828;font-size:10px;font-weight:700;margin-bottom:2px}
.db-mini-table{width:100%;border-collapse:collapse;font-size:10px}
.db-mini-table th{padding:2px 4px;font-size:9px;font-weight:700;text-align:left;color:#fff}
.db-mini-table td{padding:2px 4px;border-bottom:1px solid #f0f0f0}
.db-mini-table tr:nth-child(even) td{background:#f8fbff}
.db-mini-imp th{background:#1a6090}
.db-mini-exp th{background:#c62828}
.db-right{display:flex;flex-direction:column;gap:3px;overflow:auto}
.db-alert-box{background:#fff;border:2px solid;border-color:#808080 #fff #fff #808080;padding:0;flex-shrink:0}
.db-box-head{background:#1a4080;color:#fff;font-size:10px;font-weight:700;padding:3px 8px;text-align:center;letter-spacing:.05em}
.db-alert-row{display:flex;align-items:center;gap:4px;padding:3px 6px;border-bottom:1px solid #f0f0f0;font-size:10px}
.db-alert-ico{width:16px;height:16px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;flex-shrink:0}
.db-alert-ico.warn{background:#ff9800;color:#fff}
.db-alert-ico.danger{background:#e53935;color:#fff}
.db-alert-ico.info{background:#2196f3;color:#fff}
.db-alert-txt{flex:1;color:#333;line-height:1.2;font-size:10px}
.db-alert-num{font-weight:700;color:#333;background:#f0f0f0;padding:1px 5px;border-radius:2px;font-size:11px;flex-shrink:0}
.db-qstat{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;border-bottom:1px solid #f0f0f0;font-size:10px}
.db-qstat span{color:#555}
.db-qstat strong{color:#1a4080;font-weight:700}
.db-util-grid{display:grid;grid-template-columns:1fr 1fr;gap:3px;padding:4px}
.db-util-btn{background:#f5f5f5;border:1px solid #ccc;padding:6px 3px;text-align:center;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:2px;font-size:10px;color:#333;width:100%}
.db-util-btn:hover{background:#e8f0ff;border-color:#2196f3}
.db-util-ico{font-size:16px}

/* ===== HSD BADGES & STATUS COLORS ===== */
.hsd-badge{display:inline-block;padding:2px 7px;font-size:10px;font-weight:700;border-radius:2px;white-space:nowrap}
.hsd-expired {background:#ffcccc;color:#880000;border:1px solid #cc0000}
.hsd-critical{background:#ffe0cc;color:#883300;border:1px solid #cc5500}
.hsd-warning {background:#fff8cc;color:#886600;border:1px solid #ccaa00}
.hsd-ok      {background:#ccffcc;color:#005500;border:1px solid #009900}
.hsd-none    {background:#e8e8e8;color:#555555;border:1px solid #aaaaaa}
td.hsd-expired {color:#880000;font-weight:700}
td.hsd-critical{color:#883300;font-weight:700}
td.hsd-warning {color:#886600;font-weight:700}
td.hsd-ok      {color:#005500}

/* ===== PHÍM CHẠM NHANH (POS) — lưới 8×5 ô cấu hình gán sản phẩm ===== */
.qs-cell{
  border:1.5px solid #b8bcc4;border-radius:6px;background:#fff;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  padding:4px;min-height:64px;text-align:center;position:relative;
}
/* QUAN TRỌNG: span con (số ô/tên SP/giá) không được "chắn" sự kiện kéo-thả — nếu không, mỗi lần
   con trỏ chuột lướt qua ranh giới giữa các span con trong lúc kéo, dragover/dragleave bắn ra liên
   tục làm viền cam highlight NHẤP NHÁY (trông rất giật/bất ổn dù dữ liệu vẫn đúng). Cho toàn bộ
   span con "trong suốt" với sự kiện chuột — mọi sự kiện kéo-thả sẽ luôn tính trên đúng 1 phần tử
   .qs-cell duy nhất, không bao giờ bị ngắt quãng giữa chừng. */
.qs-cell *{pointer-events:none}
.qs-cell .qs-slotnum{position:absolute;top:2px;left:4px;font-size:9px;color:#aab;font-weight:700}
.qs-cell.qs-empty{background:#eceef1;border-style:dashed}
.qs-cell.qs-empty:hover{background:#e0e3e8}
.qs-cell.qs-filled{background:#eaf3ff;border-color:#8fb8e8}
.qs-cell.qs-filled .qs-pname{font-size:11px;font-weight:700;color:#1a1f2b;line-height:1.2;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.qs-cell.qs-filled .qs-pprice{font-size:10.5px;font-weight:800;color:#c0392f}
.qs-cell.qs-broken{background:#fff0ee;border-color:#e0a0a0}
.qs-cell.qs-broken .qs-pname{font-size:10px;color:#a03030}
.qs-cell.qs-selected{outline:3px solid #e8973f;outline-offset:-2px}
.qs-cell.qs-filled{cursor:grab}
.qs-cell.qs-filled:active{cursor:grabbing}
.qs-cell.qs-dragover{background:#fff3e0!important;border-color:var(--pos-orange,#e8973f)!important;outline:2px dashed var(--pos-orange,#e8973f);outline-offset:-2px}
/* Ô 1-4 — tab danh mục, gõ tên TRỰC TIẾP trong ô (nền navy đậm + khung nhập trắng bo góc ở giữa,
   giống mẫu tham khảo) — không còn dùng prompt() nữa. QUAN TRỌNG: input/select bên trong phải được
   MỞ LẠI pointer-events (quy tắc ".qs-cell *{pointer-events:none}" ở trên vốn để dành cho các ô
   sản phẩm/kéo-thả, KHÔNG áp dụng được ở đây vì người dùng cần gõ chữ/chọn trang trực tiếp). */
.qs-cell.qs-tab-editable{
  background:var(--pos-navy,#22242e);border-color:var(--pos-navy2,#191b23);cursor:default;
  gap:5px;padding:6px 5px;
}
.qs-cell.qs-tab-editable .qs-slotnum{color:#7d84a0}
.qs-cell.qs-tab-editable .qs-tab-input{
  pointer-events:auto;width:100%;border:none;border-radius:6px;padding:5px 6px;
  font-size:11.5px;font-weight:700;text-align:center;color:#1a1f2b;background:#fff;outline:none;
}
.qs-cell.qs-tab-editable .qs-tab-input::placeholder{color:#a3a8b5;font-weight:500}
.qs-cell.qs-tab-editable .qs-tab-input:focus{box-shadow:0 0 0 2px var(--pos-orange,#e8973f)}
.qs-cell.qs-tab-editable.qs-selected{outline:3px solid var(--pos-orange,#e8973f);outline-offset:-2px}
/* Ô 5 — dành riêng cho mũi tên chuyển trang, không thể gán/kéo-thả gì vào đây */
.qs-cell.qs-reserved{background:#e9ebee;border-style:dashed;border-color:#c3c7ce;cursor:not-allowed;opacity:.8}
.qs-cell.qs-reserved .qs-reserved-label{font-size:15px;color:#8890a0;font-weight:700;letter-spacing:2px}
/* Ô sản phẩm khi CHƯA chọn tab nào ở trên — mờ hẳn, không bấm/kéo-thả được */
.qs-cell.qs-noselect{background:#eceef1;border-style:dashed;opacity:.35;cursor:not-allowed}
/* Cặp nút mũi tên dọc (▲▼) — dùng chung cho cả pager TẦNG 1 (trang tab) lẫn TẦNG 2 (trang con) */
.qs-pager{display:flex;flex-direction:column;gap:6px;flex:0 0 40px}
.qs-pager-btn{
  flex:1;border:1.5px solid #b8bcc4;border-radius:6px;background:#fff;
  font-size:16px;font-weight:800;color:#556;min-height:28px;
}
.qs-pager-btn:active:not(:disabled){background:#eceef1}
.qs-pager-btn:disabled{opacity:.3;cursor:not-allowed}
.mini-list-table tr[draggable="true"]{cursor:grab}
.mini-list-table tr.qs-row-dragging{opacity:.35}
