/* =============================================================================
   VCI PORTAL FE — HỆ THỐNG STYLE
   Nguồn quy chuẩn: docs/design.md (Dark Finance Dashboard) — giữ nguyên hệ nền
   navy 4 tầng, 3 tầng điều hướng, icon emoji, phân quyền ẩn hẳn.
   ĐÃ CHỐT 26/07/2026: dùng ĐÚNG bảng màu hệ kế toán — brand xanh lá #30d158, nền navy
   4 tầng, gradient và màu ngữ nghĩa y hệt. Hai hệ nhìn cùng một nhà (docs 00 §6:
   "kế thừa bảng màu và ngôn ngữ thiết kế của hệ kế toán").
   Bộ màu accent của docs/color-palette.md vốn TRÙNG KHÍT với design.md ở đỏ #ff3b30,
   vàng #ffd60a, cyan #32d9ff, xanh lá #30d158 — nên không có xung đột nào.
   ========================================================================== */
:root{
  /* Nền — 4 tầng sáng dần: page → section → card → control */
  --bg:#0f1729;
  --bg2:#16213a;
  --panel:#1b2740;
  --panel2:#22314f;
  --chip:#243354;

  /* Viền */
  --line:#2c3d61;
  --line2:#38517f;

  /* Chữ */
  --txt:#e6edf7;
  --muted:#93a4c4;
  --muted2:#6b7ea3;

  /* Thương hiệu — xanh lá, đúng như hệ kế toán */
  --brand:#30d158;   --brand2:#1fa83d;
  --navy-accent:#1d3b66;
  --brand-glow:rgba(48,209,88,.35);
  --brand-dim:#0f3d31;

  /* Ngữ nghĩa (giống hệ kế toán) */
  --in:#30d158;  --in-dim:#0f3d31;
  --out:#ff3b30; --out-dim:#40211f;
  --warn:#ffd60a;
  --neg:#ff3b30;
  --cyan:#32d9ff;
  --sel:#4da3ff;

  --radius:10px;
  --shadow:0 6px 24px rgba(0,0,0,.28);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  font-family:'Segoe UI',system-ui,-apple-system,Roboto,Arial,sans-serif;
  background:var(--bg); color:var(--txt); font-size:14px; line-height:1.45;
}
button{font-family:inherit;cursor:pointer}
a{color:var(--brand);text-decoration:none}
.hidden{display:none !important}

/* ============================== KHUNG APP ============================== */
.app{display:grid;grid-template-columns:1fr;grid-template-rows:56px auto 1fr;height:100vh}
.main{overflow:auto;padding:11px 12px 8px}

