/* ============ KAW Manager — giao diện quản trị ============ */
:root {
    --blue: #2563eb;
    --blue-d: #1d4ed8;
    --bg: #f3f5f9;
    --card: #ffffff;
    --line: #e5e9f0;
    --text: #1e293b;
    --muted: #64748b;
    --sidebar: #101828;
    --sidebar-2: #1b2537;
    --red: #dc2626;
    --green: #16a34a;
    --orange: #d97706;
    --indigo: #4f46e5;
    --radius: 10px;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    font-family: Roboto, Arial, sans-serif;
    font-size: 13.5px;
    color: var(--text);
    background: var(--bg);
}
a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }
h2 { font-size: 18px; } h3 { font-size: 15px; }
hr { border: 0; border-top: 1px solid var(--line); margin: 16px 0; }
.small { font-size: 12px; }
.muted { color: var(--muted); }
.tr { text-align: right; } .tc { text-align: center; }
.c-red { color: var(--red); } .c-blue { color: var(--blue); }
.c-green { color: var(--green); } .c-orange { color: var(--orange); }
.c-red-b { color: var(--red); font-weight: 700; }
.inline { display: inline; }

/* ---------- Khung ứng dụng ---------- */
.app { display: flex; min-height: 100vh; }
.sidebar {
    width: 232px; flex: 0 0 232px;
    background: var(--sidebar); color: #cbd5e1;
    display: flex; flex-direction: column;
    position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.sidebar-top { display: flex; align-items: center; border-bottom: 1px solid rgba(255,255,255,.08); }
.brand {
    display: flex; align-items: center; flex: 1; min-width: 0;
    padding: 16px 8px 14px 16px;
    color: #fff; font-weight: 700; font-size: 15px;
}
.brand:hover { text-decoration: none; }
.brand-ico { color: var(--blue); margin-right: 4px; }
.brand-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.btn-collapse {
    flex: 0 0 auto; margin-right: 10px; width: 28px; height: 28px;
    border: none; border-radius: 6px; background: transparent; color: #9fb0cc;
    cursor: pointer; font-size: 14px; line-height: 1; position: relative;
}
.btn-collapse:hover { background: var(--sidebar-2); color: #fff; }
.nav { padding: 8px 0 24px; }
/* Bản 199: theo yêu cầu, tiêu đề nhóm ("mục cha") nay cũng là 1 "ô" riêng biệt y hệt các mục con
   bên dưới (bản 198) — thẻ nền, bo góc, cách nhau — thay vì chỉ là chữ nhỏ viết hoa trơn như trước.
   Áp dụng chung cho CẢ 2 dạng: div (.nav-group-pinned, nhóm luôn xổ sẵn, không bấm được) lẫn
   button (.nav-group-head, nhóm bấm được để xổ/thu — bản 196) nên khai ở đúng 1 nơi .nav-group. */
.nav-group {
    margin: 8px 10px 4px; padding: 10px 12px; border-radius: 9px;
    font-size: 10.5px; font-weight: 700;
    letter-spacing: .06em; color: #9fb0cc; text-transform: uppercase;
    background: var(--sidebar-2);
}
/* Bản 196: menu bên trái thu gọn từng nhóm (accordion) — bấm tên nhóm để xổ/thu. Riêng nhóm được
   "ghim" (VD "1. QUẢN LÝ ĐƠN HÀNG") vẫn dùng .nav-group (div, không phải nút) như trước, luôn hiện
   sẵn không có mũi tên — các nhóm còn lại đổi sang <button> cùng class .nav-group để giữ nguyên hệt
   kiểu chữ/màu cũ, chỉ thêm dáng nút bấm được + mũi tên ›. 'all: unset' xóa sạch mọi thuộc tính kế
   thừa từ .nav-group (kể cả nền/bo góc/cỡ chữ mới thêm ở bản 199) nên phải khai lại ĐẦY ĐỦ ở đây,
   không chỉ riêng phần layout nút bấm như trước — thiếu khai lại thuộc tính nào thì nút sẽ trông
   khác hẳn div ghim (đây chính là lý do bản 198 vô tình làm mục cha (button) trông khác mục cha
   (div) dù cùng class .nav-group, phải sửa dứt điểm ở bản này). */
button.nav-group {
    all: unset; box-sizing: border-box; display: flex; align-items: center; justify-content: space-between;
    width: 100%; margin: 8px 10px 4px; padding: 10px 12px; border-radius: 9px;
    font-size: 10.5px; font-weight: 700; letter-spacing: .06em; color: #9fb0cc; text-transform: uppercase;
    background: var(--sidebar-2); cursor: pointer;
}
button.nav-group:hover, button.nav-group.open { background: #26324a; color: #cbd5e1; }
.ng-arrow { font-size: 13px; transition: transform .15s; flex: none; color: #4b5b78; }
button.nav-group:hover .ng-arrow, button.nav-group.open .ng-arrow { color: #cbd5e1; }
.nav-group-head.open .ng-arrow { transform: rotate(90deg); }
.nav-group-body { display: none; }
.nav-group-body.open, .nav-group-body-pinned { display: block; }
.nav-item {
    display: flex; align-items: center; gap: 8px;
    margin: 3px 10px; padding: 10px 12px; color: #cbd5e1; font-size: 13px; position: relative;
    background: var(--sidebar-2); border-radius: 9px;
}
.nav-item:hover { background: #26324a; color: #fff; text-decoration: none; }
.nav-item.active { background: var(--blue); color: #fff; }
.nav-item.active .ni-arrow, .nav-item.active .ni-ico { color: #fff; }
.ni-ico { width: 18px; text-align: center; flex: 0 0 18px; }
/* Bản 198: mỗi mục menu hiển thị dạng "ô" riêng (thẻ nền, bo góc, cách nhau — tham khảo ảnh mẫu
   gửi kèm) kèm mũi tên › cố định bên phải, thay vì trước đây cả khối là 1 danh sách phẳng liền
   nhau không phân tách. Dùng span riêng (.ni-arrow) — KHÔNG dùng ::after — vì ::after của .nav-item
   đã dùng riêng cho tooltip hiện tên mục khi menu đang ở chế độ chỉ-icon (xem bên dưới), 2 công
   dụng khác nhau không thể dùng chung 1 pseudo-element. */
.ni-arrow { margin-left: auto; flex: 0 0 auto; color: #4b5b78; font-size: 17px; font-weight: 600; line-height: 1; }
.nav-item:hover .ni-arrow { color: #cbd5e1; }
.nav-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px;
    background: #e5484d; color: #fff; font-size: 10.5px; font-weight: 700;
    border-radius: 999px; line-height: 1; flex: 0 0 auto;
}
.sidebar-user-collapsed { display: none; }

/* ---------- Sidebar thu gọn (chỉ hiện icon, có tooltip khi rê chuột) ---------- */
body.sidebar-collapsed .sidebar { width: 64px; flex: 0 0 64px; }
body.sidebar-collapsed .brand { padding: 16px 0; justify-content: center; }
body.sidebar-collapsed .brand-text { display: none; }
body.sidebar-collapsed .brand-ico { margin-right: 0; }
body.sidebar-collapsed .sidebar-top { flex-direction: column-reverse; padding: 4px 0; }
body.sidebar-collapsed .btn-collapse { margin: 4px 0; }
body.sidebar-collapsed .nav-group { display: none; }
/* Chế độ chỉ-icon (thu gọn toàn sidebar): không còn tiêu đề nhóm để bấm xổ/thu nữa -> luôn hiện hết
   mọi mục (icon) bất kể đang đóng/mở accordion, giữ đúng hành vi cũ trước khi có accordion. */
body.sidebar-collapsed .nav-group-body { display: block; }
body.sidebar-collapsed .ni-label { display: none; }
body.sidebar-collapsed .ni-arrow { display: none; }
body.sidebar-collapsed .nav-item { justify-content: center; padding: 9px 0; margin: 3px 10px; }
body.sidebar-collapsed .sidebar-user { display: none; }
body.sidebar-collapsed .sidebar-user-collapsed {
    display: flex; flex-direction: column; border-top: 1px solid rgba(255,255,255,.08); padding: 6px 0;
}
/* Bản 228: sửa lỗi tooltip sidebar thu gọn KHÔNG HIỆN — nguyên nhân giống hệt lỗi panel chuông
   thông báo đã sửa ở bản 188 (`.topbar overflow:hidden` cắt mất `.bell-panel`): `.sidebar` (và
   `.sidebar .nav` ở chế độ mobile, dòng ~608) có `overflow-y: auto` để cuộn danh sách menu — theo
   đặc tả CSS, chỉ cần overflow-y KHÁC visible là overflow-x cũng tự động bị tính là "auto" (không
   còn "visible"), nên `::after` dùng `position: absolute; left: 100%` của tooltip vừa tràn ra khỏi
   mép phải sidebar là bị CẮT NGAY LẬP TỨC — tooltip vẫn "tồn tại" về mặt DOM/CSS nhưng người dùng
   không bao giờ thấy được, dù data-tip đã có sẵn đúng giá trị (đây là lỗi TỪ TRƯỚC, không phải mới
   phát sinh, không liên quan gì tới thẻ Trang chủ vừa thêm tooltip ở bản 227 — thẻ đó nằm trong
   `.content`/`.main` KHÔNG có overflow-y nên không bị lỗi này).
   Cách sửa: bỏ hẳn kỹ thuật `::after` (luôn bị cắt do nằm bên trong khung có overflow), chuyển sang
   1 phần tử `<div id="sbTooltip">` DÙNG CHUNG đặt NGOÀI `.sidebar` (con trực tiếp của `<body>`, xem
   views/layout.php) với `position: fixed` — thoát hẳn khỏi mọi khung overflow, toạ độ do JS tính lại
   đúng theo vị trí thật của icon đang hover mỗi lần hiện (xem assets/js/app.js), y hệt kỹ thuật đã
   dùng cho `.bell-panel`. */
body.sidebar-collapsed .nav-item[data-tip]:hover::after,
body.sidebar-collapsed .btn-collapse[data-tip]:hover::after { content: none; }
.sb-tooltip {
    position: fixed; background: #111827; color: #fff; padding: 5px 10px;
    border-radius: 6px; font-size: 12.5px; white-space: nowrap; z-index: 200;
    box-shadow: 0 6px 16px rgba(0,0,0,.28); pointer-events: none;
    opacity: 0; transition: opacity .08s ease-out;
}
.sb-tooltip.show { opacity: 1; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
    background: var(--card); border-bottom: 1px solid var(--line);
    display: flex; align-items: center; gap: 12px; flex-wrap: nowrap;
    padding: 0 20px; min-height: 54px; overflow: hidden;
    position: sticky; top: 0; z-index: 20;
}
.topbar-title {
    font-weight: 700; font-size: 15px; flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-user { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.topbar-logo { display: flex; align-items: center; flex: 0 0 auto; }
.u-name { font-weight: 600; }
.u-name small { color: var(--muted); font-weight: 400; }

/* ---------- Dải tab đầu trang (gộp menu — xem config/tab_groups.php) ----------
   Khi module đang mở thuộc 1 "nhóm tab", hiện các module còn lại của nhóm dưới dạng tab ngang
   ngay dưới topbar để chuyển qua lại, thay vì phải tách rời từng mục ở menu bên trái. */
.page-tabs {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
    background: var(--card); border-bottom: 1px solid var(--line);
    padding: 8px 20px; position: sticky; top: 54px; z-index: 19;
}
.page-tab {
    display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px;
    border-radius: 8px; font-size: 13px; font-weight: 600; color: var(--muted);
    text-decoration: none; white-space: nowrap; transition: background .15s, color .15s;
}
.page-tab:hover { background: var(--bg); color: var(--text); text-decoration: none; }
.page-tab.active { background: var(--sidebar); color: #fff; }
.page-tab .pt-ico { font-size: 13px; }

/* Bản 304: nút chuyển đổi 2 chế độ "Quản lý"/"Tổng quan" ở Trang chủ — dạng viên thuốc (pill)
   chia 2, đúng kiểu tham khảo từ giao diện QLNS (hệ thống khác của cùng công ty): nền xám nhạt bo
   tròn nguyên viên, nút đang CHỌN nổi nền xanh + chữ trắng, nút còn lại nền trong suốt + chữ xám. */
.mode-toggle {
    display: flex; align-items: center; gap: 2px; flex: 0 0 auto;
    background: #eef1f5; border-radius: 999px; padding: 3px;
}
.mode-btn {
    display: inline-flex; align-items: center; gap: 5px; padding: 6px 14px;
    border-radius: 999px; font-size: 13px; font-weight: 600; color: var(--muted);
    text-decoration: none; white-space: nowrap; transition: background .15s, color .15s;
}
.mode-btn:hover { color: var(--text); }
.mode-btn.active { background: var(--blue); color: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.15); }
.mode-btn.active:hover { color: #fff; }

/* Bản 309: bản mobile của nút chuyển đổi ở trên — đặt trong sidebar (nền tối) thay vì thanh trên
   cùng (quá hẹp trên điện thoại) nên cần bộ màu riêng phù hợp nền tối, và 2 nút chia đều hết chiều
   ngang thay vì co theo nội dung như bản desktop. Ẩn mặc định, chỉ hiện ở mobile (only-mobile-flex,
   xem quy tắc @media phía trên) — desktop vẫn dùng đúng 1 nút ở thanh trên cùng, không lặp 2 nơi. */
.sidebar-mode-toggle {
    align-items: center; gap: 2px; margin: 10px 14px 6px;
    background: rgba(255,255,255,.06); border-radius: 999px; padding: 3px;
}
.sidebar-mode-toggle .mode-btn {
    flex: 1 1 0; justify-content: center; color: #94a3b8;
}
.sidebar-mode-toggle .mode-btn:hover { color: #fff; }

/* ---------- 🔔 Chuông thông báo (bản 179) ---------- */
.bell-wrap { position: relative; }
.bell-btn {
    position: relative; background: none; border: none; cursor: pointer;
    font-size: 19px; line-height: 1; padding: 6px; border-radius: 8px; color: var(--text);
}
.bell-btn:hover { background: var(--bg); }
.bell-badge {
    position: absolute; top: -2px; right: -2px; background: #e5484d; color: #fff;
    font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 999px;
    display: flex; align-items: center; justify-content: center; padding: 0 3px; line-height: 1;
}
.bell-panel {
    /* Bản 187: position:fixed (không phải absolute) — .topbar là ancestor có overflow:hidden
       (để cắt gọn tiêu đề trang dài), nên panel kiểu absolute trồi ra ngoài khung .topbar sẽ bị
       CẮT MẤT hoàn toàn dù có z-index cao tới đâu (overflow:hidden clip trước, z-index không cứu
       được) — đúng nguyên nhân panel "có trong DOM nhưng không thấy gì". Dùng fixed để thoát hẳn
       khỏi mọi ancestor bị cắt, tọa độ top/right tính bằng JS lúc mở (xem assets/js/app.js) theo
       đúng vị trí thật của nút chuông trên màn hình — đúng cả khi cuộn trang lẫn khi menu thu gọn.
    */
    display: none; position: fixed; width: 340px; max-width: 90vw;
    max-height: 420px; overflow: auto; background: var(--card); border: 1px solid var(--line);
    border-radius: 10px; box-shadow: 0 10px 28px rgba(0,0,0,.16); z-index: 200;
}
.bell-panel.open { display: block; }
.bell-panel-head {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 10px 12px; border-bottom: 1px solid var(--line); font-weight: 700; font-size: 13.5px;
}
.bell-item {
    display: block; padding: 10px 12px; border-bottom: 1px solid var(--line);
    text-decoration: none; color: inherit;
}
.bell-item:last-child { border-bottom: none; }
.bell-item:hover { background: var(--bg); }
.bell-item.unread { background: #eef4ff; }
.bell-item-title { font-size: 13.5px; font-weight: 600; margin-bottom: 2px; }
.bell-item-body { font-size: 12.5px; color: var(--muted); white-space: pre-line; }
.bell-item-time { font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.bell-empty { padding: 22px 12px; text-align: center; color: var(--muted); font-size: 13px; }
.content { padding: 18px 20px 40px; }

/* ---------- Thanh tiến độ NỀN đồng bộ Shopee (sync-widget, bản 236) ----------
   Markup + endpoint JSON (ShopeeController::syncStatus()) đã có sẵn từ trước, nhưng CHƯA từng có
   CSS/JS thật đứng sau — khung <div id="syncWidget"> luôn ở display:none vĩnh viễn, không ai thấy
   được, "🔄 Đồng bộ" bấm xong coi như mất tăm. Khối này + phần JS tương ứng ở assets/js/app.js là
   phần còn thiếu, ghép nối đúng những gì server đã trả sẵn (không đổi gì phía PHP). */
.sync-widget {
    position: fixed; right: 20px; bottom: 20px; z-index: 60;
    width: 300px; max-width: calc(100vw - 32px);
    background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
    box-shadow: 0 10px 28px rgba(0,0,0,.18);
}
.sync-widget.sw-error { border-color: #f3b4b4; }
.sw-row { display: flex; align-items: flex-start; gap: 10px; padding: 12px 12px 12px 14px; }
.sw-ico { font-size: 18px; line-height: 1.3; flex: 0 0 auto; }
.sw-body { flex: 1 1 auto; min-width: 0; }
.sw-title { font-weight: 700; font-size: 13px; margin-bottom: 6px; }
.sync-widget.sw-error .sw-title { color: var(--red); }
.sync-widget.sw-done .sw-title { color: var(--green); }
.sw-bar { background: var(--bg); border-radius: 999px; height: 6px; overflow: hidden; }
.sw-bar-fill { background: var(--blue); height: 100%; border-radius: 999px; transition: width .3s ease; }
.sync-widget.sw-error .sw-bar-fill { background: var(--red); }
.sync-widget.sw-done .sw-bar-fill { background: var(--green); }
.sw-sub { color: var(--muted); font-size: 12px; margin-top: 6px; white-space: pre-line; }
.sw-stop {
    flex: 0 0 auto; border: 0; background: none; cursor: pointer; color: var(--muted);
    font-size: 14px; line-height: 1; padding: 2px 4px; border-radius: 6px;
}
.sw-stop:hover { background: var(--bg); color: var(--text); }
@media (max-width: 900px) {
    .sync-widget { right: 12px; bottom: calc(70px + env(safe-area-inset-bottom)); width: 260px; }
}

/* ---------- Nút ---------- */
.btn {
    display: inline-block; border: 1px solid transparent; cursor: pointer;
    border-radius: 8px; padding: 8px 14px; font-size: 13px; font-weight: 600;
    background: var(--card); color: var(--text); line-height: 1.2;
}
.btn:hover { text-decoration: none; filter: brightness(.97); }
.btn-primary { background: var(--blue); color: #fff; }
.btn-primary:hover { background: var(--blue-d); }
.btn-ghost { border-color: var(--line); background: #fff; }
.chart-tab-btn.active { background: var(--blue); color: #fff; border-color: var(--blue); }
.btn-danger { background: #fee2e2; color: var(--red); }
.btn-sm { padding: 5px 10px; font-size: 12.5px; }
.btn-block { width: 100%; }
.btn-icon { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 6px 10px; cursor: pointer; }
.mini {
    display: inline-block; padding: 2px 7px; border-radius: 6px;
    border: 1px solid var(--line); background: #fff; color: var(--muted);
    font-size: 12px; cursor: pointer;
}
.mini:hover { color: var(--blue); border-color: var(--blue); text-decoration: none; }
.sp-del-txt { display: none; }

/* ---------- Card / toolbar ---------- */
.card {
    display: block; width: 100%; box-sizing: border-box;
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 16px; margin-bottom: 16px;
}
.card-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 12px; flex-wrap: wrap;
}
.card-head h2 { margin: 0; }
.card-doisoat {
    background: #fffbe6; border: 1px solid #f1c40f;
    box-shadow: 0 0 0 1px rgba(241,196,15,.15) inset;
}
.toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 14px; flex-wrap: wrap;
}
.toolbar-search { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; flex: 1 1 320px; }
.toolbar-search .f-input { width: auto; min-width: 170px; }
/* Bản 231: selects trong toolbar-search trước đây "width:auto" nên MỖI ô tự co giãn theo độ dài chữ
   placeholder của riêng nó (vd "— Tất cả loại xử lý đơn hàng —" dài hơn hẳn "— Gian hàng —") — khiến
   các ô có bề rộng rất lệch nhau, ô dài chiếm hết phần còn lại của hàng và đẩy các ô sau xuống dòng
   riêng dù màn hình còn thừa chỗ ngang, nhìn lộn xộn (ảnh user gửi kèm). Ép về 1 bề rộng CỐ ĐỊNH
   giống nhau cho mọi <select> — trình duyệt tự hiện "..." nếu chữ dài hơn khung — để các ô xếp thành
   lưới đều, gọn, xuống dòng có quy luật thay vì ngẫu nhiên theo độ dài chữ. Không đổi <input type=
   "text"/"search"> (vẫn cần rộng để gõ được nội dung dài như địa chỉ). */
.toolbar-search select.f-input { width: 180px; min-width: 180px; flex: 0 0 auto; }
.toolbar-search .f-input-search { flex: 1 1 240px; min-width: 200px; }
.toolbar-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Trên desktop các nút trong "toolbar-more" hiện bình thường ngay trong hàng — chỉ mobile mới gom
   thành menu xổ xuống (xem @media max-width:900px bên dưới), nên ở đây không tạo box riêng. */
.toolbar-more { display: contents; }
/* Bản 254: theo yêu cầu (kèm ảnh tham khảo giao diện AppSheet cũ) — trên MÀN RỘNG (>900px), các nút
   Import/Xuất/Sửa nhanh trong "toolbar-more" thu gọn thành Ô VUÔNG CHỈ ICON (giống cụm icon cạnh ô
   tìm kiếm ở ảnh tham khảo) thay vì ô dài kèm chữ như trước — gọn hơn nhiều, đỡ chiếm ngang khi có
   nhiều nút. Tên nút vẫn còn NGUYÊN trong DOM (thẻ <span class="act-label">, xem title= để đọc khi
   rê chuột) — chỉ ẨN chữ bằng CSS, không xóa khỏi HTML, nên không ảnh hưởng gì tới menu "⋮" xổ
   xuống trên di động (nơi vẫn cần hiện đủ chữ vì không có tooltip khi chạm). */
@media (min-width: 901px) {
    .toolbar-actions .toolbar-more .act {
        min-width: 38px; width: 38px; height: 38px; padding: 0; border-radius: 8px;
        flex-direction: row; justify-content: center;
    }
    .toolbar-actions .toolbar-more .act-label { display: none; }
}

/* ---------- Bảng ---------- */
.table-wrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; }
.table th {
    text-align: left; font-size: 12px; color: var(--muted);
    border-bottom: 2px solid var(--line); padding: 8px 10px; white-space: nowrap;
    background: #fafbfd;
}
.table th.tr { text-align: right; } .table th.tc { text-align: center; }
.table td { border-bottom: 1px solid var(--line); padding: 8px 10px; vertical-align: middle; }
.table.small th, .table.small td { padding: 5px 8px; font-size: 12px; }
.table tbody tr:hover { background: #f6f9ff; }
.row-link { cursor: pointer; }
.empty { text-align: center; color: var(--muted); padding: 26px !important; }
.row-actions { white-space: nowrap; }
.thumb { max-height: 42px; max-width: 70px; border-radius: 4px; border: 1px solid var(--line); }
.anh-hoa-don-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.anh-hoa-don-slot { border: 1px dashed var(--line); border-radius: var(--radius); padding: 8px; text-align: center; }
.anh-hoa-don-slot .thumb { max-height: 90px; max-width: 100%; display: block; margin: 0 auto 6px; }
.anh-hoa-don-slot .f-check { justify-content: center; margin-bottom: 6px; font-size: 12px; }
.anh-hoa-don-slot .f-input { font-size: 11px; }
.detail-photos { display: flex; flex-wrap: wrap; gap: 10px; }
.detail-photos a img { max-height: 110px; max-width: 140px; border-radius: var(--radius); border: 1px solid var(--line); object-fit: cover; }

/* Bảng key-value chi tiết */
.kv { width: 100%; border-collapse: collapse; }
.kv th {
    text-align: left; color: var(--muted); font-weight: 500;
    width: 190px; padding: 7px 10px 7px 0; vertical-align: top; font-size: 13px;
}
.kv td { padding: 7px 0; border-bottom: 1px dashed var(--line); }
.kv tr:last-child td { border-bottom: 0; }
/* Dòng "PDF"/"Excel" kiểu AppSheet: tên file bên trái, icon xem nhỏ bên phải, cùng 1 dòng */
.kv-file { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--text, #1a1a1a); text-decoration: none; }
.kv-file:hover { color: var(--blue); }
.kv-file .kv-file-ico { flex: none; font-size: 15px; }
.detail-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 32px; }

/* ---------- Badge ---------- */
.badge {
    display: inline-block; padding: 3px 9px; border-radius: 999px;
    font-size: 11.5px; font-weight: 700; white-space: nowrap;
}
.b-gray { background: #eef1f5; color: #475569; }
.b-blue { background: #dbeafe; color: var(--blue-d); }
.b-green { background: #dcfce7; color: #15803d; }
.b-red { background: #fee2e2; color: var(--red); }
.b-indigo { background: #e0e7ff; color: var(--indigo); }
.b-orange { background: #ffedd5; color: var(--orange); }

/* ---------- Tiến trình đơn hàng (bản 281) — thanh icon ngang theo mốc trạng thái ở trang Chi
   tiết Đơn ngoài (donHangTimelineSteps() ở core/helpers.php). Cuộn ngang trên di động, không vỡ
   layout khi có 5 mốc (nhánh hậu mãi). ---------- */
.order-timeline { display: flex; align-items: flex-start; overflow-x: auto; padding: 8px 2px 12px; margin-bottom: 14px; }
.ot-step { display: flex; flex-direction: column; align-items: center; flex: 1 1 0; min-width: 82px; position: relative; }
.ot-line { position: absolute; top: 19px; left: -50%; width: 100%; height: 2px; background: var(--line); z-index: 0; }
.ot-step:first-child .ot-line { display: none; }
.ot-circle {
    width: 38px; height: 38px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    font-size: 17px; line-height: 1; background: var(--card); border: 2px solid var(--line); color: var(--muted);
    position: relative; z-index: 1;
}
.ot-step.done .ot-circle { background: var(--green); border-color: var(--green); color: #fff; }
.ot-step.done .ot-line { background: var(--green); }
.ot-step.current .ot-circle { background: #fff; border-color: var(--blue); color: var(--green); box-shadow: 0 0 0 3px rgba(37,99,235,.18); }
.ot-step.error .ot-circle { background: #fff; border-color: var(--red); color: var(--red); box-shadow: 0 0 0 3px rgba(220,38,38,.15); }
.ot-step.wait .ot-circle { background: #fff; border-color: var(--orange); color: var(--orange); box-shadow: 0 0 0 3px rgba(217,119,6,.15); }
.ot-label { font-size: 11.5px; text-align: center; margin-top: 6px; color: var(--text); font-weight: 600; max-width: 96px; }
.ot-step.pending .ot-label { color: var(--muted); font-weight: 500; }
.ot-sub { font-size: 10.5px; color: var(--muted); text-align: center; margin-top: 2px; }


/* ---- Modal popup dùng chung (bản 185 — "Chuyển người duyệt" ở Đơn từ) ---- */
.modal-overlay {
    display: none; position: fixed; inset: 0; background: rgba(15, 23, 42, .45);
    z-index: 1000; align-items: center; justify-content: center; padding: 16px;
}
.modal-overlay.open { display: flex; }
.modal-box {
    background: #fff; border-radius: 12px; width: 100%; max-width: 440px;
    padding: 20px; box-shadow: 0 20px 50px rgba(0,0,0,.25);
}
.modal-box h3 { margin: 0 0 14px; font-size: 17px; }
.modal-close {
    position: absolute; top: 14px; right: 16px; border: 0; background: none;
    font-size: 18px; cursor: pointer; color: var(--muted, #64748b);
}
.modal-box { position: relative; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
/* Bản 313: Modal xem PDF (theo yêu cầu "bổ sung KPI xem view PDF") — dùng chung khung .modal-overlay/
   .modal-box có sẵn ở trên, chỉ mở rộng riêng cho modal PDF vì nội dung là iframe cần nhiều diện
   tích hơn hẳn modal form thông thường (max-width mặc định 440px quá chật để đọc PDF). */
.modal-box-pdf { max-width: 900px; width: 92vw; height: 88vh; display: flex; flex-direction: column; }
.pdf-viewer-frame {
    flex: 1 1 auto; width: 100%; min-height: 0; border: 1px solid var(--line); border-radius: 8px;
    background: #525659; /* nền xám giống trình xem PDF gốc trong lúc iframe đang tải trang */
}
@media (max-width: 900px) {
    /* Trên di động không đủ chỗ chừa margin như desktop — cho modal PDF gần kín màn hình để vùng
       đọc thật sự tối đa (chữ trong PDF vốn đã nhỏ, thu hẹp thêm sẽ rất khó đọc trên điện thoại). */
    .modal-box-pdf { width: 96vw; height: 92vh; padding: 12px; }
}
.count-badge {
    display: inline-block; background: #eef1f5; color: var(--muted);
    border-radius: 6px; padding: 2px 9px; font-size: 13px; font-weight: 700;
}

/* ---------- Form ---------- */
.f-label { display: block; font-size: 12.5px; font-weight: 600; color: #475569; margin: 0 0 4px; }
.f-input {
    width: 100%; padding: 8px 10px; font-size: 13.5px;
    border: 1px solid #cfd6e0; border-radius: 8px; background: #fff; color: var(--text);
}
.f-input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,.13); }
textarea.f-input { resize: vertical; }
.f-check { display: flex; align-items: center; gap: 7px; padding: 6px 0; font-weight: 500; cursor: pointer; }
.f-hint { margin-top: 6px; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px 16px; }
.f-wide { grid-column: 1 / -1; }

/* ---------- Layout "side by side" kiểu AppSheet: nhãn cố định bên trái, ô nhập bên phải ---------- */
.form-rows { display: flex; flex-direction: column; gap: 2px; }
.form-rows .f-group {
    display: flex; align-items: center; gap: 16px;
    padding: 9px 0; border-bottom: 1px solid #f0f2f5;
}
.form-rows .f-group:last-child { border-bottom: 0; }
.form-rows .f-label {
    flex: 0 0 150px; margin: 0; font-size: 13px; font-weight: 600; color: #475569;
}
.form-rows .f-group > :not(.f-label) { flex: 1; min-width: 0; }
.form-rows .f-group > .f-label + * { flex: 1; }
/* Ô nhập trong layout này giữ nguyên khung viền như bình thường, chỉ đổi hướng bố cục nhãn/ô */
.form-rows .f-hint, .form-rows small { flex-basis: 100%; margin-left: 166px; }
.form-rows .f-group-block { align-items: flex-start; }
.form-rows .f-group-block > .f-label { padding-top: 6px; }

/* ---------- "Cách soạn mẫu" — bảng mã chèn cho Mẫu in / báo giá ---------- */
.ma-chen-box { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; margin-bottom: 14px; }
.ma-chen-box summary { cursor: pointer; font-weight: 700; font-size: 14px; }
.ma-chen-box summary::marker { color: var(--blue); }
.ma-chen-nhom { display: grid; grid-template-columns: 130px 1fr; gap: 10px 16px; margin-top: 12px; }
.ma-chen-nhom + .ma-chen-tieude { margin-top: 16px; }
.ma-chen-tieude { font-weight: 700; font-size: 12.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .3px;
    margin: 16px 0 6px; padding-top: 12px; border-top: 1px dashed var(--line); }
.ma-chen-nhom .mc-label { font-weight: 600; color: #334155; padding-top: 3px; }
.ma-chen-nhom .mc-codes { display: flex; flex-wrap: wrap; gap: 6px 8px; }
.ma-chen-nhom code {
    background: #fff5f2; border: 1px solid #f1c9bd; color: #9a3f24; border-radius: 6px;
    padding: 3px 9px; font-size: 12.5px; font-family: ui-monospace, Consolas, monospace;
}

/* ---------- Chọn khách hàng (danh bạ hoặc khai báo mới) ---------- */
.kh-block { margin-bottom: 16px; }
.kh-hidden { display: none !important; }
.kh-search-inline { display: flex; gap: 8px; flex-wrap: wrap; }
.kh-search-inline .f-input { flex: 1; min-width: 200px; }
.kh-search-inline .btn { flex: 0 0 auto; white-space: nowrap; }
.kh-picked {
    display: flex; align-items: flex-start; gap: 12px;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: #f0f7ff; padding: 12px 14px; margin-bottom: 4px;
}
.kh-picked-ico { font-size: 22px; line-height: 1.3; }
.kh-picked-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.kh-picked-info b { font-size: 14.5px; }
.kh-picked-info .muted { font-size: 12.5px; }
#khNewBlock { margin-top: 4px; }

/* ---------- Chip chọn nhanh Đơn vị vận chuyển (lọc theo Loại vận đơn) ---------- */
.dvvc-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.dvvc-chip {
    border: 1px solid var(--line); background: #fff; color: var(--text);
    border-radius: 999px; padding: 5px 12px; font-size: 12.5px; font-weight: 700;
    cursor: pointer;
}
.dvvc-chip:hover { border-color: var(--blue); color: var(--blue); }
.dvvc-chip.active { background: var(--blue); border-color: var(--blue); color: #fff; }
.form-actions { margin-top: 18px; display: flex; gap: 10px; }
.form-section {
    margin: 22px 0 10px; padding-bottom: 6px;
    border-bottom: 2px solid var(--line); color: var(--blue-d); font-size: 14px;
}
.filter-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: end; }
.filter-row .f-group { min-width: 150px; }
.map-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px 14px; }
.inline-form { display: inline-flex; gap: 6px; align-items: center; }
.inline-adjust { display: flex; gap: 6px; align-items: center; }

/* ---------- Flash ---------- */
.alert { padding: 11px 14px; border-radius: 8px; margin-bottom: 14px; font-weight: 500; }
.alert-success { background: #dcfce7; color: #166534; }
.alert-danger { background: #fee2e2; color: #991b1b; }
.alert-warning { background: #fef3c7; color: #92400e; }

/* ---------- Trang danh sách: cây tháng ---------- */
.split { display: flex; gap: 14px; align-items: flex-start; }
.month-tree { width: 230px; flex: 0 0 230px; padding: 8px; max-height: 76vh; overflow-y: auto; }
.list-card { flex: 1; min-width: 0; }
.mt-item {
    display: flex; justify-content: flex-start; align-items: center; gap: 8px;
    padding: 7px 9px; border-radius: 7px; color: var(--text); font-weight: 600; font-size: 12.5px;
}
.mt-item:hover { background: #f1f5fd; text-decoration: none; }
.mt-item.active { background: var(--blue); color: #fff; }
.mt-item.active .mt-label { color: #fff; }
.mt-item.active .mt-badge { background: rgba(255,255,255,.22); color: #fff; }
/* Bản 263: theo yêu cầu (kèm ảnh mẫu AppSheet) — badge (số tiền/số lượng) đứng SÁT ngay sau nhãn
   Tháng/Ngày thay vì bị đẩy tuốt ra sát mép phải khung 230px (hành vi cũ do .mt-item dùng
   `justify-content: space-between` + .mt-label kéo giãn `flex: 1 1 auto` chiếm hết khoảng trống
   còn lại, đẩy badge ra mép ngoài dù chữ nhãn rất ngắn — VD "2026-07" — tạo khoảng trắng chết rất
   rộng y hệt ảnh khoanh đỏ gửi kèm). Nay đổi `justify-content: flex-start` (ở trên) + bỏ hẳn
   flex-grow của nhãn (`flex: 0 1 auto` dưới đây) — 2 phần tử chỉ chiếm đúng phần chữ của mình rồi
   dừng, cách nhau đúng 1 khoảng `gap` cố định (8px), giống hệt tinh thần bản mẫu AppSheet. Vì mỗi
   cấp (Tháng "YYYY-MM" / Ngày "DD/MM/YYYY") đều có độ dài chữ ĐỀU NHAU giữa các dòng, các badge vẫn
   tự nhiên thẳng hàng như 1 cột dù không còn ép bằng flex-grow/space-between nữa. */
.mt-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; min-width: 0; color: #1d4ed8; font-weight: 700; }
.mt-badge {
    background: #eef1f5; color: var(--text); border-radius: 6px; flex: 0 0 auto;
    padding: 1px 6px; font-size: 11px; font-weight: 700; white-space: nowrap;
}
.mt-badge.neg { background: #fee2e2; color: var(--red); }
.mt-item.active .mt-badge { color: #fff; }

/* ---- Mũi tên mở/thu cây Tháng — bấm TÊN THÁNG để mở (điều hướng, xổ Ngày); bấm MŨI TÊN chỉ
   THU/MỞ tại chỗ (JS, không điều hướng) — giữ nguyên tháng đang chọn, không quay về "All" ---- */
.mt-month-row { display: flex; align-items: center; gap: 2px; }
.mt-arrow {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; border-radius: 4px; color: inherit; opacity: .75; cursor: pointer;
    border: 0; background: none; padding: 0; font: inherit;
}
.mt-arrow:hover { background: rgba(37,99,235,.12); opacity: 1; }
.mt-item.active .mt-arrow:hover { background: rgba(255,255,255,.22); }

/* Đang thu gọn bằng JS (giữ nguyên tháng đang chọn, chỉ ẩn cây Ngày) */
.mt-item.mt-collapsed + .mt-sub { display: none; }

/* ---- Cây NGÀY bung dưới tháng đang mở (giao diện admin) ---- */
.mt-sub { margin: 2px 0 6px 0; border-left: 2px solid #e5e9f0; padding-left: 6px; }
/* Bản 267: theo yêu cầu (kèm ảnh mẫu AppSheet) — chữ Ngày (VD "08/8/2026") thụt vào THẲNG HÀNG dưới
   chữ Tháng phía trên (VD "2026-08"), không lệch sang trái như trước. CHỈ áp riêng cho cây Tháng/
   Ngày của Đơn ngoài (`views/donhang/list.php`, nhận diện qua class `.mt-month` — nhãn Tháng ở đây
   dùng nút mũi tên `.mt-arrow` RIÊNG rộng 18px, khác kiểu mũi tên ▾/▸ gõ thẳng vào chung 1 chữ với
   nhãn Tháng như ở `views/generic/list.php`, VD Chi tiết công nợ) — 2 nơi dùng CHUNG class `.mt-sub`
   nhưng lệch khoảng cách mũi tên khác nhau nên KHÔNG thể chỉnh 1 giá trị `padding-left` chung cho cả
   2 mà thẳng hàng đúng cả 2 nơi được (đã thử, tăng chung sẽ làm bên Chi tiết công nợ bị thụt QUÁ SÂU,
   lệch theo chiều ngược lại) — chỉnh riêng qua bộ chọn `.mt-item.mt-month + .mt-sub` (chỉ khớp đúng
   khối Ngày đứng NGAY SAU 1 mục Tháng kiểu Đơn ngoài) để không đụng tới nơi khác đang dùng ổn.
   19px = padding .mt-item (9px) + bề rộng .mt-arrow (18px) + khoảng cách trong .mt-month-row (2px)
   − border-left của .mt-sub (2px) − padding riêng của .mt-item.mt-day (8px) = khớp đúng vị trí chữ
   nhãn Tháng phía trên. */
.mt-item.mt-month + .mt-sub { padding-left: 19px; }
.mt-item.mt-day { font-weight: 500; font-size: 12px; padding: 5px 8px; }
.mt-item.mt-day .mt-badge { font-size: 10.5px; }
.mt-item.mt-open { background: #eef2ff; }
.mt-item.mt-open.active { background: var(--blue); }

/* ---- Dòng tiêu đề nhóm NHÂN VIÊN trong bảng đơn hàng ---- */
.table tbody tr.grp-row td {
    background: #f1f5f9; border-top: 2px solid #cbd5e1;
    padding: 7px 10px; font-size: 12.5px;
}
.table tbody tr.grp-row:hover td { background: #f1f5f9; }
.grp-name { font-weight: 700; margin-right: 10px; }
.grp-name-ico { margin-right: 6px; }
.grp-sum {
    background: #dbeafe; color: #1d4ed8; border-radius: 6px;
    padding: 1px 7px; font-size: 11.5px; font-weight: 700; margin-right: 8px;
}
.grp-sum.neg { background: #fee2e2; color: var(--red); }
.list-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; flex-wrap: wrap; gap: 8px; }
.bulk-bar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    background: #eff6ff; border: 1px solid #bfdbfe; border-radius: var(--radius);
    padding: 10px 14px; margin-bottom: 10px;
}
.bulk-bar .f-input { width: auto; min-width: 160px; }
.bulk-bar #bulkApply:disabled { opacity: .5; cursor: not-allowed; }
.pagination { display: flex; gap: 5px; }
.pg {
    display: inline-block; min-width: 30px; text-align: center; padding: 5px 8px;
    border: 1px solid var(--line); border-radius: 7px; color: var(--text); font-weight: 600; font-size: 12.5px;
}
.pg:hover { text-decoration: none; border-color: var(--blue); color: var(--blue); }
.pg.active { background: var(--blue); border-color: var(--blue); color: #fff; }
.pg-dots { align-self: center; color: var(--muted); }

/* ---------- Trang chủ ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; margin-bottom: 18px; }
.stat { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.stat-label { color: var(--muted); font-size: 12px; font-weight: 600; margin-bottom: 5px; }
.stat-value { font-size: 19px; font-weight: 800; }
.home-group { margin-bottom: 22px; }
/* Bản 195: theo yêu cầu, riêng khối thẻ chức năng Trang chủ (tiêu đề nhóm + tên từng thẻ) dùng lại
   font hệ thống của Apple (-apple-system/San Francisco — nét chữ gọn, đậm đẹp hơn trên iPhone/Mac,
   đúng như ảnh mẫu gửi kèm) — CHỈ áp cho đúng 2 lớp dưới đây, KHÔNG đụng tới font chung của toàn bộ
   ứng dụng (body vẫn giữ Roboto, Arial, sans-serif như đã đổi trước đó). Máy không phải Apple (Windows/
   Android) tự động rơi xuống các font hệ thống tương đương trong chuỗi fallback, không lỗi gì. */
.home-group-title, .home-card {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
}
.home-group-title {
    font-weight: 700; font-size: 17px; margin-bottom: 12px; color: #0f172a;
    display: flex; align-items: center; gap: 8px;
}
.home-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; }
.home-card {
    display: flex; align-items: center; gap: 14px; position: relative;
    background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 16px; color: var(--text); font-weight: 800; font-size: 15.5px; letter-spacing: .1px;
}
.home-card:hover { border-color: var(--blue); text-decoration: none; box-shadow: 0 2px 8px rgba(37,99,235,.10); }
/* Bản 227: hiện tên đầy đủ dạng tooltip khi di chuột tới thẻ chức năng ở Trang chủ — theo yêu cầu
   (tham khảo ảnh chụp hệ thống cũ: tooltip đen nhỏ nổi lên khi hover). Dùng chung đúng cơ chế data-tip
   đã có cho sidebar thu gọn (assets/css/style.css dòng ~134), chỉ khác là áp dụng LUÔN — không cần
   điều kiện body.sidebar-collapsed — vì thẻ Trang chủ không có chế độ thu gọn nào để phụ thuộc vào.
   Tooltip hiện PHÍA TRÊN thẻ (không phải bên phải như sidebar) để không bị tràn ra ngoài lưới nhiều cột. */
.home-card[data-tip]:hover::after {
    content: attr(data-tip);
    position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%);
    margin-bottom: 8px; background: #111827; color: #fff; padding: 5px 10px;
    border-radius: 6px; font-size: 12.5px; font-weight: 600; white-space: nowrap; z-index: 30;
    box-shadow: 0 6px 16px rgba(0,0,0,.28); pointer-events: none;
}
.hc-ico { font-size: 27px; }
.hc-badge {
    position: absolute; top: 8px; right: 8px;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 20px; height: 20px; padding: 0 5px;
    background: #e5484d; color: #fff; font-size: 11px; font-weight: 700;
    border-radius: 999px; line-height: 1;
}

/* ---------- Chi tiết đơn: hàng nút thao tác ---------- */
.action-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.act {
    display: inline-flex; flex-direction: column; align-items: center; gap: 4px;
    min-width: 84px; padding: 9px 10px; border: 1px solid var(--line); border-radius: 9px;
    background: #fff; color: var(--text); font-size: 11.5px; font-weight: 700; cursor: pointer;
}
.act:hover { border-color: var(--blue); color: var(--blue); text-decoration: none; }
.act-ico { font-size: 17px; }
.act-danger:hover { border-color: var(--red); color: var(--red); }

/* ---------- Bar chart CSS ---------- */
.bar-wrap { display: flex; align-items: center; gap: 8px; }
.bar { height: 16px; background: var(--blue); border-radius: 3px; min-width: 3px; }
.bar-val { font-weight: 700; font-size: 12.5px; }

/* ---------- Phân quyền ---------- */
.perm-table td, .perm-table th { padding: 6px 10px; }
.perm-group td { background: #f1f5fd; font-weight: 700; color: var(--blue-d); font-size: 12.5px; }
.perm-table input[type="checkbox"] { width: 16px; height: 16px; }

/* ---------- Đăng nhập ---------- */
.login-body {
    display: flex; align-items: center; justify-content: center;
    min-height: 100vh; min-height: 100dvh;
    padding: 20px calc(20px + env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-left));
    background: linear-gradient(135deg, #101828 0%, #1e3a8a 100%);
}
.login-box {
    background: #fff; border-radius: 14px; padding: 30px 28px;
    width: 100%; max-width: 380px; box-shadow: 0 18px 50px rgba(0,0,0,.35);
}
.login-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.login-badge {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 9px; flex: 0 0 auto;
    background: var(--blue); color: #fff; font-size: 18px; font-weight: 800;
}
.login-title { font-size: 17px; font-weight: 800; }
.login-sub { color: var(--muted); margin: 0 0 18px; font-size: 13px; }
.login-box .f-input { margin-bottom: 13px; font-size: 16px; min-height: 44px; }
.login-box .f-label { margin-top: 2px; }
.login-box .btn-block { min-height: 46px; font-size: 15px; }
.login-divider { display: flex; align-items: center; gap: 10px; margin: 16px 0; color: var(--muted); font-size: 12.5px; }
.login-divider::before, .login-divider::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.btn-google {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    border: 1px solid var(--line); background: #fff; color: var(--text);
    min-height: 46px; font-size: 14.5px;
}
.btn-google:hover { background: #f8fafc; }
.login-note { text-align: center; color: var(--muted); font-size: 12px; margin: 12px 0 0; }
@media (max-width: 420px) {
    .login-box { padding: 24px 20px; border-radius: 12px; }
}

/* ---------- In ấn & responsive ---------- */
@media print {
    .sidebar, .topbar, .toolbar, .btn, .month-tree, .action-row, .row-actions, .bottomnav { display: none !important; }
    .content { padding: 0; }
    .card { border: 0; }
}
.only-mobile { display: none; }
.only-mobile-flex { display: none; }
.sidebar-mask { display: none; }
.bottomnav { display: none; }
.sidebar-user { display: none; }

@media (max-width: 900px) {
    .only-mobile { display: inline-block; }
    .only-mobile-flex { display: flex; }
    .hide-mobile { display: none !important; }
    .sidebar {
        position: fixed; left: -250px; z-index: 40; transition: left .18s ease;
        box-shadow: 4px 0 18px rgba(0,0,0,.3);
        display: flex; flex-direction: column;
        width: 250px !important; flex: 0 0 250px !important;
    }
    /* Trên di động luôn hiện đầy đủ menu, không áp trạng thái thu gọn của desktop */
    body.sidebar-collapsed .brand-text,
    body.sidebar-collapsed .ni-label { display: inline; }
    body.sidebar-collapsed .nav-group { display: block; }
    /* Trên di động KHÔNG phải chế độ chỉ-icon (đó là hành vi riêng của desktop) -> trả accordion về
       đúng trạng thái đóng/mở bình thường thay vì luôn hiện hết như override chỉ-icon ở trên. */
    body.sidebar-collapsed .nav-group-body:not(.nav-group-body-pinned):not(.open) { display: none; }
    body.sidebar-collapsed .nav-item { justify-content: flex-start; padding: 10px 12px; margin: 3px 10px; }
    body.sidebar-collapsed .ni-arrow { display: block; }
    body.sidebar-collapsed .brand { justify-content: flex-start; padding: 16px 8px 14px 16px; }
    body.sidebar-collapsed .sidebar-user-collapsed { display: none; }
    .sidebar .nav { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; }
    body.sidebar-open .sidebar { left: 0; }
    body.sidebar-open .sidebar-mask {
        display: block; position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 35;
    }
    /* Khối user cuối sidebar (thay cụm user trên topbar) */
    .sidebar-user {
        display: block; border-top: 1px solid rgba(255,255,255,.12);
        padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    }
    .sidebar-user .su-name { font-weight: 700; font-size: 13px; margin-bottom: 6px; }
    .sidebar-user .su-name small { color: var(--muted); font-weight: 500; }
    .sidebar-user .su-links { display: flex; gap: 14px; }
    .sidebar-user .su-links a { color: #cfd8ea; font-size: 13px; text-decoration: none; }

    .split { flex-direction: column; }
    .detail-cols { grid-template-columns: 1fr; }
    .content { padding: 12px 12px calc(74px + env(safe-area-inset-bottom)); }
    .topbar { position: sticky; top: 0; z-index: 30; }

    /* ---- Danh sách Tháng / Ngày kiểu "đi sâu từng cấp" (giống app tham khảo):
       mỗi dòng full-width, số tiền hiện dạng pill xám bên phải, có mũi tên "›".
       Đang xem ngày của 1 tháng thì CHỈ hiện đúng list ngày đó (ẩn các tháng khác);
       đã chọn hẳn 1 ngày thì ẩn cả khối này, chỉ còn bảng đơn + nút "‹ quay lại". ---- */
    .month-tree {
        width: 100%; flex: none; max-height: none;
        display: block; padding: 0; overflow: visible;
    }
    .mt-section-label {
        padding: 12px 14px 6px; font-weight: 700; font-size: 15px; color: var(--text);
    }
    .mt-back {
        display: block; padding: 13px 14px; font-weight: 700; color: var(--blue);
        font-size: 15px; border-bottom: 1px solid var(--line); background: var(--card);
    }
    .month-tree .mt-item {
        display: flex; justify-content: space-between; align-items: center; gap: 8px;
        white-space: nowrap; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
        background: var(--card); padding: 14px 14px; font-size: 16px; font-weight: 700; color: var(--blue);
    }
    .month-tree .mt-item::after { content: '›'; color: #94a3b8; font-size: 20px; font-weight: 400; }
    /* Bản 269: sửa lỗi mục Tháng "mồ côi" không có mũi tên ">" trên di động (kèm ảnh mẫu AppSheet —
       MỌI dòng, kể cả dòng Tháng, đều có ">" bên phải). Trước đây có luật
       `.mt-item.mt-month::after { content:none }` với lý do "đã có mũi tên ▸/▾ thật riêng, khỏi lặp"
       — đúng cho DESKTOP (nút .mt-arrow thật vẫn hiện), nhưng SAI cho di động: đúng 2 dòng dưới đây
       lại ẩn hẳn `.mt-arrow` (chế độ "đi sâu từng cấp", không cần nút thu/mở tại chỗ) — hậu quả dòng
       Tháng trên di động KHÔNG CÒN mũi tên nào cả (không phải chevron ›, cũng chẳng còn ▸/▾), khác
       hẳn dòng "All"/dòng Ngày (vẫn có chevron), nhìn như dòng "cụt", không có gì báo hiệu bấm được.
       Bỏ hẳn luật ẩn chevron này trong phạm vi di động — dòng Tháng nay có lại đúng chevron › giống
       mọi dòng khác, khớp mẫu AppSheet. Desktop không đụng gì (rule gốc `.mt-item.mt-month::after`
       chỉ khai trong khối `@media max-width:900px` này, không có ở CSS gốc ngoài media query). */
    .month-tree .mt-item .mt-arrow { display: none; }         /* mobile đi sâu từng cấp, có nút "‹ Tháng" quay lại riêng, không cần bấm mũi tên để thu */
    .month-tree .mt-item .mt-month-row, .month-tree .mt-item .mt-label { flex: 1; }
    .month-tree .mt-item.active { background: #eef4ff; }
    .month-tree .mt-item.mt-all { color: var(--text); }
    .month-tree .mt-item.mt-day { font-size: 15px; font-weight: 500; color: var(--text); }
    .month-tree .mt-badge {
        background: #e9edf3; color: #475569; border-radius: 999px;
        padding: 4px 12px; font-size: 13px; font-weight: 700;
    }
    .month-tree .mt-sub { display: block; margin: 0; border: 0; padding: 0; }
    /* Đang ở list NGÀY của 1 tháng: ẩn nút All + các dòng tháng, chỉ còn list ngày */
    .month-tree.mt-drilled .mt-all,
    .month-tree.mt-drilled .mt-item.mt-month { display: none; }
    /* Đã chọn hẳn 1 ngày: ẩn toàn bộ khối Tháng/Ngày, chỉ còn bảng đơn */
    .split.mobile-drill-day .month-tree { display: none; }
    /* NGƯỢC LẠI: khi CHƯA đi hẳn vào 1 ngày cụ thể (đang ở mức Tháng/Ngày), ẩn hẳn khối danh sách đơn —
       app tham khảo (AppSheet) ở mức Tháng/Ngày CHỈ hiện cây Tháng/Ngày, không hiện kèm danh sách đơn
       bên dưới; chỉ khi bấm hẳn vào 1 ngày cụ thể mới sang màn hình danh sách đơn của ngày đó. Dùng
       class riêng (không phải ":not(.mobile-drill-day)") vì ở Đơn hàng ngoài/Đơn hàng Shopee, việc bung
       Ngày CHỈ dành cho admin — người dùng khác không có bước "Ngày" nên phải luôn hiện danh sách đơn
       ngay khi chọn Tháng, nếu dùng :not() sẽ ẩn mất danh sách đơn của họ hoàn toàn trên di động.
       Xem thêm view dùng chung pattern này: donhang/list.php (admin có bước Ngày, người dùng khác không). */
    .split.mobile-hide-list .list-card { display: none; }

    /* ---- Dòng tiêu đề nhóm (nhân viên / gian hàng): avatar tròn + tên đậm + pill tổng tiền ---- */
    /* Bản 311: theo yêu cầu (kèm ảnh chụp thật trên điện thoại) — dòng gom nhóm này dùng `colspan`
       phủ hết các cột; trên mobile khi chỉ còn vài cột hẹp hiện ra (checkbox, VC, CN, COD...),
       `table-layout: auto` của bảng cha lấy NỘI DUNG của dòng gom nhóm (tên NV dài + pill tổng tiền
       + số đơn) làm căn cứ tính chiều rộng cột, và dồn hết phần chiều rộng dư cần thiết vào ĐÚNG CỘT
       CHECKBOX ĐẦU TIÊN của bảng (cột hẹp nhất, không có nội dung dài nào khác để "chia sẻ" độ giãn)
       — tạo khoảng trắng rất lớn giữa checkbox và các cột dữ liệu thật ở TỪNG DÒNG ĐƠN bên dưới.
       Bản 311 (bản sửa): bản 311 gốc gắn thẳng `width:1px` + `display:flex` CÙNG 1 LÚC lên chính
       <td> — tưởng `width:1px` chỉ là "gợi ý" cho thuật toán auto-layout tính cột (như với ô thường),
       nhưng khi <td> đồng thời là flex container, trình duyệt lấy LUÔN `width:1px` làm chiều rộng
       THẬT của hộp flex (không giãn theo cột bảng nữa như ô thường) — toàn bộ nội dung flex bên
       trong (icon, TÊN nhân viên, pill tổng tiền, số đơn) bị ép co lại trong đúng 1px, và vì
       `.grp-name-txt` có `overflow:hidden` nên theo đặc tả Flexbox, "automatic minimum size" của nó
       tụt về 0 — TÊN NHÂN VIÊN BIẾN MẤT HOÀN TOÀN (chỉ còn icon + pill số tiền), người dùng báo lại
       kèm ảnh. Sửa đúng gốc rễ: TÁCH làm 2 lớp — <td> (ngoài) chỉ còn `width:1px` làm "gợi ý" cho
       auto-layout, KHÔNG còn display:flex nữa nên vẫn là hộp block bình thường → khi bảng dàn cột
       xong, <td> tự giãn về ĐÚNG chiều rộng cột thật (giống mọi ô khác, "width" chỉ là gợi ý chứ
       không phải chốt chặn cứng với box block); flex chuyển hẳn sang <div class="grp-row-inner">
       (mới, bọc trong <td> — xem views/donhang/list.php) luôn rộng 100% theo <td> cha thật, nên
       không còn bị co theo 1px nữa — tên nhân viên hiện lại đầy đủ, ĐÚNG 1 dòng kèm "…" nếu quá dài
       (giữ nguyên hành vi bản 310), đồng thời checkbox vẫn không bị kéo giãn (giữ đúng fix bản 311
       gốc). Đã kiểm thử lại bằng Playwright mobile 390px: xác nhận tên hiện đầy đủ + cột checkbox
       không còn bị giãn — cả 2 lỗi cùng hết, không lỗi nào tái diễn. */
    .table tbody tr.grp-row td {
        width: 1px;
        padding: 12px 14px; background: var(--card); border-top: 1px solid var(--line);
    }
    .grp-row-inner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; width: 100%; }
    .grp-name { display: flex; align-items: center; gap: 8px; font-size: 15px; min-width: 0; max-width: 100%; }
    /* Bản 310: theo yêu cầu (kèm ảnh chụp thật trên điện thoại) — tên nhân viên/khách hàng dài
       (VD "Nguyễn Thanh Tùng") trước đây tự XUỐNG DÒNG do `.grp-name` là flex + cha có
       `flex-wrap: wrap`, không có gì chặn chữ vỡ dòng — chiếm 2-3 dòng cao, dòng tiêu đề nhóm nhìn
       lệch xấu. Nay CHỈ riêng phần CHỮ tên (`.grp-name-txt`, tách khỏi icon để không cắt icon) gói
       gọn ĐÚNG 1 DÒNG, dài quá thì hiện "…" thay vì vỡ dòng — bấm giữ/xem chi tiết vẫn thấy đủ tên
       (không mất dữ liệu, chỉ cắt hiển thị). `gap:8px` ở trên đã đủ khoảng cách icon-chữ nên bỏ hẳn
       margin-right của icon (kế thừa từ bản desktop) để không bị cách đôi (gap + margin cộng dồn). */
    .grp-name-ico { margin-right: 0; flex: 0 0 auto; }
    .grp-name-txt {
        min-width: 0; max-width: 62vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .grp-sum { background: #e9edf3; color: #334155; border-radius: 999px; padding: 4px 12px; font-size: 13px; }

    /* Nút "+ Thêm" nổi kiểu FAB, dính góc dưới phải giống app tham khảo */
    .btn-fab {
        position: fixed; right: 16px; bottom: calc(72px + env(safe-area-inset-bottom));
        z-index: 25; width: 52px; height: 52px; padding: 0; border-radius: 50%;
        display: flex; align-items: center; justify-content: center;
        box-shadow: 0 6px 16px rgba(37,99,235,.4);
    }
    .btn-fab .fab-icon { font-size: 26px; line-height: 1; }
    .btn-fab .fab-label { display: none; }

    /* Bảng: cuộn ngang mượt, chữ vừa mắt */
    .table-wrap { -webkit-overflow-scrolling: touch; }
    .table th, .table td { white-space: nowrap; }

    /* Toolbar: ô tìm kiếm full width, nút to dễ bấm */
    .toolbar { flex-direction: column; align-items: stretch; }
    /* Bản 269: sửa lỗi "khoảng trắng rất lớn phía trên/dưới ô tìm kiếm" trên di động (kèm ảnh chụp
       thật trên điện thoại) — nguyên nhân: `.toolbar-search` (khai ở CSS gốc, dùng chung desktop) có
       `flex: 1 1 320px`, viết cho NGỮ CẢNH `.toolbar` xếp HÀNG NGANG (flex-direction mặc định: row) —
       ở đó 320px là flex-basis theo CHIỀU NGANG (giống min-width). Nhưng đúng 1 dòng phía trên vừa
       đổi `.toolbar` sang `flex-direction: column` cho di động — flex-basis của CON bên trong (`.toolbar-search`)
       nay tính theo CHIỀU DỌC (trục chính đổi hướng theo flex-direction của CHA), khiến 320px vô tình
       trở thành CHIỀU CAO TỐI THIỂU 320px cho cả khối form tìm kiếm (dù bên trong chỉ có 1 dòng input
       cao ~42px) — đúng thủ phạm gây khoảng trắng chết ở trên (phần "thừa" phía trước nội dung được
       căn giữa theo `align-items:center` của .toolbar-search) LẪN dưới (phần thừa còn lại) ô tìm kiếm,
       khớp chính xác kích thước khoảng trắng trong ảnh chụp gửi kèm. Ép lại `flex: 1 1 auto` (bỏ hẳn
       flex-basis cố định 320px) ngay tại đây — chỉ ảnh hưởng di động, desktop (không đổi flex-direction)
       giữ nguyên hành vi cũ 100%. Đã kiểm thử: dựng lại chính xác cấu trúc DOM+CSS thật trong file HTML
       cô lập, dùng `wkhtmltoimage --disable-smart-width` (bắt buộc để áp đúng media query theo đúng độ
       rộng khai báo, mặc định wkhtmltoimage tự ý chọn "smart width" khác) so sánh trực quan TRƯỚC/SAU —
       xác nhận khoảng trắng biến mất hoàn toàn, ô tìm kiếm co về đúng 1 dòng cao vừa đủ. */
    .toolbar-search { width: 100%; flex: 1 1 auto; }
    .toolbar-search .f-input { flex: 1; min-width: 0; }
    .toolbar-actions { justify-content: flex-start; }
    .btn { min-height: 40px; }
    .btn-sm { min-height: 34px; }
    .row-actions a, .row-actions button { padding: 8px; }

    /* ---- Dọn gọn toolbar di động kiểu AppSheet: ô tìm kiếm + icon Filter là đủ, mọi bộ lọc
       (Trạng thái/4 bộ đối soát/Ngày bán/Nhân viên/Khách hàng/khoảng tiền...) đều đã có sẵn trong
       panel Filter (bản 254, dùng chung cả desktop lẫn di động — bản 260 đã bỏ hẳn 5 select khỏi
       toolbar-search ở list.php trên MỌI cỡ màn hình, rule select bên dưới nay chỉ còn tác dụng
       phòng hờ nếu sau này có select khác lọt vào toolbar-search) nên trên MÀN HẸP ẩn nốt nút "Tìm"
       ở đây cho đỡ rối, chỉ còn đúng ô tìm kiếm + icon phễu; các nút phụ (Import/Xuất Excel/Sửa
       nhanh) gom vào menu "⋮" xổ xuống thay vì xếp thành nhiều hàng. ---- */
    .toolbar-search select.f-input,
    .toolbar-search > button[type="submit"] { display: none; }
    .toolbar-more {
        display: none; position: absolute; right: 0; top: calc(100% + 4px); z-index: 45;
        background: #fff; border: 1px solid var(--line); border-radius: 10px;
        box-shadow: 0 8px 20px rgba(0,0,0,.14); padding: 6px; min-width: 220px;
        flex-direction: column; gap: 2px;
    }
    .toolbar-more.open { display: flex; }
    .toolbar-more .btn, .toolbar-more .act {
        width: 100%; flex-direction: row; justify-content: flex-start; gap: 8px;
        border: 0; box-shadow: none; min-width: 0;
    }
    .toolbar-actions { position: relative; }
    .btn-icon-more { display: inline-flex; }

    /* Form: 1 cột, input 16px chống iOS tự zoom, nút Lưu dính đáy */
    .form-grid, .map-grid { grid-template-columns: 1fr; }
    .form-rows .f-group { flex-direction: column; align-items: stretch; gap: 4px; }
    .form-rows .f-label { flex-basis: auto; }
    .form-rows .f-hint, .form-rows small { margin-left: 0; }
    .f-input, select.f-input, textarea.f-input { font-size: 16px; min-height: 42px; }
    .form-actions {
        position: sticky; bottom: calc(64px + env(safe-area-inset-bottom));
        background: var(--bg); padding: 10px 0; margin: 8px -2px 0;
        border-top: 1px solid var(--line); z-index: 5; display: flex; gap: 8px;
    }
    .form-actions .btn { flex: 1; }

    /* ===== Bảng "Sản phẩm mua": chuyển thành thẻ (card) từng dòng, kiểu form 1 cột dễ chọn ===== */
    #spTable, #spTable tbody { display: block; width: 100%; }
    #spTable thead { display: none; }
    #spTable tr.sp-row {
        display: block; border: 1px solid var(--line); border-radius: 12px;
        padding: 12px 14px 10px; margin-bottom: 12px; background: var(--card);
        box-shadow: 0 1px 3px rgba(0,0,0,.04);
    }
    #spTable tbody { counter-reset: sp-line; }
    #spTable tr.sp-row { counter-increment: sp-line; }
    #spTable tr.sp-row::before {
        content: "Sản phẩm #" counter(sp-line);
        display: block; font-weight: 800; font-size: 12.5px; color: var(--primary);
        text-transform: uppercase; letter-spacing: .3px;
        margin: -2px -2px 10px; padding-bottom: 8px; border-bottom: 1px solid var(--line);
    }
    #spTable td {
        display: block; width: 100%; padding: 0 0 12px; border: 0; text-align: left !important;
    }
    #spTable td::before {
        content: attr(data-label); display: block; font-size: 11.5px; font-weight: 700;
        color: var(--muted); margin-bottom: 5px; text-transform: uppercase; letter-spacing: .3px;
    }
    #spTable td input { width: 100%; }
    #spTable td.sp-tt {
        background: #eff6ff; border-radius: 8px; padding: 10px 12px; font-size: 17px;
        font-weight: 800; color: var(--primary);
    }
    #spTable td.sp-tt::before { color: var(--primary); opacity: .75; }
    #spTable td.tc { padding-bottom: 0; }
    #spTable td.tc::before { content: none; }
    #spTable .sp-del {
        width: 100%; min-height: 42px; border-radius: 8px; background: #fef2f2;
        color: var(--red); border: 1px solid #fecaca; font-weight: 700; font-size: 13.5px;
    }
    #spTable .sp-del-txt { display: inline; }
    #btnAddSp { width: 100%; justify-content: center; min-height: 46px; font-weight: 700; margin-top: 4px; }

    /* Khối chọn khách hàng: xếp dọc, nút full width */
    .kh-picked { flex-direction: column; }
    .kh-picked #btnKhChange { width: 100%; }
    .kh-search-inline { flex-direction: column; }
    .kh-search-inline .f-input, .kh-search-inline .btn { width: 100%; min-width: 0; }

    /* Nút thao tác chi tiết đơn: lưới 2 cột, tap target chuẩn */
    .action-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
    .action-row .act, .action-row form { width: 100%; }
    .action-row form .act { width: 100%; justify-content: center; }
    .act { min-height: 42px; display: inline-flex; align-items: center; justify-content: center; }

    /* Thẻ thống kê 2 cột */
    .stat-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
    .stat-value { font-size: 16px; }

    /* ===== Bottom navigation kiểu app ===== */
    .bottomnav {
        display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
        background: var(--card); border-top: 1px solid var(--line);
        padding: 4px 2px calc(4px + env(safe-area-inset-bottom));
        justify-content: space-around; align-items: center;
    }
    .bn-item {
        display: flex; flex-direction: column; align-items: center; gap: 2px;
        font-size: 10.5px; font-weight: 600; color: var(--muted);
        text-decoration: none; background: none; border: 0; padding: 4px 8px;
        min-width: 58px; cursor: pointer; border-radius: 8px;
    }
    .bn-item.active { color: var(--primary); }
    .bn-ico { font-size: 19px; line-height: 1; }
    .bn-add {
        width: 46px; height: 46px; border-radius: 50%; background: var(--primary);
        color: #fff; font-size: 26px; font-weight: 700; display: flex;
        align-items: center; justify-content: center; text-decoration: none;
        margin-top: -18px; box-shadow: 0 4px 12px rgba(37,99,235,.45);
        border: 3px solid var(--bg);
    }
}
@media (max-width: 900px) {
    .filter-row .f-group { min-width: 0; flex: 1 1 140px; }
    .bulk-bar { flex-direction: column; align-items: stretch; }
    .bulk-bar .f-input, .bulk-bar #bulkApply { width: 100%; min-width: 0; }
}

@media (max-width: 560px) {
    .card { padding: 12px; }
    .card-head h2 { font-size: 16px; }
    .table.small th, .table.small td { font-size: 12px; }
    .kv th { width: 40%; font-size: 12.5px; }
}

/* ---- Đóng công nợ: phân biệt bằng màu nền cả dòng ----
   XANH = tiền RÚT VỀ từ Shopee (tiền vào tay quản lý gian hàng)
   ĐỎ   = tiền ĐÓNG công nợ cho công ty (tiền nộp ra) */
tr.row-money-in  { background: rgba(22, 163, 74, .07); box-shadow: inset 3px 0 0 var(--green); }
tr.row-money-out { background: rgba(220, 38, 38, .07); box-shadow: inset 3px 0 0 var(--red); }
tr.row-money-in:hover  { background: rgba(22, 163, 74, .14); }
tr.row-money-out:hover { background: rgba(220, 38, 38, .14); }
.badge-in  { background: rgba(22,163,74,.12); color: var(--green); border: 1px solid rgba(22,163,74,.35);
             padding: 2px 8px; border-radius: 999px; font-weight: 600; font-size: 12px; white-space: nowrap; }
.badge-out { background: rgba(220,38,38,.12); color: var(--red); border: 1px solid rgba(220,38,38,.35);
             padding: 2px 8px; border-radius: 999px; font-weight: 600; font-size: 12px; white-space: nowrap; }

/* ---- Thu chi: nền dòng theo trạng thái thanh toán ---- */
tr.row-tt-ok   { background: rgba(22, 163, 74, .06); box-shadow: inset 3px 0 0 var(--green); }
tr.row-tt-no   { background: rgba(220, 38, 38, .06); box-shadow: inset 3px 0 0 var(--red); }
tr.row-tt-warn { background: rgba(234, 88, 12, .06); box-shadow: inset 3px 0 0 var(--orange); }
tr.row-tt-ok:hover   { background: rgba(22, 163, 74, .13); }
tr.row-tt-no:hover   { background: rgba(220, 38, 38, .13); }
tr.row-tt-warn:hover { background: rgba(234, 88, 12, .13); }

/* ---- Bản 279: theo yêu cầu, bỏ nền/viền của badge màu ở 4 cột Trạng thái/Kho/Đơn vị vận
   chuyển/Phương thức thanh toán — CHỈ trong bảng danh sách đơn (list-card), không đụng tới nơi
   khác đang dùng chung 2 hàm badge_trang_thai_don()/badge_dm() (Dashboard, Chi tiết đơn, form).
   !important vì badge màu tùy chỉnh (Danh mục tra cứu) đặt background/border qua inline style,
   selector CSS thường không thắng được inline style. */
.list-card .table td[data-field="trang_thai"] .badge,
.list-card .table td[data-field="kho"] .badge,
.list-card .table td[data-field="don_vi_van_chuyen"] .badge,
.list-card .table td[data-field="phuong_thuc_tt"] .badge {
    background: transparent !important; border: none !important; padding-left: 0; padding-right: 0;
}

/* ---- Bấm tiêu đề cột để sắp xếp ---- */
.table thead th a.th-sort { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.table thead th a.th-sort:hover { color: var(--blue); }
.th-arrow { font-size: 10px; opacity: .35; }
a.th-sort:hover .th-arrow { opacity: .8; }
a.th-sort-on { color: var(--blue); font-weight: 700; }
a.th-sort-on .th-arrow { opacity: 1; }

/* ---- Bảng dài/rộng: cuộn ngay trong khung vừa màn hình ----
   Trước đây bảng dài bao nhiêu thì trang dài bấy nhiêu, muốn kéo ngang phải cuộn xuống tận
   cuối trang mới thấy thanh trượt. Nay khung bảng tự giới hạn theo chiều cao màn hình nên
   THANH TRƯỢT NGANG luôn nằm trong tầm nhìn, đồng thời tiêu đề cột dính lại khi cuộn dọc. */
.list-card .table-wrap {
    max-height: calc(100vh - 240px);
    min-height: 220px;
    overflow: auto;
    overscroll-behavior: contain;
}
.list-card .table thead th {
    position: sticky; top: 0; z-index: 3;
    background: transparent; border-bottom: none; box-shadow: none;
}
/* Thanh trượt dày hơn cho dễ bắt chuột */
.list-card .table-wrap::-webkit-scrollbar { height: 12px; width: 10px; }
.list-card .table-wrap::-webkit-scrollbar-thumb { background: #b9bfc9; border-radius: 6px; }
.list-card .table-wrap::-webkit-scrollbar-thumb:hover { background: #97a0ad; }
.list-card .table-wrap::-webkit-scrollbar-track { background: #f1f2f4; }

/* ---- Ô dữ liệu dài (tên sản phẩm, ghi chú...) hiện GỌN TRÊN 1 DÒNG, thừa chữ thì "..." ----
   Bấm/rê chuột vẫn xem được đủ nội dung qua title. Ô nào chủ động cần xuống dòng (VD cột
   Khách hàng có thêm số điện thoại bên dưới, dòng gộp nhóm) thì gắn class "td-wrap" để bỏ qua. */
.list-card .table td {
    max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.list-card .table td.td-wrap,
.list-card .table tr.grp-row td {
    max-width: none; overflow: visible; text-overflow: clip; white-space: normal;
}
/* Trong ô cho phép xuống dòng (td-wrap), TỪNG DÒNG con (VD mỗi tên sản phẩm) vẫn gọn 1 dòng
   riêng, thừa chữ thì "..." — ô cha xuống dòng được nhưng mỗi dòng con không tự vỡ dòng. */
.list-card .table td .sp-line {
    max-width: 320px; overflow: hidden;
    /* Bản 322: sửa lỗi "Còn lại" (bản 318) tính đúng nhưng KHÔNG HIỆN — tên sản phẩm dài chiếm hết
       320px rồi bị cắt "..." (ellipsis) trước khi tới phần chữ "— Còn lại: N" nối phía sau trong
       CÙNG 1 dòng text (white-space:nowrap trước đây áp cho cả dòng, ellipsis/overflow:hidden cắt
       mất luôn phần đuôi bất kể nó là gì). Đổi sang flex: tên sản phẩm (.sp-line-name) tự co lại +
       ellipsis RIÊNG nó, còn "Còn lại" (.sp-line-conlai) là ô ANH EM cố định độ rộng theo nội dung,
       LUÔN hiện đủ, không bao giờ bị cắt cùng tên sản phẩm nữa. */
    display: flex; align-items: baseline; gap: 4px;
}
.list-card .table td .sp-line .sp-line-name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto;
}
.list-card .table td .sp-line .sp-line-conlai {
    white-space: nowrap; flex: 0 0 auto;
}
/* Bản 263: cột "Khách hàng" ở danh sách Đơn ngoài rộng cố định 177px theo yêu cầu (trước tự do co
   giãn theo độ dài tên khách/SĐT). Áp cho cả <th> lẫn <td> để khớp nhau, không phụ thuộc
   table-layout auto có tôn trọng width của <th> hay không. */
.list-card .table th.col-khach,
.list-card .table td.col-khach {
    width: 177px; min-width: 177px; max-width: 177px;
}

@media (max-width: 900px) {
    /* Trên điện thoại để TRANG cuộn dọc bình thường (không lồng 2 vùng cuộn vào nhau — đây là
       nguyên nhân làm cả trang bị "đứng hình", không trượt được cả dọc lẫn ngang trên di động):
       bỏ giới hạn chiều cao + bỏ overscroll-behavior:contain của bản desktop, module bảng chỉ còn
       đúng 1 việc là cuộn NGANG khi bảng rộng hơn màn hình. */
    .list-card .table-wrap {
        max-height: none; min-height: 0; overflow-x: auto; overflow-y: visible;
        overscroll-behavior: auto; -webkit-overflow-scrolling: touch;
    }
    .list-card .table thead th { position: static; }
}

/* Dòng bấm được thì con trỏ phải là bàn tay — người dùng mới biết là bấm được */
.table tbody tr.row-link { cursor: pointer; }
.table tbody tr.row-link:hover { background: rgba(37, 99, 235, .05); }

/* Bản 303 (bản sửa): bản 302 gắn "::before" thẳng vào <tr class="row-xm"> — Chrome/Blink áp
   dụng "table fixup" cho NỘI DUNG SINH RA (generated content) nằm trực tiếp trong <tr> giống như
   với 1 ô con thường, tạo THÊM 1 CỘT ẢO đẩy lùi toàn bộ các cột thật sang phải 1 cột (lỗi người
   dùng báo lại, đã tái hiện + xác nhận qua ảnh chụp Chromium thật). Sửa: chuyển "::before" sang
   `td:first-child` — chọn đúng Ô ĐẦU TIÊN của dòng bằng CSS THUẦN TÚY (`:first-child`, không cần
   biết trước ô đó là checkbox/đối soát/ngày bán hay Khách hàng vì cột nào đang ẩn/hiện tùy cấu
   hình phân quyền cột), vì nội dung sinh ra NẰM TRONG 1 <td> có sẵn nên không còn bị tính là ô
   riêng nữa — không đẩy cột nào cả. Đã kiểm thử lại bằng Chromium thật (nhiều dòng, nhiều cột đầu
   khác nhau) — toàn bộ cột thẳng hàng đúng giữa dòng vàng và dòng thường. */
.table tbody tr.row-xm td { background: #fff6cf; }
.table tbody tr.row-xm:hover td { background: #ffefa8; }
.table tbody tr.row-xm > td:first-child { position: relative; overflow: visible; }
.table tbody tr.row-xm > td:first-child::before {
    content: "XM";
    position: absolute; top: -6px; left: -6px; z-index: 3;
    background: #dc2626; color: #fff; font-size: 10px; font-weight: 800;
    line-height: 1; padding: 3px 6px; border-radius: 4px 4px 4px 0;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .35); letter-spacing: .3px; pointer-events: none;
}

/* Tô NỀN CẢ DÒNG theo trạng thái (VD Đơn hàng Shopee) — nhạt hơn hẳn màu nền của badge để
   chữ trong dòng vẫn đọc rõ; giữ nguyên sắc thái khi rê chuột qua để không bị "mất màu". */
.table tbody tr.row-st-green  { background: #f0fdf4; }
.table tbody tr.row-st-red    { background: #fef2f2; }
.table tbody tr.row-st-orange { background: #fffbeb; }
.table tbody tr.row-st-indigo { background: #eef2ff; }
.table tbody tr.row-st-blue   { background: #eff6ff; }
.table tbody tr.row-st-gray   { background: transparent; }
.table tbody tr.row-st-green:hover  { background: #e2fbe9; }
.table tbody tr.row-st-red:hover    { background: #fde3e3; }
.table tbody tr.row-st-orange:hover { background: #fef3c7; }
.table tbody tr.row-st-indigo:hover { background: #e0e7ff; }
.table tbody tr.row-st-blue:hover   { background: #dbeafe; }

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 700px) { .grid-3 { grid-template-columns: 1fr; } }

/* Trang Cấu hình Cron: ép chắc chắn các khối luôn xếp DỌC — dùng !important để không thể bị
   ghi đè bởi bất kỳ CSS nào khác (kể cả style tiêm từ ngoài vào), phòng trường hợp có nguyên
   nhân nằm ngoài file này mà chưa xác định được. */
.cron-page-stack {
    display: flex !important; flex-direction: column !important; flex-wrap: nowrap !important;
    width: 100% !important;
}
.cron-page-stack > .card { flex: 0 0 auto !important; width: 100% !important; }

.multi-box { display:flex; flex-wrap:wrap; gap:4px 14px; max-height:180px; overflow:auto; padding:8px 10px; border:1px solid var(--border,#e5e7eb); border-radius:8px; }

/* ---------- Overlay "đang chạy" cho các thao tác lâu (đồng bộ Shopee, chạy cron thử...) ---------- */
.longrun-overlay {
    position: fixed; inset: 0; z-index: 9999;
    background: rgba(15, 23, 42, .55);
    display: flex; align-items: center; justify-content: center;
}
.longrun-box {
    background: #fff; border-radius: 12px; padding: 28px 32px;
    display: flex; flex-direction: column; align-items: center; gap: 14px;
    box-shadow: 0 12px 32px rgba(0,0,0,.25); max-width: 320px; text-align: center;
    font-size: 14.5px; color: #1f2937;
}
.longrun-spinner {
    width: 34px; height: 34px; border-radius: 50%;
    border: 4px solid #e5e7eb; border-top-color: #2563eb;
    animation: longrun-spin .8s linear infinite;
}
@keyframes longrun-spin { to { transform: rotate(360deg); } }

/* ---------- Sửa nhanh nhiều dòng trên danh sách Đơn hàng (kiểu bảng tính) ---------- */
.qe-bar {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 9px 14px; margin-bottom: 10px;
    background: #EFF6FF; border: 1px solid #BFDBFE; border-radius: 8px;
}
.qe-cell { position: relative; min-width: 96px; }
.qe-input {
    display: none; width: 100%; min-width: 90px; padding: 4px 7px;
    font-size: 13px; min-height: 30px;
}
select.qe-input { min-width: 130px; }
table.qe-editing .qe-view { display: none; }
table.qe-editing .qe-input { display: inline-block; }
table.qe-editing .qe-cell { background: #FFFBEB; }
@media (max-width: 720px) {
    .qe-bar { font-size: 13px; }
}

/* ---------- Giá niêm yết trong bảng Sản phẩm mua: hiển thị thuần, không còn sửa/mở khóa được ---------- */
input.sp-gny-plain {
    border: none; background: transparent; box-shadow: none;
    padding: 6px 2px; color: inherit; cursor: default; pointer-events: none;
    width: 100%; text-align: right;
}

/* ---------- Panel "Filter" kiểu AppSheet — donhang/list.php ---------- */
/* Bản 254: icon phễu nay LUÔN hiện (mọi cỡ màn hình), không còn giới hạn chỉ trên di động — panel
   trượt bên dưới (.filter-panel) vốn đã định vị kiểu overlay cố định, hoạt động đúng ở mọi độ rộng. */
.btn-icon-filter { border: 1px solid var(--line); background: #fff; border-radius: 8px;
    width: 38px; height: 38px; display: inline-flex; align-items: center; justify-content: center; flex: none; color: var(--text); }
.btn-icon-filter.has-active { border-color: var(--blue); color: var(--blue); background: #eef4ff; }
.btn-icon-more { border: 1px solid var(--line); background: #fff; border-radius: 8px;
    width: 38px; height: 38px; display: none; align-items: center; justify-content: center; flex: none; color: var(--text);
    font-size: 18px; font-weight: 700; line-height: 1; }
.filter-mask { display: none; position: fixed; inset: 0; background: rgba(16,24,40,.45); z-index: 70; }
.filter-panel {
    position: fixed; top: 0; right: 0; bottom: 0; width: 88%; max-width: 400px;
    background: #fff; z-index: 71; transform: translateX(100%); transition: transform .25s ease;
    display: flex; flex-direction: column; box-shadow: -6px 0 20px rgba(0,0,0,.18);
}
/* Bản 261: sửa lỗi "kéo xuống không được, không chọn được các mục lọc phía dưới" — .filter-panel
   là flex-column nhưng con TRỰC TIẾP của nó là <form> (không phải .filter-body), nên flex:1 +
   overflow-y:auto khai trên .filter-body hoàn toàn vô tác dụng: layout flex chỉ áp dụng cho CON
   TRỰC TIẾP của phần tử flex, form ở giữa không hề kế thừa lại các thuộc tính này. Form vốn là
   block-level, cao tự do theo đúng tổng chiều cao nội dung bên trong (toàn bộ filter-row cộng lại),
   tràn thẳng ra ngoài khung `.filter-panel` bị giới hạn cứng theo viewport (top:0;bottom:0) mà
   không có thanh cuộn nào — phần dưới (đặc biệt các dòng mới thêm ở bản 260/261: Trạng thái/4 bộ
   đối soát) bị lọt ra ngoài màn hình, không cách nào kéo/chạm tới được, dù DOM vẫn có đủ. Bọc lại
   đúng flex-column + full height cho CHÍNH form (con trực tiếp) để .filter-body (cháu) mới thật sự
   là flex item có thể co giãn (`flex:1; min-height:0`) và cuộn đúng bên trong đúng phần còn lại của
   khung, còn .filter-head/.filter-foot giữ cố định trên/dưới như thiết kế ban đầu. */
.filter-panel > form { display: flex; flex-direction: column; height: 100%; min-height: 0; }
body.filter-open .filter-mask { display: block; }
body.filter-open .filter-panel { transform: translateX(0); }
.filter-head { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.filter-head .fh-back { background: none; border: none; font-size: 20px; cursor: pointer; color: var(--text); padding: 4px; }
.filter-head .fh-title { font-size: 19px; font-weight: 700; flex: 1; }
.filter-body { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.filter-row { border-bottom: 1px solid var(--line); }
.filter-row-head { display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 15px 16px; cursor: pointer; font-size: 15px; -webkit-tap-highlight-color: transparent; }
.filter-row-head .fr-label { flex: 1; min-width: 0; }
.filter-row-head .fr-val { color: var(--blue); font-size: 12.5px; font-weight: 600; display: block; margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-row-head .fr-arrow { color: var(--muted); font-size: 13px; transition: transform .15s; flex: none; }
.filter-row.open .fr-arrow { transform: rotate(90deg); }
.filter-row-body { display: none; padding: 0 16px 16px; }
.filter-row.open .filter-row-body { display: block; }
.filter-row-body .f-input { width: 100%; margin-bottom: 8px; box-sizing: border-box; }
.filter-range { display: flex; gap: 8px; align-items: center; }
.filter-range .f-input { margin-bottom: 0; }
.filter-range span { color: var(--muted); font-size: 12.5px; flex: none; }
.filter-foot { display: flex; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--line);
    position: sticky; bottom: 0; background: #fff; }
.filter-foot button { flex: 1; }

/* ---------- 🧪 Thanh cam "Đang xem thử phân quyền" ---------- */
.xemthu-bar {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    flex-wrap: wrap; padding: 9px 16px; background: var(--orange); color: #fff;
    font-size: 12.5px; font-weight: 600; position: relative; z-index: 50;
    box-shadow: 0 2px 8px rgba(217,119,6,.35);
}
.xemthu-bar-txt { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.xemthu-bar-role, .xemthu-bar-admin { font-weight: 500; opacity: .92; }
.xemthu-bar-exit {
    background: #fff; color: var(--orange); border-radius: 999px; padding: 5px 14px;
    font-weight: 700; white-space: nowrap; flex: none;
}
.xemthu-bar-exit:hover { background: #fff7ed; text-decoration: none; }
@media (max-width: 700px) {
    .xemthu-bar { font-size: 12px; padding: 8px 12px; }
}

/* ---------- 📝 Soạn thảo định dạng (field 'richtext' — Thông báo / Nội quy, bản 194) ---------- */
.richtext-wrap { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.richtext-toolbar {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
    padding: 6px 8px; background: #f8fafc; border-bottom: 1px solid var(--line);
}
.rt-btn {
    border: 1px solid transparent; background: none; border-radius: 6px; cursor: pointer;
    width: 28px; height: 28px; font-size: 13px; color: var(--text); line-height: 1;
}
.rt-btn:hover { background: #e9edf3; border-color: var(--line); }
.rt-select { border: 1px solid var(--line); border-radius: 6px; font-size: 12.5px; padding: 4px 6px; background: #fff; }
.rt-color { border: none; width: 26px; height: 26px; padding: 0; border-radius: 6px; cursor: pointer; background: none; }
.rt-sep { width: 1px; height: 20px; background: var(--line); margin: 0 2px; }
/* Bản 240: ô soạn thảo nay chiếm trọn bề ngang form (xem 'f-wide' ở views/generic/form.php) nên nới
   luôn chiều cao cho tương xứng — bài Hướng dẫn thường dài, có ảnh chèn giữa các đoạn, khung 160px cũ
   phải cuộn liên tục mới đọc lại được đoạn vừa gõ. */
.richtext-body {
    min-height: 260px; max-height: 560px; overflow-y: auto; padding: 10px 12px;
    font-size: 13.5px; line-height: 1.6; outline: none;
}
/* Ảnh chèn trong lúc SOẠN: giới hạn bề ngang để 1 ảnh chụp màn hình cỡ lớn không đẩy khung soạn thảo
   cao vọt lên, vẫn bấm mở được cỡ gốc ở trang Chi tiết. */
.richtext-body img { max-width: 520px; }
.richtext-body:empty::before { content: 'Nhập nội dung...'; color: var(--muted); }
.richtext-body p { margin: 0 0 8px; }
.richtext-body ul, .richtext-body ol { margin: 0 0 8px; padding-left: 22px; }
.richtext-body blockquote { margin: 0 0 8px; padding: 4px 12px; border-left: 3px solid var(--blue); color: var(--muted); }
/* Kỹ thuật: KHÔNG dùng display:none — <textarea> vẫn cần "focusable" để trình duyệt tự cuộn/báo lỗi
   đúng ô khi field khai 'req' (bắt buộc) mà submit rỗng; display:none sẽ khiến trình duyệt báo lỗi
   console "not focusable" và im lặng không submit được, không rõ vì sao. */
.richtext-hidden { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; pointer-events: none; }
/* Vùng hiển thị lại nội dung đã lưu (trang Chi tiết) — cùng bộ margin/list như lúc soạn để không
   "nhảy" bố cục giữa soạn và xem. */
.richtext-view { font-size: 13.5px; line-height: 1.7; }
.richtext-view p { margin: 0 0 10px; }
.richtext-view ul, .richtext-view ol { margin: 0 0 10px; padding-left: 22px; }
.richtext-view blockquote { margin: 0 0 10px; padding: 6px 14px; border-left: 3px solid var(--blue); color: var(--muted); }
.richtext-view h2 { font-size: 17px; margin: 14px 0 8px; }
.richtext-view h3 { font-size: 15px; margin: 12px 0 6px; }
/* Bản 230: ảnh chèn qua nút "🖼 Chèn ảnh" — co vừa khung (không tràn ngang trang như ảnh gốc dán
   thẳng), bo góc + viền nhẹ + khoảng cách trên dưới, con trỏ "phóng to" gợi ý bấm để xem cỡ lớn. */
.richtext-view img, .richtext-body img {
    max-width: 100%; height: auto; display: block; margin: 8px 0;
    border: 1px solid var(--line); border-radius: 8px; cursor: zoom-in;
}
.rt-btn.rt-uploading { opacity: .5; pointer-events: none; }

/* ---------- 📣 Thông báo nội bộ: đối tượng/lịch gửi, đã xem (bản 194) ---------- */
.tb-daxem-badge {
    display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px;
    background: #eef2ff; color: var(--indigo); font-weight: 700; font-size: 12.5px;
}
.tb-daxem-list { max-width: 520px; }
.tb-daxem-list .kv th { width: 200px; }

/* ---------- 🖱 Menu chuột phải tối giản trên các dòng bảng ".row-link" (bản 207) ----------
 * Thay cho menu "Mở liên kết trong tab mới..." mà trình duyệt chỉ tự hiện với thẻ <a> thật —
 * dòng bảng dùng data-href + JS điều hướng (không phải <a> thật, vì <a> không phải con hợp lệ
 * của <tr>) nên bấm chuột phải tự dựng đúng 1 mục "Mở trong tab mới" tại vị trí con trỏ. */
.row-ctx-menu {
    position: fixed; z-index: 200; background: #fff; border: 1px solid var(--line);
    border-radius: 8px; box-shadow: 0 8px 24px rgba(16,24,40,.18); padding: 4px; min-width: 170px;
}
.row-ctx-item {
    display: block; width: 100%; text-align: left; padding: 8px 12px; border: none; background: none;
    border-radius: 6px; font-size: 13.5px; cursor: pointer; color: var(--text);
}
.row-ctx-item:hover { background: #f4f6fb; }

/* ---------- Bản 287: "Data Sản phẩm" — trình duyệt thư mục kiểu Google Drive ---------- */
.dsp-crumb { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; font-size: 14.5px; font-weight: 600; }
.dsp-crumb-link { color: var(--text); text-decoration: none; padding: 3px 6px; border-radius: 6px; }
.dsp-crumb-link:hover { background: #eef1f5; text-decoration: none; }
.dsp-crumb-sep { color: var(--muted); }

.dsp-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px;
    margin-bottom: 18px;
}
.dsp-grid-files { margin-top: 4px; }
.dsp-tile {
    position: relative; background: #fff; border: 1px solid var(--line); border-radius: 10px;
    padding: 14px 10px 10px; text-align: center; transition: box-shadow .15s, border-color .15s;
}
.dsp-tile:hover { box-shadow: 0 4px 14px rgba(16,24,40,.10); border-color: #cfd6e0; }
.dsp-tile-main { display: block; text-decoration: none; color: var(--text); }
.dsp-tile-icon { font-size: 34px; line-height: 1; margin-bottom: 8px; }
.dsp-tile-name {
    font-size: 12.5px; font-weight: 600; word-break: break-word; overflow: hidden;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; min-height: 32px;
}
.dsp-file-size { display: block; font-size: 10.5px; color: var(--muted); margin-top: 3px; font-weight: 500; }
.dsp-badge {
    display: inline-block; margin-top: 6px; font-size: 10px; font-weight: 700; padding: 2px 7px;
    border-radius: 999px;
}
.dsp-badge-chung { background: #e6f4ea; color: #1e7d34; }
.dsp-badge-rieng { background: #fdecea; color: #b3261e; }

.dsp-tile-menu { position: absolute; top: 4px; right: 4px; }
.dsp-dots {
    border: none; background: transparent; cursor: pointer; font-size: 16px; font-weight: 700;
    color: var(--muted); border-radius: 6px; padding: 2px 6px; line-height: 1;
}
.dsp-dots:hover { background: #eef1f5; color: var(--text); }
.dsp-dropdown {
    display: none; position: absolute; right: 0; top: 26px; background: #fff;
    border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 8px 24px rgba(16,24,40,.18);
    padding: 4px; min-width: 150px; z-index: 50; text-align: left;
}
.dsp-dropdown.open { display: block; }
.dsp-drop-item {
    display: block; width: 100%; text-align: left; padding: 8px 10px; border: none; background: none;
    border-radius: 6px; font-size: 13px; cursor: pointer; color: var(--text); text-decoration: none;
}
.dsp-drop-item:hover { background: #f4f6fb; text-decoration: none; }
.dsp-drop-danger { color: var(--red, #dc2626); }
.dsp-drop-danger:hover { background: #fdecea; }

/* ---------- Bản 289: "Data Sản phẩm" — chuyển Lưới/Danh sách + ảnh thu nhỏ thật + nhiều Kho ---------- */
.dsp-view-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; margin-left: 8px; }
.dsp-view-btn {
    border: none; background: #fff; padding: 7px 12px; font-size: 12.5px; font-weight: 600;
    cursor: pointer; color: var(--muted); border-right: 1px solid var(--line);
}
.dsp-view-btn:last-child { border-right: none; }
.dsp-view-btn.active { background: #eef1f5; color: var(--text); }
.dsp-view-btn:hover { background: #f4f6fb; }

/* Chế độ Danh sách ẩn theo mặc định — JS gắn class .che-do-danh-sach lên #dspViewContainer để đổi */
.dsp-view-container .dsp-mode-list { display: none; }
.dsp-view-container.che-do-danh-sach .dsp-mode-grid { display: none; }
.dsp-view-container.che-do-danh-sach .dsp-mode-list { display: block; }

/* Ảnh thu nhỏ THẬT (kiểu Drive) thay cho icon 🖼 — cả 2 chế độ */
.dsp-tile-thumb { background: #f4f6fb; border-radius: 6px; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.dsp-tile-thumb img { width: 100%; height: 100%; object-fit: cover; }
.dsp-tile-icon.dsp-tile-thumb { height: 44px; }

.dsp-badge-kho { background: #e8eefc; color: #2952cc; }

.dsp-list-table { width: 100%; border-collapse: collapse; background: #fff; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.dsp-list-table thead th { text-align: left; font-size: 11px; color: var(--muted); font-weight: 700; padding: 8px 12px; border-bottom: 1px solid var(--line); background: #fafbfc; }
.dsp-list-table tbody tr { border-bottom: 1px solid #f0f2f5; }
.dsp-list-table tbody tr:last-child { border-bottom: none; }
.dsp-list-table tbody tr:hover { background: #fafbfc; }
.dsp-list-table td { padding: 8px 12px; font-size: 13px; vertical-align: middle; }
.dsp-list-icon { width: 32px; font-size: 18px; text-align: center; }
.dsp-list-thumb { display: inline-block; width: 28px; height: 28px; border-radius: 5px; overflow: hidden; vertical-align: middle; background: #f4f6fb; }
.dsp-list-thumb img { width: 100%; height: 100%; object-fit: cover; }
.dsp-list-name { color: var(--text); text-decoration: none; font-weight: 600; }
.dsp-list-name:hover { text-decoration: underline; }
.dsp-list-menu-cell { width: 40px; text-align: right; position: relative; }

/* ---------- Bản 290: "Data Sản phẩm" — tìm kiếm, kéo-thả nhiều file/thư mục, xem ảnh lightbox ---------- */
.dsp-search-form { display: inline-block; }
.dsp-search-input {
    width: 220px; padding: 7px 10px; font-size: 13px; border: 1px solid var(--line);
    border-radius: 8px; background: #fff;
}
.dsp-search-input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,.13); }
.dsp-search-banner {
    background: #eef4ff; border: 1px solid #cfe0fd; color: #1d4ed8; border-radius: 8px;
    padding: 8px 14px; font-size: 13px; margin-bottom: 12px;
}
.dsp-search-banner a { color: #1d4ed8; font-weight: 600; }
.dsp-search-warn { color: #b3261e; }

/* Tiến độ tải lên hàng loạt */
.dsp-tien-do {
    margin-top: 10px; padding: 8px 12px; background: #f4f6fb; border-radius: 8px;
    font-size: 12.5px; color: var(--text); font-weight: 600;
}

/* Lớp phủ kéo-thả toàn màn hình */
.dsp-drop-overlay {
    display: none; position: fixed; inset: 0; z-index: 900;
    background: rgba(37,99,235,.12); border: 3px dashed var(--blue);
    align-items: center; justify-content: center;
}
.dsp-drop-overlay.open { display: flex; }
.dsp-drop-msg {
    background: #fff; padding: 22px 32px; border-radius: 12px; font-size: 16px; font-weight: 700;
    color: var(--blue); box-shadow: 0 10px 30px rgba(16,24,40,.2);
}

/* Lightbox xem ảnh */
.dsp-lightbox-overlay {
    display: none; position: fixed; inset: 0; z-index: 1100; background: rgba(10,12,18,.92);
    align-items: center; justify-content: center; flex-direction: column;
}
.dsp-lightbox-overlay.open { display: flex; }
.dsp-lb-body { max-width: 90vw; max-height: 78vh; display: flex; align-items: center; justify-content: center; }
.dsp-lb-body img { max-width: 90vw; max-height: 78vh; object-fit: contain; border-radius: 4px; }
.dsp-lb-close {
    position: absolute; top: 16px; right: 20px; background: none; border: none; color: #fff;
    font-size: 22px; cursor: pointer; line-height: 1; padding: 6px;
}
.dsp-lb-nav {
    position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,.12);
    border: none; color: #fff; font-size: 30px; width: 48px; height: 48px; border-radius: 50%;
    cursor: pointer; line-height: 1;
}
.dsp-lb-nav:hover { background: rgba(255,255,255,.25); }
.dsp-lb-prev { left: 16px; }
.dsp-lb-next { right: 16px; }
.dsp-lb-info {
    margin-top: 14px; display: flex; align-items: center; gap: 12px; color: #fff; font-size: 13.5px;
}
.dsp-lb-info .btn { color: #fff; border-color: rgba(255,255,255,.3); }