/* ================================ TOPBAR =============================== */
.topbar{position:relative;display:flex;align-items:center;gap:16px;padding:0 18px;
  background:linear-gradient(90deg,#16213a,#1b2740);border-bottom:1px solid var(--line)}
.topbar .spacer{flex:1}
.brand{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:.3px}
/* Ô logo công ty — biểu tượng đã có màu nền trong suốt nên KHÔNG đặt nền gradient */
.brand .logo{width:30px;height:30px;display:grid;place-items:center;overflow:hidden}
.brand .logo img{width:100%;height:100%;object-fit:contain;display:block}
.brand small{display:block;font-weight:500;color:var(--muted);font-size:11px;letter-spacing:0}

.topbar-title{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  font-size:21px;font-weight:900;letter-spacing:2px;white-space:nowrap;
  color:var(--brand);text-shadow:0 0 14px var(--brand-glow);pointer-events:none}

.home-btn{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;font-size:17px;
  background:var(--chip);border:1px solid var(--line);cursor:pointer;transition:all .15s}
.home-btn:hover{border-color:var(--brand);box-shadow:0 0 10px var(--brand-glow)}
.home-btn.active{border-color:var(--brand);background:var(--brand-dim)}
.home-menu-wrap{position:relative}
.home-menu{position:absolute;top:calc(100% + 8px);right:-6px;min-width:250px;z-index:90;
  background:var(--panel2);border:1px solid var(--line2);border-radius:12px;padding:6px;
  box-shadow:0 14px 44px rgba(0,0,0,.55);
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .15s,transform .15s,visibility .15s}
.home-menu::before{content:'';position:absolute;top:-10px;left:0;right:0;height:10px}
.home-menu-wrap:hover .home-menu{opacity:1;visibility:visible;transform:translateY(0)}
.home-menu-item{display:flex;align-items:center;gap:10px;width:100%;border-radius:8px;
  padding:8px 10px;color:var(--txt);font-size:13px;font-weight:600;transition:background .12s}
.home-menu-item:hover{background:var(--chip)}
.home-menu-item.active{background:var(--brand-dim);color:var(--brand)}
.home-menu-sep{border-top:1px solid var(--line);margin:5px 6px;padding-top:4px;
  color:var(--muted2);font-size:10px;font-weight:700;letter-spacing:.8px}

.user-chip{display:flex;align-items:center;gap:8px;background:var(--chip);
  border:1px solid var(--line);padding:5px 10px 5px 5px;border-radius:20px}
.avatar{width:28px;height:28px;border-radius:50%;background:var(--brand2);
  display:grid;place-items:center;font-size:12px;font-weight:700}
.badge{font-size:10px;padding:2px 7px;border-radius:10px;font-weight:700;letter-spacing:.4px;
  display:inline-block;white-space:nowrap}
/* Mỗi vai trò Portal 1 cặp nền-tối / chữ-sáng (docs 02 §2.5) */
.badge.ADMIN{background:#3a2d5e;color:#c4b5fd}          /* tím  — quản trị hệ thống */
.badge.CEO{background:#4a2b18;color:#fdba74}            /* cam  — TGĐ */
.badge.HCNS_TCKT{background:#0f3d31;color:#6ee7b7}      /* lá   — phòng HCNS-TCKT */
.badge.DEPT_HEAD{background:#123a52;color:#7dd3fc}      /* cyan — trưởng bộ phận */
.badge.MANAGER{background:#102c4d;color:#93c5fd}        /* blue — quản lý trực tiếp */
.badge.PM{background:#2b2140;color:#c9a3ff}             /* tím nhạt — quản lý dự án */
.badge.EMPLOYEE{background:#2b2f34;color:#9aa4ad}       /* xám  — nhân viên */
.logout-btn{width:28px;height:28px;margin-left:4px;border-radius:50%;display:grid;place-items:center;
  background:transparent;border:1px solid transparent;color:var(--muted);transition:all .15s}
.logout-btn:hover{background:var(--out-dim);border-color:var(--out);color:var(--out)}

/* ============================== DOCK (macOS) =========================== */
.dock-trigger{position:fixed;left:0;right:0;bottom:0;height:10px;z-index:69}
.dock-wrap{position:fixed;left:0;right:0;bottom:0;display:flex;justify-content:center;
  z-index:70;pointer-events:none}
.dock{pointer-events:auto;display:flex;align-items:flex-end;gap:4px;padding:9px 14px 10px;
  background:rgba(22,33,58,.78);backdrop-filter:blur(20px);
  border:1px solid var(--line2);border-radius:20px;box-shadow:0 14px 44px rgba(0,0,0,.55);
  transform:translateY(calc(100% - 8px));
  transition:transform .32s cubic-bezier(.2,.8,.2,1) .35s}
.dock-trigger:hover + .dock-wrap .dock,
.dock-wrap:hover .dock{transform:translateY(-10px);transition-delay:0s}
.dock-wrap.pinned .dock{transform:translateY(-10px);transition-delay:0s}
body.dock-pinned .main{padding-bottom:96px}
.dock-item{position:relative;display:grid;place-items:center;width:46px;height:46px;
  background:transparent;border:none;border-radius:12px;
  transform-origin:bottom center;transition:transform .09s ease-out}
.dock-item .dock-ic{font-size:27px;line-height:1;filter:drop-shadow(0 3px 6px rgba(0,0,0,.4))}
.dock-item.active::after{content:'';position:absolute;bottom:-6px;left:50%;
  transform:translateX(-50%);width:4px;height:4px;border-radius:50%;background:var(--brand)}
.dock-item .dock-label{position:absolute;bottom:calc(100% + 12px);left:50%;transform:translateX(-50%);
  white-space:nowrap;background:var(--panel2);border:1px solid var(--line2);color:var(--txt);
  font-size:12px;font-weight:600;padding:5px 11px;border-radius:8px;box-shadow:var(--shadow);
  opacity:0;pointer-events:none;transition:opacity .12s}
.dock-item:hover .dock-label{opacity:1}
.dock-sep{width:1px;align-self:stretch;margin:5px 5px;background:var(--line2)}
.dock-item .dock-badge{position:absolute;top:-1px;right:-1px;min-width:16px;height:16px;padding:0 4px;
  border-radius:9px;background:var(--out);color:#fff;font-size:10px;font-weight:800;
  display:grid;place-items:center;box-shadow:0 2px 6px rgba(0,0,0,.5)}

/* ============================ TRANG CHỦ (cards) ======================== */
.home-wrap{display:grid;place-items:center;min-height:calc(100vh - 170px)}
.home-head{text-align:center;margin-bottom:22px}
.home-head h2{margin:0;font-size:19px;font-weight:800;letter-spacing:.5px}
.home-head p{margin:6px 0 0;color:var(--muted);font-size:13px}
.home-grid{display:grid;grid-template-columns:repeat(4,minmax(200px,240px));gap:18px;justify-content:center}
@media (max-width:1100px){.home-grid{grid-template-columns:repeat(2,minmax(200px,240px))}}
.home-card{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:26px 20px 22px;text-align:center;box-shadow:var(--shadow);
  transition:transform .15s,border-color .15s,box-shadow .15s}
.home-card:hover{transform:translateY(-4px);border-color:var(--brand);
  box-shadow:0 10px 30px rgba(48,209,88,.18)}
.home-card .hc-ic{font-size:38px;margin-bottom:12px;filter:drop-shadow(0 4px 8px rgba(0,0,0,.35))}
.home-card .hc-name{font-size:15px;font-weight:800;letter-spacing:1.2px;color:var(--brand)}
.home-card .hc-desc{font-size:11.5px;color:var(--muted);margin-top:7px;line-height:1.45}
.home-card .hc-phase{position:absolute;top:10px;right:10px;font-size:9.5px;font-weight:800;
  letter-spacing:.5px;padding:2px 7px;border-radius:8px;background:var(--chip);
  border:1px solid var(--line);color:var(--muted2)}
.home-card.soon{opacity:.62}
.home-card.soon:hover{border-color:var(--line2);box-shadow:var(--shadow);transform:none}
.home-card .hc-badge{position:absolute;top:10px;left:10px;min-width:18px;height:18px;padding:0 5px;
  border-radius:9px;background:var(--out);color:#fff;font-size:10px;font-weight:800;
  display:grid;place-items:center}

/* ==================== TAB PHÂN HỆ CON (hàng dưới topbar) =============== */
.sub-tabs{display:flex;align-items:stretch;flex-wrap:wrap;padding:0 12px;
  background:linear-gradient(90deg,#1d3b66,#1a2f52);
  border-bottom:1px solid var(--line2);box-shadow:0 4px 12px rgba(0,0,0,.20)}
.sub-tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;
  color:#b7c6e2;font-size:12px;font-weight:600;text-decoration:none;
  border:none;border-bottom:2px solid transparent;border-radius:0;
  white-space:nowrap;letter-spacing:.2px;transition:background .12s,color .12s}
.sub-tab:hover{color:#fff;background:rgba(255,255,255,.08)}
.sub-tab.active{color:#fff;border-bottom-color:var(--brand);
  background:linear-gradient(180deg,transparent,rgba(48,209,88,.16))}
.sub-tab.lead{font-weight:800}
.sub-tabs .st-sep{width:1px;align-self:stretch;background:var(--line2);margin:5px 8px}
.sub-tabs .st-cap{align-self:center;color:var(--muted2);font-size:9.5px;
  text-transform:uppercase;letter-spacing:.7px;margin-right:2px;white-space:nowrap}
.sub-tab .pill{padding:0 5px;margin-left:2px;font-size:10px}

/* Hàng công cụ trên bảng: tab cấp 3 (.seg — khai ở khối nút bên dưới) + bộ lọc */
.subnav{display:flex;align-items:center;gap:10px;margin-bottom:7px;flex-wrap:wrap}
.cat-search{position:relative;display:inline-flex;align-items:center}
.cat-search .cs-ic{position:absolute;left:11px;font-size:12px;opacity:.55;pointer-events:none}
.cat-search input{width:250px;padding-left:32px;border-radius:20px}
.cat-search input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(48,209,88,.12)}

/* ========================= BUTTONS & CONTROLS ========================== */
.btn{background:var(--panel2);border:1px solid var(--line2);color:var(--txt);
  padding:5px 12px;border-radius:8px;font-size:12px;font-weight:600;
  display:inline-flex;align-items:center;gap:6px}
.btn:hover{background:var(--panel)}
.btn.primary{background:linear-gradient(135deg,var(--brand2),var(--navy-accent));border-color:var(--brand)}
.btn.primary:hover{box-shadow:0 0 12px var(--brand-glow)}
.btn.sm{padding:3px 8px;font-size:11px}
.btn.icon{width:28px;height:26px;padding:0;display:inline-grid;place-items:center;font-size:14px}
.btn:disabled{opacity:.35;cursor:not-allowed;pointer-events:none}
.btn.danger-btn{border-color:var(--out);color:var(--out)}
.btn.danger-btn:hover{background:var(--out-dim)}
.btn.ok-btn{border-color:var(--in);color:var(--in)}
.btn.ok-btn:hover{background:var(--in-dim)}

/* Segmented control — cùng khuôn với tab P&L / Lãi-lỗ theo BCTC của HQKD bên hệ kế toán */
.seg{display:inline-flex;background:var(--panel);border:1px solid var(--line);
  border-radius:9px;overflow:hidden}
.seg button{display:inline-flex;align-items:center;gap:7px;background:transparent;border:none;
  color:var(--muted);padding:4px 12px;font-size:12px;font-weight:600;
  transition:background .12s,color .12s}
.seg button:hover{color:var(--txt);background:var(--chip)}
.seg button.active{background:var(--brand2);color:#fff}
/* Số bản ghi của từng tab — chữ nhỏ, không cướp nhìn của nhãn */
.seg .seg-n{font-size:10.5px;font-weight:700;padding:0 6px;border-radius:9px;
  background:var(--chip);color:var(--muted2)}
.seg button.active .seg-n{background:rgba(255,255,255,.18);color:#fff}
/* Bộ lọc segmented của bảng: nhãn + dãy nút dính nhau khi toolbar wrap (design.md §9.2.1) */
.seg-filter{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}

.input,select.input,textarea.input{background:var(--panel2);color:var(--txt);border:1px solid var(--line2);
  border-radius:8px;padding:5px 9px;font-size:12px;color-scheme:dark;font-family:inherit}
select.input option{background:var(--panel2);color:var(--txt)}
.input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(48,209,88,.12)}
.hint{color:var(--muted2);font-size:12px}

.row-act{border:1px solid var(--line);background:var(--chip);border-radius:7px;padding:3px 7px;
  font-size:14px;line-height:1;color:var(--txt);transition:border-color .12s,color .12s,background .12s}
.row-act:hover{border-color:var(--brand);color:#fff;background:var(--panel2)}
.row-act.danger:hover{border-color:var(--out);color:#fff}
.row-act.ok{color:var(--in)}
.row-act.ok:hover{border-color:var(--in);color:#fff}
.row-act+.row-act{margin-left:5px}

/* Toolbar nổi bật (màn thao tác chính) */
.big-tools .btn{padding:5px 15px;font-size:14px;border-radius:10px;
  background:linear-gradient(135deg,var(--panel2),var(--panel));border-color:var(--line2);
  box-shadow:0 2px 10px rgba(0,0,0,.25);transition:border-color .12s,box-shadow .12s}
.big-tools .btn:hover{border-color:var(--brand);background:var(--chip);
  box-shadow:0 0 12px var(--brand-glow)}
.big-tools .btn.primary{background:linear-gradient(135deg,var(--brand2),var(--navy-accent))}
.tb-count{background:var(--brand2);color:#fff;font-size:12px;font-weight:800;
  min-width:20px;text-align:center;padding:1px 7px;border-radius:10px}

/* ======================= MÀN DANH SÁCH (list screen) =================== */
/* Màn có danh sách: cả khung ăn trọn chiều cao màn hình, KHÔNG cuộn cả trang —
   chỉ vùng .list-scroll cuộn dọc theo từng dòng. */
.main:has(.list-wrap){display:flex;flex-direction:column;overflow:hidden}
.main:has(.list-wrap)>*{flex:0 0 auto}            /* KPI, subnav giữ nguyên cao */
.main:has(.list-wrap)>.list-wrap{flex:1 1 auto}   /* bảng ăn hết chỗ còn lại */
.list-wrap{height:100%;min-height:0;display:flex;flex-direction:column}
/* .card.list-card (không phải .list-card) — phải thắng padding của .card khai báo bên dưới.
   Card danh sách KHÔNG có viền trong: toolbar/bảng/chân trang tự lo padding của mình. */
.card.list-card{flex:1 1 auto;min-height:0;padding:0;overflow:hidden;display:flex;flex-direction:column}
.list-toolbar{display:flex;align-items:center;gap:8px;padding:5px 12px;
  border-bottom:1px solid var(--line);flex-wrap:wrap;flex:0 0 auto}
.list-scroll{flex:1 1 auto;min-height:0;overflow:auto}
/* table-layout:fixed → cột giữ đúng width đã đặt, cột không đặt nhận phần còn lại.
   Mọi ô 1 dòng: dòng nào cũng cao bằng nhau, text dài cắt bằng … (bản đầy đủ ở title). */
.list-scroll .grid{width:100%;font-size:12px;table-layout:fixed}
.list-scroll .grid th,.list-scroll .grid td{padding:5px 10px;height:28px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.list-scroll .grid thead th{position:sticky;top:0;background:var(--panel);z-index:1}
/* Ô chứa control nổi (select, menu) — bỏ cắt để không xén popup */
.list-scroll .grid td.cell-free{overflow:visible}
/* Ngoại lệ: bảng ô nhiều dòng (ma trận quyền) — vẫn fit chiều cao + header dính,
   nhưng KHÔNG ép 1 dòng/ô */
.list-scroll.free .grid{table-layout:auto}
.list-scroll.free .grid th,.list-scroll.free .grid td{height:auto;white-space:normal;overflow:visible}
/* Bảng phụ NẰM NGOÀI .list-scroll (khối tổng hợp trong card) — vẫn theo chuẩn
   dòng cao cố định + cắt … để mọi bảng của hệ thống nhìn như nhau */
.grid.tight{font-size:12px;table-layout:fixed}
.grid.tight th,.grid.tight td{padding:5px 10px;height:28px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.list-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:6px 14px;border-top:1px solid var(--line);flex-wrap:wrap;flex:0 0 auto}
/* Phân trang chân danh sách — cỡ trang + « ‹ Trang n/m › » (giống HĐ đầu vào bên hệ kế toán) */
.pager{display:inline-flex;align-items:center;gap:4px}
.pager button{min-width:30px;text-align:center}
.pager .pg-size{width:auto;padding:4px 6px;font-size:12px;margin-right:4px}
.pager .pg-info{font-size:12px;color:var(--muted);padding:0 8px;white-space:nowrap}
/* Thanh hành động hàng loạt khi tick chọn dòng */
.bulk-bar{display:flex;align-items:center;gap:10px;padding:8px 14px;flex:0 0 auto;
  background:rgba(48,209,88,.10);border-bottom:1px solid var(--line2);font-size:12px}

table.grid{width:100%;border-collapse:collapse;font-size:13px}
.grid th{text-align:left;color:var(--muted);font-weight:600;font-size:12px;padding:10px 12px;
  border-bottom:1px solid var(--line2);text-transform:uppercase;letter-spacing:.4px}
.grid td{padding:11px 12px;border-bottom:1px solid var(--line)}
.grid tr:hover td{background:var(--panel2)}
.grid .num{text-align:right;font-variant-numeric:tabular-nums}
/* Header sắp xếp được — mũi tên ⇅ mờ, sáng màu brand ▲▼ khi đang sắp theo cột đó */
.grid th.sortable{cursor:pointer;user-select:none}
.grid th.sortable:hover{color:var(--txt)}
.grid th.sortable.on{color:var(--txt)}
.grid th .s-ind{font-size:9px;margin-left:4px;opacity:.35}
.grid th.sortable.on .s-ind{opacity:1;color:var(--brand)}
.grid tr.selected td{background:rgba(77,163,255,.16)}
.grid tr.selected td:first-child{box-shadow:inset 3px 0 0 var(--sel)}
.grid td.warn-cell{background:rgba(255,214,10,.08)}
.grid .c-check{width:34px}
.grid .c-stt{width:44px}
/* Cột thao tác — luôn cuối bảng, không sort, nút gọn về phải.
   88px vừa 2 nút; bảng nào có 3 nút thì thêm .act3 kẻo nút thứ ba bị cắt. */
.grid .c-act{width:88px;text-align:right;white-space:nowrap}
.grid .c-act.act3{width:124px}
/* 4 nút — chỉ ô Thao tác của màn Danh sách phê duyệt (🖨 · ✓ · ↩ · ✕). Luật "tối đa 3 nút"
   ở acc-request-rows.js áp cho màn "của tôi": ở đó nút thứ tư là thừa. Ở màn duyệt thì ba
   quyết định là BA VIỆC KHÁC NHAU, gộp lại được cái nào. */
.grid .c-act.act4{width:158px}
/* ⚠ CHO TRÀN, KHÔNG cắt. `.list-scroll .grid` là table-layout:fixed + text-overflow:ellipsis
   áp cho MỌI ô (xem rule ở trên), nên ô này hụt vài px là trình duyệt vẽ thêm dấu "…" cạnh
   các nút — nhìn y như một nút thứ tư mà bấm không được. Nút là inline-block nên vẫn thuộc
   diện text-overflow. Cùng cách hệ kế toán xử lý ô Thao tác của bảng HĐ đầu vào (td.hc-act). */
.list-scroll .grid td.c-act{overflow:visible;text-overflow:clip}
/* Cột cờ trạng thái 1 icon (✅ / ⚠️) — hẹp, căn giữa */
.grid .c-flag{width:58px;text-align:center}
.grid th.c-flag .s-ind{margin-left:2px}

/* ---- Popover trên toolbar bảng — MỘT khuôn dùng cho 2 việc (design.md §9.2.2 · §9.7):
   "⚙ Cột" ẩn/hiện cột (shared/table-columns.js) và "⚙ Lọc" bộ lọc nhiều chiều (app/core.js).
   Vỏ ngoài (nút .has + panel neo dưới nút + đầu panel) dùng chung, chỉ khác RUỘT. ---- */
.cols-wrap,.filter-wrap{position:relative;display:inline-block}
.cols-wrap .btn.has,.filter-wrap .btn.has{border-color:var(--brand);color:var(--brand)}
.cols-badge,.filter-badge{display:inline-grid;place-items:center;min-width:15px;height:15px;padding:0 3px;
  margin-left:2px;border-radius:8px;background:var(--brand);color:#04240f;
  font-size:10px;font-weight:700;line-height:1}
.cols-pop,.filter-pop{position:absolute;top:calc(100% + 6px);right:0;z-index:60;width:300px;display:none;
  background:var(--panel);border:1px solid var(--line2);border-radius:10px;
  padding:10px 12px;box-shadow:0 10px 30px rgba(0,0,0,.45)}
.cols-pop.open,.filter-pop.open{display:block}
.cols-head,.filter-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:7px;
  font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.4px}
/* Ruột "⚙ Cột" — lưới 2 cột checkbox */
.cols-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px 12px}
.cols-item{display:flex;align-items:center;gap:7px;font-size:12.5px;padding:3px 4px;
  border-radius:6px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cols-item:hover{background:rgba(255,255,255,.06)}
.cols-item input{width:auto;cursor:pointer;flex:0 0 auto}
.cols-foot{margin-top:8px;padding-top:7px;border-top:1px solid var(--line);font-size:11px}
/* Ruột "⚙ Lọc" — mỗi chiều lọc MỘT hàng: nhãn bề rộng cố định (thẳng cột) + select ăn phần dư.
   Panel rộng hơn ⚙ Cột vì option là nhãn nghiệp vụ dài (tên khách hàng, loại dự án).
   Neo mép TRÁI: nút ⚙ Lọc đứng ở nửa trái toolbar (sau ô tìm), khác ⚙ Cột nằm sau
   `<span flex:1>` ở mép phải — neo phải thì panel thò ra ngoài mép trái card. */
.filter-pop{left:0;right:auto;width:330px}
.fp-row{display:flex;align-items:center;gap:10px;margin:7px 0;flex-wrap:wrap}
.fp-row>span{flex:none;width:96px;font-size:12px;color:var(--muted)}
.fp-row .input{flex:1;min-width:0;width:auto;font-size:12px}
/* Màn hẹp: popover neo giữa màn thay vì bám mép phải nút (tránh tràn ra ngoài);
   nhãn hàng lọc xuống dòng riêng để select còn đủ bề rộng */
@media (max-width:820px){
  .cols-pop,.filter-pop{position:fixed;left:50%;right:auto;transform:translateX(-50%);top:96px;
    width:min(320px,94vw);max-height:70dvh;overflow:auto}
  .fp-row>span{width:auto;flex:1 1 100%}
}

/* ============================ CARDS / KPI ============================== */
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 18px;box-shadow:var(--shadow)}
/* KPI card GỌN — kích thước chuẩn của portal, lấy nguyên từ hệ kế toán · HQKD/HĐ đầu vào.
   Cao ~1/2 card KPI cổ điển: nhãn + chú thích chung 1 HÀNG, giá trị 16px ở dưới.
   Luôn dựng bằng helper kpi() trong shared/ui.js — không viết tay HTML. */
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
  gap:8px;margin-bottom:7px;flex:0 0 auto}
.card.kpi{padding:5px 12px 6px}
.kpi .k-head{display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.kpi .k-label{color:var(--muted);font-size:10px;font-weight:600;
  text-transform:uppercase;letter-spacing:.4px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpi .k-value{font-size:16px;font-weight:700;margin-top:1px;font-variant-numeric:tabular-nums;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpi .k-foot{font-size:10px;color:var(--muted);margin:0;text-align:right;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.k-value.pos{color:var(--in)} .k-value.neg{color:var(--neg)}
.k-value.brand{color:var(--brand)} .k-value.warn{color:var(--warn)}
/* Card lọc nhanh: bấm để lọc danh sách bên dưới, bấm lại để bỏ lọc (.on = đang lọc) */
.card.kpi.clickable{cursor:pointer;transition:border-color .12s,box-shadow .12s}
.card.kpi.clickable:hover{border-color:var(--line2)}
.card.kpi.on{border-color:var(--brand);box-shadow:0 0 8px rgba(48,209,88,.35)}

.page-head{display:flex;align-items:flex-end;justify-content:space-between;
  margin-bottom:18px;gap:16px;flex-wrap:wrap}
.page-title{font-size:22px;font-weight:700}
.page-sub{color:var(--muted);font-size:13px;margin-top:3px}
.section-title{font-size:14px;font-weight:700;margin:2px 0 12px;color:var(--muted)}
.empty{padding:60px 20px;text-align:center;color:var(--muted2)}
.empty h2{color:var(--txt);font-size:18px;margin:12px 0 6px}
.detail-line{display:flex;justify-content:space-between;gap:12px;padding:9px 0;
  border-bottom:1px solid var(--line);font-size:13px}
.detail-line:last-child{border-bottom:none}
.detail-line .d-desc{color:var(--txt)}
/* Trang chi tiết (vd hồ sơ nhân sự) — cùng khuôn với màn danh sách: đầu trang
   đứng yên, CHỈ vùng thẻ cuộn dọc. Thẻ hẹp, xếp 2–3 thẻ/hàng tuỳ bề ngang. */
.main:has(.detail-wrap){display:flex;flex-direction:column;overflow:hidden}
.main:has(.detail-wrap)>*{flex:0 0 auto}
.main:has(.detail-wrap)>.detail-wrap{flex:1 1 auto}
.detail-wrap{height:100%;min-height:0;display:flex;flex-direction:column}
.detail-scroll{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding-right:4px}
.detail-grid{display:grid;gap:12px;align-items:start;
  grid-template-columns:repeat(auto-fill,minmax(400px,1fr))}
.detail-grid .card{padding:10px 14px}
.detail-grid .section-title{margin:0 0 6px;padding-bottom:6px;border-bottom:1px solid var(--line)}

/* ====================== PILL / ALERT / PROGRESS ========================= */
.pill{display:inline-block;font-size:11px;font-weight:700;padding:3px 9px;border-radius:12px;
  white-space:nowrap}
.pill.on,.pill.APPROVED,.pill.PAID,.pill.ACTIVE{background:#0f3d31;color:#6ee7b7}
.pill.PENDING,.pill.PROBATION{background:#3a3320;color:#fde68a}
.pill.SYNCED,.pill.IN_PROGRESS,.pill.ON_LEAVE{background:#123a52;color:#7dd3fc}
.pill.off,.pill.REJECTED,.pill.SYNC_FAILED,.pill.OVERDUE{background:#40211f;color:#fca5a5}
.pill.DRAFT,.pill.CANCELLED,.pill.RESIGNED,.pill.ENDED{background:#2b2f34;color:#9aa4ad}
.pill.RETURNED{background:#4a2b18;color:#fdba74}
.pill.DONE{background:#2b2140;color:#c9a3ff}
.pill.info{background:#102c4d;color:#93c5fd}

.alert{display:flex;gap:10px;align-items:flex-start;padding:11px 14px;border-radius:9px;
  margin-bottom:10px;font-size:13px}
.alert.warn{background:rgba(255,214,10,.1);border:1px solid #6b5416;color:#fde68a}
.alert.danger{background:rgba(255,59,48,.1);border:1px solid #6b2b2b;color:#fca5a5}
.alert.ok{background:rgba(48,209,88,.1);border:1px solid #1c5245;color:#6ee7b7}
.alert.info{background:rgba(59,130,246,.1);border:1px solid #2b466b;color:#93c5fd}

.bar{height:7px;background:var(--panel2);border-radius:6px;overflow:hidden;min-width:90px}
.bar>span{display:block;height:100%;background:linear-gradient(90deg,var(--navy-accent),var(--brand))}
.money-neg{color:var(--neg)}
.money-zero{color:var(--muted2)}
.num{font-variant-numeric:tabular-nums}

/* Chuỗi bước duyệt (engine phê duyệt — docs 03 §4.2) */
.flow{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:11.5px}
.flow-step{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:20px;
  background:var(--panel2);border:1px solid var(--line);color:var(--muted)}
.flow-step.done{background:var(--in-dim);border-color:#1c5245;color:#6ee7b7}
.flow-step.current{background:var(--brand-dim);border-color:var(--brand);color:#6ee7b7;
  box-shadow:0 0 8px var(--brand-glow)}
.flow-step.rejected{background:var(--out-dim);border-color:var(--out);color:#fca5a5}
.flow-arrow{color:var(--muted2);font-size:10px}

/* ==================== SIDE PANEL / MODAL / LOADING ===================== */
.side{position:fixed;top:0;right:0;height:100vh;width:460px;background:var(--bg2);
  border-left:1px solid var(--line2);box-shadow:-10px 0 40px rgba(0,0,0,.4);
  transform:translateX(100%);transition:transform .22s;z-index:40;padding:20px;overflow-y:auto}
.side.open{transform:translateX(0)}
.side.wide{width:min(760px,94vw)}
.side .close{position:absolute;top:16px;right:16px;background:var(--panel2);
  border:1px solid var(--line2);color:var(--txt);border-radius:8px;width:32px;height:32px}
.side h3{margin:4px 0 8px;font-size:18px}
.backdrop{position:fixed;inset:0;background:rgba(4,8,17,.5);z-index:35;
  opacity:0;pointer-events:none;transition:opacity .2s}
.backdrop.open{opacity:1;pointer-events:auto}

.modal-wrap{position:fixed;inset:0;z-index:80;display:grid;place-items:center;padding:20px}
.modal-wrap .modal-backdrop{position:absolute;inset:0;background:rgba(4,8,17,.6)}
.modal{position:relative;width:min(440px,94vw);max-height:90vh;overflow-y:auto;
  background:var(--bg2);border:1px solid var(--line2);border-radius:14px;
  box-shadow:0 18px 60px rgba(0,0,0,.5);padding:20px;animation:modal-in .16s ease-out}
@keyframes modal-in{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}
.modal h3{margin:0 0 4px;font-size:17px}
.modal .modal-sub{color:var(--muted);font-size:12px;margin-bottom:6px}
.modal-actions{display:flex;gap:8px;margin-top:16px;justify-content:flex-end}
.modal-err{margin-top:12px;background:var(--out-dim);border:1px solid var(--out);
  color:#ffb4ae;border-radius:8px;padding:8px 10px;font-size:12.5px;white-space:pre-wrap}
.modal.wide{width:min(900px,96vw)}
.modal.wide-form{width:min(720px,95vw)}
.modal.popup h3.t-error{color:#fca5a5} .modal.popup h3.t-warning{color:#fde68a}
.modal.popup h3.t-success{color:#6ee7b7} .modal.popup h3.t-info{color:#93c5fd}
.modal.popup .popup-body{white-space:pre-wrap;font-size:13px;color:var(--txt);margin-top:8px}

.field{margin-top:10px}
.field label{display:block;font-size:12px;color:var(--muted);margin-bottom:5px}
.field .input,.field input,.field select,.field textarea{width:100%}
.field input,.field select,.field textarea{background:var(--panel2);color:var(--txt);
  border:1px solid var(--line2);border-radius:8px;padding:7px 10px;font-size:13px;
  color-scheme:dark;font-family:inherit}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--brand);
  box-shadow:0 0 0 3px rgba(48,209,88,.12)}
.field .f-hint{font-size:11px;color:var(--muted2);margin-top:4px}

/* Combobox có tìm kiếm — ô `combo` của openFormModal (danh sách dài: nhân sự) */
.field.combo .combo-box{position:relative}
.combo-list{position:absolute;z-index:30;left:0;right:0;top:calc(100% + 4px);
  max-height:230px;overflow-y:auto;background:var(--panel2);
  border:1px solid var(--line2);border-radius:8px;box-shadow:0 14px 40px rgba(0,0,0,.5)}
.combo-list.hidden{display:none}
.combo-opt{padding:7px 10px;font-size:13px;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.combo-opt:hover,.combo-opt.on{background:var(--chip)}
.combo-empty{padding:8px 10px;font-size:12px;color:var(--muted2)}
.cols-2{display:grid;grid-template-columns:1fr 1fr;gap:2px 18px}
.cols-2 .full{grid-column:1 / -1}

/* ============================== ĐĂNG NHẬP ============================== */
.login-screen{position:fixed;inset:0;display:grid;place-items:center;
  background:radial-gradient(1200px 600px at 70% -10%,#1d3054,#0f1729)}
.login-card{width:390px;background:var(--panel);border:1px solid var(--line2);border-radius:16px;
  padding:30px;box-shadow:var(--shadow)}
.login-card h1{font-size:20px;margin:14px 0 4px}
.login-card .field{margin-top:14px}
.login-card input{width:100%;padding:10px 12px;font-size:14px}
.login-card .btn{width:100%;justify-content:center;margin-top:18px;padding:11px;font-size:13px}
.pass-wrap{position:relative}
.pass-wrap input{padding-right:42px}
.pass-toggle{position:absolute;top:50%;right:6px;transform:translateY(-50%);width:32px;height:32px;
  display:grid;place-items:center;background:none;border:0;border-radius:8px;font-size:16px;
  line-height:1;opacity:.7}
.pass-toggle:hover{opacity:1;background:var(--line2)}
/* Chọn nhanh tài khoản demo — CHỈ CÓ Ở MOCKUP, bản thật không có */
.demo-users{margin-top:18px;border-top:1px solid var(--line);padding-top:12px}
.demo-users .du-cap{font-size:10px;font-weight:800;letter-spacing:.8px;color:var(--muted2);
  text-transform:uppercase;margin-bottom:8px}
.demo-users .du-list{display:flex;flex-direction:column;gap:5px}
.du-item{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:6px 9px;
  color:var(--txt);font-size:12px;transition:border-color .12s,background .12s}
.du-item:hover{border-color:var(--brand);background:var(--chip)}
.du-item .du-name{flex:1;font-weight:600}

/* ============================== SCROLLBAR ============================== */
*{scrollbar-width:thin;scrollbar-color:rgba(147,164,196,.18) transparent}
::-webkit-scrollbar{width:5px;height:5px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(147,164,196,.18);border-radius:10px}
::-webkit-scrollbar-thumb:hover{background:rgba(147,164,196,.45)}

/* ========================== MOCKUP BANNER ============================== */
/* Chỉ hiện khi chạy hoàn toàn bằng mock-store (USE_MOCK=true) — nối BE thật
   thì KHÔNG hiện nhãn nào ở góc màn hình. */
.mock-flag{position:fixed;left:0;bottom:0;z-index:75;pointer-events:none;font-size:10px;font-weight:800;
  letter-spacing:.6px;padding:3px 10px;border-radius:0 8px 0 0;
  background:var(--warn);color:#2b2200;opacity:.85}

/* ============================ MOBILE ≤768px ============================ */
@media (max-width:768px){
  .app{grid-template-rows:48px auto 1fr;height:100dvh}
  .main{padding:8px 10px 10px}
  .brand div{display:none}
  .topbar{gap:10px;padding:0 10px}
  .topbar-title{position:static;left:auto;top:auto;transform:none;font-size:13px;letter-spacing:1px;
    overflow:hidden;text-overflow:ellipsis;max-width:44vw}
  .user-chip{padding:4px;gap:4px}
  .user-chip>div{display:none}
  .dock-wrap .dock{transform:translateY(-8px) !important;max-width:100vw;overflow-x:auto;
    border-radius:16px 16px 0 0;padding-bottom:calc(10px + env(safe-area-inset-bottom))}
  .dock-item{transform:none !important;width:42px;height:42px}
  .dock-item .dock-label{display:none}
  body.dock-pinned .main{padding-bottom:80px}
  .side,.side.wide{width:100vw;height:100dvh}
  .pager button{min-height:34px;min-width:36px}
  .pager .pg-size{min-height:34px}
  .home-grid{grid-template-columns:1fr}
  .login-card{width:calc(100vw - 32px)}
  .login-card input{font-size:16px}
  .cols-2{grid-template-columns:1fr}
  .cat-search input{width:100%}
  .acc-cols{grid-template-columns:1fr !important}
  .kpi-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
}

/* ==================== QUẢN TRỊ · ĐỒNG BỘ hệ kế toán (docs 10 §8.2) ================ */
/* Cam = "cần người xử lý": khác hẳn đỏ (lỗi tạm thời, máy tự thử lại được). */
.pill.warn{background:#4a2b18;color:#fdba74}

/* Dải cảnh báo đầu màn — thay cho email/Zalo chưa có hạ tầng gửi (§8.2). */
.sync-alerts{display:flex;flex-direction:column;gap:6px;margin-bottom:11px}
.sync-alert{padding:8px 12px;border-radius:9px;font-size:12.5px;font-weight:600;
  border:1px solid transparent}
.sync-alert.error{background:#40211f;border-color:#7f2d2b;color:#fca5a5}
.sync-alert.warn{background:#3a3320;border-color:#6b5a2a;color:#fde68a}

/* Modal cao — form nhiều dòng (bảng chi phí) cần cuộn trong thân, không cuộn cả trang */
.modal.tall{max-height:92vh;display:flex;flex-direction:column}
.modal.tall .modal-body{overflow:auto;flex:1;min-height:0}
.modal .close{position:absolute;top:10px;right:12px;width:28px;height:28px;border-radius:50%;
  display:grid;place-items:center;background:transparent;border:1px solid transparent;
  color:var(--muted);font-size:14px}
.modal .close:hover{background:var(--out-dim);border-color:var(--out);color:var(--out)}
.modal{position:relative}

/* --- Popover ⚙ Lọc của màn Đề nghị (giống hồ sơ đầu vào hệ kế toán) ------------- */
.req-filter-wrap{position:relative;display:inline-flex}
.req-filter-pop{
  position:absolute;top:calc(100% + 6px);left:0;z-index:60;width:250px;
  background:#0f172a;border:1px solid #334155;border-radius:8px;padding:10px;
  box-shadow:0 12px 30px rgba(0,0,0,.5);display:flex;flex-direction:column;gap:8px;
}
.req-filter-pop.hidden{display:none}
.req-filter-pop .field{display:flex;flex-direction:column;gap:3px}
.req-filter-pop label{font-size:11px;color:#94a3b8}
.req-filter-pop select{
  background:#1e293b;color:#e2e8f0;border:1px solid #334155;
  border-radius:6px;padding:5px 7px;font-size:12.5px;width:100%;
}

/* --- Dòng TỔNG ở chân bảng (khớp anatomy bảng của hệ kế toán) ------------------- */
.grid tfoot tr.total td{
  background:var(--panel);border-top:2px solid var(--line2);
  font-size:12px;height:30px;position:sticky;bottom:0;z-index:1;
}
/* Radio/checkbox trong .field KHÔNG được kéo full width — luật `.field input`
   ở trên là dành cho ô nhập văn bản, áp lên radio thì hàng Biểu mẫu vỡ layout. */
.field input[type="radio"],.field input[type="checkbox"]{
  width:auto;display:inline-block;margin:0 5px 0 0;vertical-align:middle;
  padding:0;background:none;border:none;box-shadow:none;accent-color:var(--brand);
}
.field label.f-lbl{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Hàng "Biểu mẫu" của popup tạm ứng — 2 lựa chọn chia đôi, NGANG NHAU.
   Luật `.field label{display:block}` ở trên nhắm MỌI label trong .field, nên 2
   label bọc radio bị đẩy thành 2 dòng. hệ kế toán không dính vì dùng `.hsf-field>.f-lbl`
   (child + class) — chỉ nhãn của field bị block. Ở đây bọc trong lưới 2 cột
   bằng nhau: vừa kéo lại 1 hàng, vừa cho 2 lựa chọn đúng bề rộng như nhau. */
.field .acf-form-pick{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
.field .acf-form-pick>label{display:flex;align-items:center;margin:0;
  font-size:13px;color:var(--txt);cursor:pointer;white-space:nowrap}

/* ============================================================================
   POPUP ĐỀ NGHỊ 2 TẦNG — Hoàn ứng / Thanh toán (docs 13 §5, mẫu hệ kế toán)

   Bài học bê từ hệ kế toán: nội dung dài đẩy dãy nút Lưu/Xem trước tụt khỏi khung, người
   lập phải cuộn xuống đáy một bảng 30 dòng mới bấm được. Nên thân cuộn RIÊNG
   (.req-form-scroll) còn chân GHIM lại (.req-form-foot), luôn nhìn thấy tổng tiền
   và nút bấm.
   ========================================================================== */
.req-form-wrap{display:flex;flex-direction:column;min-height:0;max-height:calc(92vh - 92px)}
.req-form-scroll{overflow-y:auto;flex:1;min-height:0;padding-right:4px}
.req-form-foot{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  border-top:1px solid var(--line2);background:var(--bg2);
  padding:10px 0 2px;margin-top:8px;position:sticky;bottom:0;z-index:2;
}
/* Popup hoàn ứng có 2 bảng cạnh nhau ⇒ cần rộng hơn `.modal.wide` mặc định */
.modal.wide.tall.xwide{width:min(1240px,97vw)}

/* Lưới dày trong popup — nhiều dòng phải nhìn hết trong một màn, không cuộn dài */
.rfx-grid th,.rfx-grid td{padding:4px 8px;height:26px;font-size:12px;line-height:1.35;
  border-bottom:1px solid var(--line);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rfx-grid thead th{position:sticky;top:0;background:var(--panel);z-index:1;
  color:var(--muted);font-weight:600;font-size:11px}
.rfx-grid tbody tr:hover td{background:var(--panel2)}
.rfx-grid tbody tr.pickable{cursor:pointer}
.rfx-box{border:1px solid var(--line);border-radius:8px;overflow:hidden}
.rfx-box .rfx-scroll{overflow:auto}
.rfx-sum{display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:6px 12px;border-top:2px solid var(--line2);background:rgba(48,209,88,.10);font-weight:700}
.rfx-in{height:24px;padding:2px 6px;font-size:12px;text-align:right;width:110px}
/* Ô phân bổ đã bị sửa tay — viền cảnh báo để phân biệt với số hệ thống tự rải */
.rfx-in.manual{border-color:var(--warn)}
.rfx-toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:6px}
.rfx-toolbar .input{height:28px;padding:3px 8px;font-size:12.5px}
.rfx-empty{text-align:center;padding:14px;color:var(--muted);font-size:12.5px}

/* Vùng kéo-thả nộp hoá đơn gốc */
.rfx-drop{border:1px dashed var(--line2);border-radius:8px;padding:10px 12px;
  font-size:12.5px;color:var(--muted);text-align:center;cursor:pointer;transition:.15s}
.rfx-drop:hover,.rfx-drop.over{border-color:var(--brand);color:var(--txt);background:var(--panel2)}
.rfx-sugg{border:1px solid var(--brand);border-radius:8px;padding:8px 10px;margin-top:6px;
  background:rgba(77,163,255,.08);font-size:12.5px}

/* Modal chồng lớp (openStackModal) — nằm trên modal nền, cùng khuôn hình */
.stack-modal{position:fixed;inset:0;display:grid;place-items:center;padding:20px}
.stack-modal .modal-backdrop{position:absolute;inset:0;background:rgba(4,8,17,.6)}

/* ==================== TIMESHEET · LỊCH KHAI GIỜ (docs 06 §6.1) ==============
   Lưới 7 cột T2→CN. Ô ngày mang MỘT trạng thái, màu lấy từ TS_DAY_STATE ở
   modules/timesheet/timesheet-core.js — không màn nào tự nghĩ ra màu riêng. */
.ts-toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.ts-toolbar .input{height:30px}

.ts-legend{display:flex;gap:14px;flex-wrap:wrap;margin:2px 2px 8px;font-size:11.5px;color:var(--muted)}
.ts-lg{display:inline-flex;align-items:center;gap:5px}
.ts-dot{width:10px;height:10px;border-radius:3px;border:1px solid var(--line2);display:inline-block}

.ts-cal-card{padding:0;overflow:hidden}
.ts-cal-head,.ts-cal{display:grid;grid-template-columns:repeat(7,1fr)}
.ts-cal-head>div{padding:6px 8px;font-size:11.5px;font-weight:700;color:var(--muted);
  letter-spacing:.6px;border-bottom:1px solid var(--line);background:var(--panel2)}
.ts-cal-head>div:nth-child(n+6){color:var(--muted2)}

.ts-cell{min-height:104px;border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:5px 6px;display:flex;flex-direction:column;gap:3px;cursor:pointer;
  transition:background .12s,box-shadow .12s}
.ts-cell:nth-child(7n){border-right:none}
.ts-cell:hover{background:var(--panel2)}
/* Ngày của tháng khác — chỉ giữ chỗ cho lưới tuần đủ 7 ô, không bấm được */
.ts-cell.out{background:var(--bg2);cursor:default;opacity:.45}
.ts-cell.out:hover{background:var(--bg2)}
.ts-cell.today{box-shadow:inset 0 0 0 2px var(--sel)}
.ts-cell.is-closed{cursor:default}
/* Kỳ tuần Chờ chốt (SUBMITTED) — viền vàng CHỒNG lên màu nền trạng thái ngày
   (ok/short/…), không thay nền: đây là tín hiệu về KỲ, khác tín hiệu về NGÀY.
   `.today.pending` cộng cả hai viền (ngoài = hôm nay, trong = chờ chốt) để
   không viền nào bị mất khi trùng nhau. */
.ts-cell.pending{box-shadow:inset 0 0 0 1.5px rgba(255,214,10,.55)}
.ts-cell.today.pending{box-shadow:inset 0 0 0 2px var(--sel),inset 0 0 0 4px rgba(255,214,10,.55)}

/* Nền theo trạng thái — cùng bảng màu ngữ nghĩa của hệ kế toán. HAI MÀU cho
   hai mức "không chuẩn" (docs 06 §5 mở rộng 2026-09): cam = VARIANCE (lệch
   chấm công, HOẶC khớp nhưng thiếu chưa bù đúng đơn nghỉ) · đỏ = EMPTY (thiếu
   một hoặc cả hai phía dữ liệu) — khớp `.tsm-table td.tsm-day.*` (styles.css,
   Bảng công tháng) — hai nơi PHẢI giữ cùng bảng màu, không lệch nhau. */
.ts-cell.ok{background:rgba(48,209,88,.09)}
.ts-cell.variance,.ts-dot.variance{background:rgba(255,149,0,.24)}
.ts-cell.empty-d,.ts-dot.empty-d{background:rgba(255,59,48,.24)}
.ts-cell.leave,.ts-dot.leave{background:rgba(50,217,255,.12)}
.ts-cell.holiday,.ts-dot.holiday{background:rgba(201,163,255,.15)}
.ts-cell.locked,.ts-dot.locked{background:var(--bg2)}
.ts-cell.off,.ts-dot.off{background:var(--bg2)}
.ts-dot.ok{background:rgba(48,209,88,.35)}
.ts-dot.pending{background:transparent;box-shadow:inset 0 0 0 1.5px rgba(255,214,10,.55)}

.ts-cell-top{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--muted)}
.ts-day{font-weight:700;font-size:13px;color:var(--txt);min-width:17px}
.ts-io{display:inline-flex;align-items:center;gap:2px;font-variant-numeric:tabular-nums}
.ts-io i{font-style:normal;color:var(--muted2)}
.ts-total{font-size:11.5px;color:var(--brand);font-variant-numeric:tabular-nums}
.ts-total.warn{color:var(--warn)}
.ts-tag{font-size:8.5px;font-weight:700;letter-spacing:.3px;padding:1px 4px;border-radius:4px;
  background:var(--chip);color:var(--muted)}
.ts-tag.wfh{background:#123a52;color:#7dd3fc}
.ts-tag.manual{background:#3a3320;color:#fde68a}
.ts-holiday{font-size:11px;font-weight:700;color:#c9a3ff}

.ts-items{display:flex;flex-direction:column;gap:2px;overflow:hidden}
/* Một dòng = một dự án trong ngày: `mã ngắn · tên dự án` bên trái, số giờ bên phải.
   Tên dài thì cắt bằng ellipsis — tooltip của cả ô đã nói đủ. */
.ts-item{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600;
  padding:1px 5px;border-radius:4px;background:var(--navy-accent);color:#dbe7ff}
.ts-item.LEAVE{background:#3a3320;color:#fde68a}
.ts-item.HOLIDAY{background:#2b2140;color:#c9a3ff}
.ts-item.OT{background:#40211f;color:#fca5a5}
.ts-item-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ts-item-h{font-variant-numeric:tabular-nums;opacity:.85}

/* Dải kỳ chốt tuần dưới lịch */
.ts-strip-head{padding:7px 12px;font-weight:700;font-size:12.5px;
  border-bottom:1px solid var(--line);background:var(--panel2)}
.ts-strip-head .hint{font-weight:400}

/* ---- Form khai giờ một ngày ---- */
.ts-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}
.ts-stat{padding:6px 11px}
.ts-stat-l{font-size:11px;color:var(--muted);font-weight:700;letter-spacing:.3px}
.ts-stat-v{font-size:17px;font-weight:700;font-variant-numeric:tabular-nums}
.ts-stat-v.pos{color:var(--in)} .ts-stat-v.neg{color:var(--out)} .ts-stat-v.warn{color:var(--warn)}
.ts-note{margin-top:8px;padding:6px 10px;border-radius:7px;font-size:12.5px;
  background:var(--panel2);border:1px solid var(--line);color:var(--muted)}
.ts-note.warn{border-color:var(--warn);color:var(--txt)}
.ts-sys{display:flex;flex-direction:column;gap:3px;margin-top:8px}
.ts-sys .ts-item{font-size:12px;padding:4px 8px}
.ts-group{margin-top:10px;border:1px solid var(--line);border-radius:8px;overflow:hidden}
.ts-group-head{display:flex;align-items:center;gap:8px;padding:6px 10px;
  background:var(--panel2);border-bottom:1px solid var(--line);font-size:12.5px}
.ts-group-name{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:340px}
.ts-group .grid td{padding:4px 6px}
.ts-group .input{height:28px;padding:2px 7px;font-size:12.5px;width:100%}
.ts-add{display:flex;align-items:center;gap:10px;margin-top:12px;flex-wrap:wrap}

/* Điện thoại: lịch tháng vẫn phải dùng được (docs 00 §5 — yêu cầu bắt buộc) */
@media (max-width:860px){
  .ts-cell{min-height:78px;padding:4px}
  .ts-io,.ts-item-h{display:none}
  .ts-item-name{font-size:10px}
}

/* Trạng thái kỳ chốt tuần (docs 06 §3.2) — dùng lại đúng bảng màu của các pill khác:
   còn ghi được = xám/cam · chờ người khác = vàng · xong = lá · khoá = tím */
.pill.OPEN{background:#2b2f34;color:#9aa4ad}
.pill.REOPENED{background:#4a2b18;color:#fdba74}
.pill.SUBMITTED{background:#3a3320;color:#fde68a}
.pill.LOCKED{background:#2b2140;color:#c9a3ff}
/* "Đã duyệt một phần" (docs 06 §3.2.2) — nhãn SUY RA từ projectApprovals, không
   phải giá trị status thật (kỳ vẫn SUBMITTED bên trong). Cam đậm hơn SUBMITTED
   để phân biệt rõ "chưa ai xử lý" (vàng) với "đã có người xử lý một phần" (cam),
   và khác REOPENED (không còn dùng) dù cùng tông màu. */
.pill.PARTIAL{background:#4a2f12;color:#fb923c}

/* ==================== TIMESHEET · BẢNG CÔNG THÁNG (docs 06 §6.3) ============
   Ma trận nhân viên × ngày — hai cột đầu (Nhân viên/Phòng ban) VÀ hàng tiêu đề
   cùng dính (position:sticky) để cuộn bảng rộng (tới 31 cột ngày + 6 cột tổng)
   mà vẫn biết đang xem dòng/cột nào. z-index xếp lớp: góc trên-trái (dính cả
   hai chiều) > hàng tiêu đề > cột ghim > ô thường. */
.tsm-scroll{flex:1 1 auto;min-height:0;overflow:auto}
.tsm-table{border-collapse:separate;border-spacing:0;font-size:11.5px;white-space:nowrap}
.tsm-table th,.tsm-table td{padding:4px 7px;height:26px;border-bottom:1px solid var(--line);
  border-right:1px solid var(--line)}
.tsm-table thead th{position:sticky;top:0;background:var(--panel);z-index:2;
  color:var(--muted);font-weight:600;text-align:center;font-size:11px}
.tsm-table .tsm-emp{position:sticky;left:0;z-index:1;background:var(--panel2);
  text-align:left;min-width:172px;max-width:172px;overflow:hidden;text-overflow:ellipsis;
  cursor:default}
.tsm-table .tsm-dept{position:sticky;left:172px;z-index:1;background:var(--panel2);
  min-width:60px;max-width:60px;color:var(--muted);text-align:center}
.tsm-table thead .tsm-emp,.tsm-table thead .tsm-dept{z-index:3;background:var(--panel)}
.tsm-table .tsm-day{width:28px;min-width:28px;text-align:center;cursor:pointer;
  color:var(--muted);transition:background .12s}
.tsm-table td.tsm-day{color:var(--txt);font-variant-numeric:tabular-nums}
.tsm-table .tsm-day.weekend{color:var(--muted2)}
.tsm-table .tsm-sum{text-align:right;min-width:70px;font-variant-numeric:tabular-nums}
.tsm-table tbody tr:hover td{background:var(--panel2)}
.tsm-table tbody tr:hover td.tsm-emp,.tsm-table tbody tr:hover td.tsm-dept{background:var(--chip)}
/* Màu ô ngày — CÙNG bảng ngữ nghĩa với `.ts-cell.*` của lịch khai giờ (docs 06 §6.1),
   khai lại riêng vì `.ts-cell` còn mang layout khối (min-height, flex) không hợp ô bảng.
   HAI MÀU cho hai mức "không chuẩn" (docs 06 §5 mở rộng 2026-09): cam (VARIANCE —
   lệch chấm công, HOẶC khớp nhưng thiếu chưa bù đúng đơn nghỉ) → đỏ (EMPTY —
   thiếu một hoặc cả hai phía dữ liệu, nặng nhất). */
.tsm-table td.tsm-day.ok{background:rgba(48,209,88,.09)}
.tsm-table td.tsm-day.variance{background:rgba(255,149,0,.24);color:#ffb454}
.tsm-table td.tsm-day.empty-d{background:rgba(255,59,48,.24);color:var(--out);font-weight:700}
.tsm-table td.tsm-day.leave{background:rgba(50,217,255,.12)}
.tsm-table td.tsm-day.holiday{background:rgba(201,163,255,.15)}
.tsm-table td.tsm-day.locked,.tsm-table td.tsm-day.off{background:var(--bg2)}
.tsm-legend{display:flex;gap:12px;flex-wrap:wrap;margin:0 2px 8px;font-size:11.5px;color:var(--muted)}

/* Quỹ phép công ty (#hr-leave-fund) — chấm tròn tăng/giảm trong ma trận tháng,
   dùng chung khung .tsm-table (sticky header + 2 cột đầu) ở trên. */
.lf-badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;
  padding:0 5px;border-radius:10px;font-size:10.5px;font-weight:700;font-variant-numeric:tabular-nums}
.lf-badge.up{background:rgba(48,209,88,.18);color:#6ee7b7}
.lf-badge.down{background:rgba(255,59,48,.18);color:#fca5a5}
.lf-badge+.lf-badge{margin-left:3px}
.tsm-table .tsm-month{width:66px;min-width:66px;text-align:center}
/* Cột "Phép năm" — số + nút ✎ sửa nhanh (ghi đè tổng, docs 07 §3.2 mở rộng 2026-09) */
.tsm-table .lf-grant-cell{min-width:92px;white-space:nowrap}
.lf-total-num{margin-right:4px}
/* Ma trận Quỹ phép công ty chỉ có 12 cột tháng (ít hơn hẳn lịch ngày của Bảng công
   tháng dùng chung khung .tsm-table) — ép width:100% + table-layout:fixed để bảng
   giãn hết bề ngang thẻ card, CHIA ĐỀU phần dư cho 15 cột dữ liệu (Phép năm, T1-T12,
   Đã dùng, Còn lại — cột nào không khai width sẽ tự chia đều ở layout fixed), còn 2
   cột dính (Nhân sự/Phòng) giữ NGUYÊN bề rộng cũ (khai lại width tường minh vì fixed
   layout không đọc min-width/max-width để định cỡ cột). */
.lf-table{width:100%;table-layout:fixed}
.lf-table .tsm-emp{width:172px}
.lf-table .tsm-dept{width:60px}
.lf-table .tsm-month,
.lf-table .tsm-sum{width:auto}

/* Bảng công tháng (#timesheet-monthly) — CHỈ giãn đều các cột NGÀY (01 → hết
   tháng, 28-31 cột tuỳ tháng) cho full bề ngang thẻ card; 2 cột dính (Nhân
   viên/Phòng) và 6 cột tổng cuối bảng (Giờ khai…OT) giữ NGUYÊN bề rộng cũ —
   khai width tường minh cho các cột đó vì fixed layout không đọc min-width để
   định cỡ, cột nào bỏ trống width (.tsm-day) sẽ tự chia đều phần dư còn lại. */
.tsmm-table{width:100%;table-layout:fixed}
.tsmm-table .tsm-emp{width:172px}
.tsmm-table .tsm-dept{width:60px}
.tsmm-table .tsm-sum{width:112px}
.tsmm-table thead .tsm-sum{white-space:normal;line-height:1.25}
.tsmm-table .tsm-day{width:auto;min-width:0}

/* ============================ PHÂN HỆ NHÂN SỰ ============================
   Màn "của tôi": hồ sơ · bảng công · bảng phép · danh bạ (docs 02 §4.2, §4.3) */

/* Ảnh đại diện thật — cùng kích thước với `.avatar` chữ cái đầu để đổi qua lại
   không làm nhảy bố cục. `object-fit:cover` vì người dùng tải lên ảnh đủ mọi tỉ lệ;
   `contain` sẽ để lại hai dải trống trong khung tròn. */
.avatar-img{border-radius:50%;object-fit:cover;display:block;
  border:1px solid var(--line2);background:var(--panel2)}

.hr-profile-top{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap}
.hr-avatar-box{display:flex;flex-direction:column;align-items:center;gap:8px;flex:0 0 auto}
.hr-avatar-acts{display:flex;gap:6px;flex-wrap:wrap;justify-content:center}

/* Hai cột trên màn rộng, một cột khi hẹp — các thẻ hồ sơ dài ngắn khác nhau nên
   dùng grid thay vì flex để chúng không kéo nhau cao bằng nhau. */
.hr-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(360px,1fr));gap:14px;
  margin-top:14px;align-items:start}

.hr-perm-grid{display:flex;flex-wrap:wrap;gap:6px}

.hr-dir-card{display:flex;gap:12px;align-items:center;padding:12px 14px}
.hr-dir-contact{display:flex;flex-direction:column;gap:1px;margin-top:3px}
.hr-dir-contact a{color:var(--muted)}
.hr-dir-contact a:hover{color:var(--brand)}

/* ---- Lịch tháng của Bảng công ----
   7 cột cố định. Ô cao 64px chứa 4 dòng (ngày · giờ vào-ra · giờ khai · giờ có mặt —
   dòng giờ vào-ra thêm để soi nhanh y hệt ô lịch bên Timesheet, docs 06 §6.1) mà cả
   tháng vẫn nằm gọn trong một màn không phải cuộn — đó là điểm của cái lịch này. */
.hr-cal-head{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:4px}
.hr-cal-head span{text-align:center;font-size:10px;font-weight:700;letter-spacing:.4px;
  color:var(--muted2)}
.hr-cal{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.hr-cal-cell{position:relative;min-height:64px;border-radius:8px;padding:4px 6px;
  background:var(--panel2);border:1px solid var(--line);
  display:flex;flex-direction:column;gap:1px}
.hr-cal-cell .d{font-size:11px;font-weight:700;color:var(--muted)}
.hr-cal-cell .io{font-size:10px;color:var(--muted2);font-variant-numeric:tabular-nums}
.hr-cal-cell .k{font-size:12.5px;font-weight:700;font-variant-numeric:tabular-nums}
.hr-cal-cell .a{font-size:10.5px;color:var(--muted2);font-variant-numeric:tabular-nums}
/* Ngày đệm của tuần đầu/cuối — có ô để lưới thẳng hàng, nhưng không vẽ gì */
.hr-cal-cell.out{background:transparent;border-color:transparent}
.hr-cal-cell.weekend{background:var(--bg2);opacity:.6}
.hr-cal-cell.holiday{background:var(--brand-dim);border-color:var(--brand2)}
.hr-cal-cell.leave{background:#2b2140;border-color:#5b4a86}
/* Cảnh báo thiếu giờ — viền vàng, KHÔNG tô nền: nền vàng cả chục ô thì bảng chói và
   không còn phân biệt được với ngày lễ. */
.hr-cal-cell.warn{border-color:var(--warn)}
.hr-cal-cell.warn .k{color:var(--warn)}
/* Thiếu/không có in-out từ máy chấm công — viền CAM, độc lập với cảnh báo khai giờ
   ở trên (hai nguồn khác nhau, docs 06 §1 — không được lẫn ý nghĩa của nhau). */
.hr-cal-cell.no-inout{border-color:#ff9500}
/* Chưa khai giờ (khai = 0) — số "0" đỏ đậm, khác "khai thiếu một phần" (vàng ở trên)
   vì đây là CHƯA LÀM GÌ, cần chú ý hơn hẳn khai thiếu vài chục phút. */
.hr-cal-cell.k-zero .k{color:var(--out);font-weight:800}
