/* ============================================================
   Dynamik — FILE NÀY SINH RA TỰ ĐỘNG, KHÔNG SỬA TAY.
   Sửa ở mes/src/ rồi chạy: php bin/build-app.php
   ============================================================ */

/* ───── src/css/main.css ───── */
/* ============================================================
   DYNAMIK — Design system: MINIMAL, một typeface
   ------------------------------------------------------------
   Một chữ duy nhất: LEXEND. Trước đây ba chữ (Fraunces serif +
   IBM Plex Sans + IBM Plex Mono) — đẹp nhưng ồn: mỗi khối chữ
   là một giọng khác nhau, mắt phải chuyển liên tục khi quét bảng.
   Lexend được thiết kế cho tốc độ đọc, hợp với màn đọc lướt ở xưởng.

   Số liệu vẫn thẳng cột nhờ font-variant-numeric:tabular-nums, không
   cần font mono riêng. Mã hàng dùng letter-spacing rộng thay cho mono.

   Minimal ở đây nghĩa là: bỏ bóng đổ, chỉ còn đường kẻ tóc; bỏ dải
   màu trang trí; màu chỉ xuất hiện khi nó MANG NGHĨA (trạng thái,
   chuỗi biểu đồ). Không phải "ít tính năng" — là ít trang trí.
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap');

:root{
  /* Neutral CHỌN, không mặc định: xám lệch nhẹ về phía xanh của thương hiệu
     nên nền và accent thuộc cùng một họ. Nhạt hơn bản kraft cũ để bảng dày
     đọc đỡ mỏi, nhưng không phải trắng tinh — trắng tinh chói dưới đèn xưởng. */
  --bg:#f7f8f7; --bg-2:#eef0ef; --panel:#ffffff; --panel-2:#f4f6f5; --card:#ffffff;
  --line:#e2e5e3; --line-2:#cdd2cf;
  --ink:#15201c; --ink-2:#525b57; --ink-3:#7a8480;
  /* Nhận diện thương hiệu */
  --brand:#0f5c4c; --brand-2:#147a63; --brand-soft:#dcece7; --brand-ink:#0b4539; --on-brand:#ffffff;
  /* Hiệu cánh */
  --venture:#1d4a7a; --venture-soft:#dde7f1; --vulcan:#6b2d5b; --vulcan-soft:#f0e0ec;
  /* Trạng thái (kỷ luật BI — an toàn mù màu) */
  --ok:#17864B;   --ok-soft:#e2f1e8;   --ok-ink:#0f6a3a;
  --info:#1F6FEB; --info-soft:#e4eefd; --info-ink:#1657c4;
  --warn:#B5620E; --warn-soft:#fbeddb; --warn-ink:#8f4c07;
  --crit:#B3261E; --crit-soft:#fbe6e4; --crit-ink:#8f1d17;
  --plum:#6b2d5b; --plum-soft:#f0e0ec; --plum-ink:#54234799;
  /* Bảng màu PHÂN LOẠI cho biểu đồ — đã chạy validator của skill dataviz:
     dải sáng ✓ · sàn chroma ✓ · CVD cặp kề tệ nhất ΔE 12.0 protan / 22.9 tritan
     (ngưỡng 8). Thứ tự xen kẽ để hai màu xanh không kề nhau — đảo lại thì tritan
     tụt còn 5.9. ĐỔI MÀU THÌ PHẢI CHẠY LẠI VALIDATOR. */
  --c1:#17a085; --c2:#c9780e; --c3:#2b6fe0; --c4:#a8459a;
  --grid:#eceeed;
  /* Minimal: không bóng đổ. Phân tầng bằng ĐƯỜNG KẺ và KHOẢNG TRẮNG,
     không bằng độ nổi. Giữ tên biến --shadow để không phải sửa 40 chỗ. */
  --shadow:none;
  --r:6px;
  /* Ba biến, một font — giữ tên cũ để mọi quy tắc CSS hiện có vẫn chạy. */
  --f-display:"Lexend",system-ui,-apple-system,"Segoe UI",sans-serif;
  --f-sans:"Lexend",system-ui,-apple-system,"Segoe UI",sans-serif;
  --f-mono:"Lexend",system-ui,ui-monospace,monospace;
}
/* Chặn bằng :not([data-theme="light"]) — người chọn nền sáng thắng cả khi máy
   đang để tối. Nhờ vậy KHÔNG cần một khối [data-theme="light"] nhân bản lại toàn
   bộ bảng màu; trước đây có, và sửa màu ở :root thì nó âm thầm đè lại. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#101312; --bg-2:#161a18; --panel:#1b201e; --panel-2:#232927; --card:#1b201e;
  --line:#2a302d; --line-2:#3b433f;
  --ink:#eef2f0; --ink-2:#a9b3af; --ink-3:#88938e;
  --brand:#3f9c86; --brand-2:#4fb69c; --brand-soft:#123029; --brand-ink:#6fc9b2; --on-brand:#06231d;
  --venture:#6a9ed4; --venture-soft:#16233a; --vulcan:#c07fae; --vulcan-soft:#2c1a28;
  --ok:#28A56A;   --ok-soft:#12291d;   --ok-ink:#4cc98c;
  --info:#4B8AF0; --info-soft:#152238; --info-ink:#7aa9f5;
  --warn:#D9781A; --warn-soft:#2e2210; --warn-ink:#f0a24e;
  --crit:#E24C42; --crit-soft:#2e1513; --crit-ink:#f0786e;
  --plum:#c07fae; --plum-soft:#2c1a28; --plum-ink:#d9a4ca;
  /* Bước lại riêng cho nền tối (KHÔNG đảo màu của nền sáng): ΔE 10.4 protan /
     21.8 tritan trên nền #211e18. */
  --c1:#28a184; --c2:#c67a1c; --c3:#4a86ea; --c4:#bb68a8;
  --grid:#242a27;
  --shadow:none;
}}
:root[data-theme="dark"]{
  --bg:#101312; --bg-2:#161a18; --panel:#1b201e; --panel-2:#232927; --card:#1b201e;
  --line:#2a302d; --line-2:#3b433f;
  --ink:#eef2f0; --ink-2:#a9b3af; --ink-3:#88938e;
  --brand:#3f9c86; --brand-2:#4fb69c; --brand-soft:#123029; --brand-ink:#6fc9b2; --on-brand:#06231d;
  --venture:#6a9ed4; --venture-soft:#16233a; --vulcan:#c07fae; --vulcan-soft:#2c1a28;
  --ok:#28A56A; --ok-soft:#12291d; --ok-ink:#4cc98c;
  --info:#4B8AF0; --info-soft:#152238; --info-ink:#7aa9f5;
  --warn:#D9781A; --warn-soft:#2e2210; --warn-ink:#f0a24e;
  --crit:#E24C42; --crit-soft:#2e1513; --crit-ink:#f0786e;
  --plum:#c07fae; --plum-soft:#2c1a28; --plum-ink:#d9a4ca;
  /* Bước lại riêng cho nền tối (KHÔNG đảo màu của nền sáng): ΔE 10.4 protan /
     21.8 tritan trên nền #211e18. */
  --c1:#28a184; --c2:#c67a1c; --c3:#4a86ea; --c4:#bb68a8;
  --grid:#242a27; --shadow:none;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--ink);font-family:var(--f-sans);font-size:13px;line-height:1.5;
  -webkit-font-smoothing:antialiased}
.num,.tnum{font-variant-numeric:tabular-nums;letter-spacing:0;font-weight:500}
a{color:var(--brand-2)}
/* Một typeface nên phân cấp phải do CỠ và ĐẬM gánh, không do đổi chữ. */
h1,h2,h3,.disp{font-family:var(--f-display);font-weight:600;letter-spacing:-.35px}
h1{font-weight:600}
/* Mã hàng, mã lệnh: không còn font mono, dùng chữ thưa + đậm vừa để vẫn
   nhận ra là "mã" chứ không phải chữ thường. */
.code,.ent-code,.ent>b.code{font-family:var(--f-sans);font-weight:600;
  letter-spacing:.4px;font-variant-numeric:tabular-nums}

/* ---------- Layout ----------
   Thanh trên cố định + (menu bên · vùng nội dung). Phân hệ ở thanh trên, mục của
   phân hệ ở thanh bên: 23 mục đổ hết vào một sidebar phẳng thì phải cuộn mới thấy
   hết, và mục cấp quyền lẫn vào nhóm phân tích nên không ai tìm ra. */
.app{display:flex;flex-direction:column;min-height:100vh}
.shell{display:grid;grid-template-columns:216px 1fr;flex:1;min-height:0}
.side{background:var(--panel);border-right:1px solid var(--line);padding:12px 10px;
  display:flex;flex-direction:column;gap:2px;position:sticky;top:var(--toph);
  height:calc(100vh - var(--toph));overflow-y:auto}
.side-foot{padding:10px 6px 0;border-top:1px solid var(--line);font-size:10px}

/* ── Thanh trên ── */
:root{--toph:54px}
.top{position:sticky;top:0;z-index:40;height:var(--toph);flex:none;
  display:flex;align-items:center;gap:14px;padding:0 14px 0 12px;
  background:var(--panel);border-bottom:1px solid var(--line)}
.mods{display:flex;gap:2px;align-items:center;min-width:0;overflow-x:auto;scrollbar-width:none}
.mods::-webkit-scrollbar{display:none}
.mod{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  padding:7px 11px;border-radius:var(--r);border:1px solid transparent;background:none;
  color:var(--ink-2);font:600 12.5px/1 var(--f-sans);cursor:pointer}
.mod:hover{background:var(--panel-2);color:var(--ink)}
.mod.on{background:var(--brand-soft);color:var(--brand-ink)}
.mod .ico{width:14px;height:14px}
.mod .bdg{font:700 10px/1 var(--f-mono);padding:2px 5px;border-radius:20px;
  background:var(--crit-soft);color:var(--crit-ink)}

/* Ô tìm kiếm toàn cục: trông như input nhưng là button — bấm mới mở hộp thoại,
   nên không nuốt phím tab và không cần giữ trạng thái ở thanh trên. */
.omni{flex:1;max-width:420px;min-width:0;display:flex;align-items:center;gap:8px;
  padding:7px 11px;border:1px solid var(--line-2);border-radius:var(--r);
  background:var(--bg-2);color:var(--ink-3);font:400 12px/1 var(--f-sans);cursor:pointer;
  text-align:left}
.omni:hover{border-color:var(--brand);color:var(--ink-2)}
.omni span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.omni kbd{font:600 10px/1 var(--f-mono);padding:3px 5px;border-radius:4px;
  background:var(--panel-2);border:1px solid var(--line);color:var(--ink-3);flex:none}

.top-r{display:flex;align-items:center;gap:8px;margin-left:auto;flex:none}
.ico-btn{width:30px;height:30px;display:grid;place-items:center;border-radius:8px;
  border:1px solid var(--line-2);background:var(--card);color:var(--ink-2);
  cursor:pointer;font:600 13px/1 var(--f-sans);text-decoration:none}
.ico-btn:hover{border-color:var(--brand);color:var(--brand)}
.ico-btn .ico{width:14px;height:14px}

/* Ngữ cảnh xưởng: nút + menu thả xuống */
.wsx{display:inline-flex;align-items:center;gap:7px;padding:6px 10px;border-radius:var(--r);
  border:1px solid var(--line-2);background:var(--card);color:var(--ink);cursor:pointer;
  font:600 12px/1 var(--f-sans)}
.wsx:hover{border-color:var(--brand)}
.wsx .dot{width:8px;height:8px;border-radius:2px;flex:none}
.wsx .ico{width:12px;height:12px;transform:rotate(90deg);opacity:.6}
.wsw{position:relative}
.wsmenu{position:absolute;right:0;top:calc(100% + 6px);min-width:200px;z-index:50;
  background:var(--card);border:1px solid var(--line-2);border-radius:var(--r);
  box-shadow:0 10px 28px rgba(0,0,0,.14);padding:5px}
.wsmenu a{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:7px;
  text-decoration:none;color:var(--ink-2);font:600 12.5px/1 var(--f-sans)}
.wsmenu a:hover{background:var(--panel-2);color:var(--ink)}
.wsmenu a.on{background:var(--brand-soft);color:var(--brand-ink)}
.wsmenu .dot{width:8px;height:8px;border-radius:2px;flex:none}

/* Người đang đăng nhập */
.who-btn{display:flex;align-items:center;gap:8px;padding:4px 8px 4px 4px;border-radius:var(--r);
  border:1px solid transparent;background:none;cursor:pointer;color:inherit;max-width:190px}
.who-btn:hover{background:var(--panel-2)}
.who-av{width:26px;height:26px;border-radius:7px;flex:none;display:grid;place-items:center;
  background:var(--brand-soft)}
.who-av .ico{width:14px;height:14px;color:var(--brand-ink)}
.who-nm{min-width:0;text-align:left}
.who-nm b{display:block;font:600 12px/1.25 var(--f-sans);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.who-nm span{display:block;font-size:10px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#who{position:relative}
.who-menu{position:absolute;right:0;top:calc(100% + 6px);min-width:230px;z-index:50;
  background:var(--card);border:1px solid var(--line-2);border-radius:var(--r);
  box-shadow:0 10px 28px rgba(0,0,0,.14);padding:5px}
.who-hd{padding:9px 10px;border-bottom:1px solid var(--line);margin-bottom:4px}
.who-hd b{display:block;font:600 12.5px/1.3 var(--f-sans)}
.who-hd span{font-size:10.5px;color:var(--ink-3)}
.who-mi{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;border-radius:7px;
  border:0;background:none;color:var(--ink-2);font:500 12.5px/1 var(--f-sans);cursor:pointer;text-align:left}
.who-mi:hover{background:var(--panel-2);color:var(--ink)}
.who-mi.warn{color:var(--warn-ink);font-weight:700}
.who-mi .ico{width:14px;height:14px}

/* Đường dẫn phân cấp */
.crumb{font-size:10.5px;text-transform:uppercase;letter-spacing:.9px;color:var(--ink-3);
  font-weight:700;margin-bottom:4px}
.crumb i{font-style:normal;opacity:.45;margin:0 3px}

/* Hộp tìm kiếm toàn cục */
.omni-box{min-width:min(560px,86vw)}
.omni-box input{width:100%;padding:12px 13px;font-size:14.5px;border-radius:9px;
  border:1px solid var(--line-2);background:var(--bg-2);color:var(--ink)}
.omni-res{margin-top:9px;max-height:52vh;overflow-y:auto}
.omni-hit{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:8px;
  text-decoration:none;color:var(--ink-2)}
.omni-hit:hover,.omni-hit.on{background:var(--panel-2);color:var(--ink)}
.omni-hit b{font-family:var(--f-mono);font-size:12.5px}
.omni-hit .muted{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.omni-tip{margin-top:8px;font-size:10.5px;color:var(--ink-3);text-align:right}

.brand{display:flex;align-items:center;gap:9px;flex:none;text-decoration:none;color:inherit;
  padding-right:6px;border-right:1px solid var(--line);margin-right:2px}
.brand .mk{width:30px;height:30px;border-radius:8px;flex:none;display:grid;place-items:center;color:#fff;
  font-family:var(--f-display);font-weight:700;font-size:17px;
  background:var(--brand)}
.brand b{font-family:var(--f-display);font-size:15px;display:block;line-height:1.1}
.brand span{font-size:9px;color:var(--ink-3);letter-spacing:.4px;text-transform:uppercase}

.nav-sec{font-size:9.5px;text-transform:uppercase;letter-spacing:.7px;color:var(--ink-3);font-weight:700;padding:10px 8px 4px}
.nv{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:var(--r);text-decoration:none;
  color:var(--ink-2);font-weight:500;font-size:12.5px}
.nv:hover{background:var(--panel-2);color:var(--ink)}
.nv.on{background:var(--brand-soft);color:var(--brand-ink);font-weight:700}
.nv .ic{width:17px;text-align:center;flex:none;opacity:.9}
.nv .bdg{margin-left:auto;font-family:var(--f-mono);font-size:10px;font-weight:700;padding:1px 6px;border-radius:20px;
  background:var(--crit-soft);color:var(--crit-ink)}

/* min-width:0 là bắt buộc: .main là ô của lưới .shell nên mặc định có sàn
   min-width:auto = min-content của nội dung. Một bảng rộng hơn màn hình sẽ nong
   ô này ra tới max-width rồi đẩy CẢ TRANG cuộn ngang, thay vì để .tw tự cuộn
   trong khung như thiết kế. */
.main{padding:18px 22px 52px;max-width:1560px;min-width:0}
.hdr{display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap;padding-bottom:13px;margin-bottom:16px;
  border-bottom:1px solid var(--line)}
.hdr h1{font-size:23px;margin:0}
.hdr .sub{font-size:12.5px;color:var(--ink-2);margin-top:3px;max-width:78ch}
.hdr .sp{flex:1}
.eyebrow{font-size:10px;text-transform:uppercase;letter-spacing:1.1px;color:var(--brand-2);font-weight:700;margin-bottom:3px}

/* ---------- Nút, input ---------- */
.btn{font-family:inherit;font-size:12.5px;font-weight:600;padding:7px 13px;border-radius:var(--r);cursor:pointer;
  border:1px solid var(--line-2);background:var(--panel);color:var(--ink-2);transition:.15s}
.btn:hover{border-color:var(--brand);color:var(--brand-2)}
.btn.pri{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.btn.pri:hover{background:var(--brand-2);color:var(--on-brand)}
.btn.dgr{color:var(--crit-ink);border-color:var(--crit)}
.btn.sm{padding:4px 9px;font-size:11.5px}
.btn:disabled{opacity:.45;cursor:not-allowed}
input,select,textarea{font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--panel);
  border:1px solid var(--line-2);border-radius:6px;padding:6px 9px;outline:none}
input:focus,select:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
input[type=checkbox]{width:15px;height:15px;accent-color:var(--brand)}
label.fld{display:flex;flex-direction:column;gap:4px;font-size:10px;text-transform:uppercase;letter-spacing:.6px;
  color:var(--ink-3);font-weight:700}
.toolbar{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;margin-bottom:14px}
.seg{display:inline-flex;background:var(--panel);border:1px solid var(--line-2);border-radius:var(--r);padding:3px;gap:2px}
.seg button{font-family:inherit;font-size:12px;font-weight:600;color:var(--ink-2);background:none;border:0;
  border-radius:5px;padding:5px 11px;cursor:pointer}
.seg button[aria-pressed="true"]{background:var(--brand);color:var(--on-brand)}

/* ---------- Card / KPI ---------- */
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:15px 17px}
.card h2{font-size:15px;margin:0 0 2px}
.card .hs{font-size:11.5px;color:var(--ink-3);margin-bottom:12px}
.row{display:grid;gap:13px;margin-bottom:15px}
/* Ô lưới mặc định lấy min-content làm sàn chiều rộng, nên MỘT nhãn dài trong một
   ô KPI là đủ đẩy cả cột nội dung rộng ra và làm cả trang cuộn ngang. Nhãn có thể
   đến từ dữ liệu (tên công đoạn lấy thẳng từ Google Sheet), không kiểm soát được
   độ dài — nên chặn ở đây thay vì mong nhãn lúc nào cũng ngắn. */
.row>*{min-width:0}
.kpi .kl>span.kt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.k6{grid-template-columns:repeat(6,1fr)}.k5{grid-template-columns:repeat(5,1fr)}
.k4{grid-template-columns:repeat(4,1fr)}.k3{grid-template-columns:repeat(3,1fr)}.k2{grid-template-columns:repeat(2,1fr)}
.kpi .kl{font-size:11px;color:var(--ink-2);font-weight:600;display:flex;align-items:center;gap:6px}
.kpi .kv{font-family:var(--f-display);font-size:28px;font-weight:600;margin-top:5px;line-height:1;letter-spacing:-.5px}
.kpi .ks{font-size:11px;color:var(--ink-3);margin-top:5px}
.kpi .kb{height:3px;border-radius:3px;margin-top:10px;background:var(--grid);overflow:hidden}
.kpi .kb>i{display:block;height:100%;border-radius:3px}
.sw{width:9px;height:9px;border-radius:2px;flex:none}

/* ---------- Icon (bộ Lucide — ISC, sprite cục bộ) ---------- */
.ico{width:15px;height:15px;flex:none;vertical-align:-3px;stroke-width:2}
.ico.lg{width:24px;height:24px;vertical-align:-5px}
.ico.sm{width:13px;height:13px;vertical-align:-2px}
.nv .ic{display:inline-flex;align-items:center;justify-content:center;width:17px}
.nv .ico{width:15px;height:15px;vertical-align:0}
.wsico{display:inline-flex;align-items:center}
.btn .ico{margin-right:4px;vertical-align:-2.5px}
.btn.sm .ico{width:13px;height:13px;margin-right:3px}
.alert b .ico,.note .ico{vertical-align:-3px;margin-right:5px}
.tag .ico{width:11px;height:11px;vertical-align:-1.5px;margin-right:2px}
#thm{display:inline-grid;place-items:center;width:34px;height:32px;padding:0}
#thm .ico{margin:0;vertical-align:0}

/* ---------- Bảng (kỷ luật BI) ---------- */
.tw{overflow-x:auto}
table.t{width:100%;border-collapse:collapse;font-size:12.5px}
table.t th{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--ink-3);
  font-weight:700;padding:8px 9px;border-bottom:2px solid var(--line);position:sticky;top:0;background:var(--panel);z-index:1;white-space:nowrap}
table.t td{padding:8px 9px;border-bottom:1px solid var(--line);vertical-align:middle}
table.t th.n,table.t td.n{text-align:right}
table.t tbody tr:hover{background:var(--panel-2)}
table.t tr.sel{background:var(--brand-soft)}
.code{font-family:var(--f-mono);font-weight:600;color:var(--ink)}
.muted{color:var(--ink-3)}
.empty{text-align:center;padding:28px;color:var(--ink-3)}

/* ---------- Nhãn ---------- */
.pill{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;padding:3px 9px;border-radius:20px;white-space:nowrap}
.pill .pd{width:7px;height:7px;border-radius:50%}
.p-ok{background:var(--ok-soft);color:var(--ok-ink)}     .p-info{background:var(--info-soft);color:var(--info-ink)}
.p-warn{background:var(--warn-soft);color:var(--warn-ink)} .p-crit{background:var(--crit-soft);color:var(--crit-ink)}
.p-plum{background:var(--plum-soft);color:var(--plum-ink)} .p-gray{background:var(--panel-2);color:var(--ink-2);border:1px solid var(--line-2)}
.p-ven{background:var(--venture-soft);color:var(--venture)} .p-vul{background:var(--vulcan-soft);color:var(--vulcan)}
.tag{display:inline-block;font-family:var(--f-mono);font-size:10px;font-weight:600;padding:2px 6px;border-radius:4px;
  background:var(--panel-2);border:1px solid var(--line);color:var(--ink-2)}

/* ---------- Thanh tiến độ ---------- */
.bar{position:relative;background:var(--grid);border-radius:4px;height:18px;min-width:76px}
.bar>i{position:absolute;left:0;top:0;height:100%;border-radius:4px;min-width:2px;transition:width .3s}
.bar>span{position:absolute;inset:0;display:grid;place-items:center;font-family:var(--f-mono);font-size:10.5px;font-weight:600;color:var(--ink)}
.barw{display:flex;flex-direction:column;gap:8px}
.brow{display:grid;grid-template-columns:140px 1fr;gap:10px;align-items:center}
.brow .bl{font-size:11.5px;font-weight:600;color:var(--ink-2);text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------- Dây chuyền công đoạn ---------- */
.line{display:grid;gap:0;margin-top:6px}
.lstep{position:relative;padding:0 11px}
.lstep:not(:last-child)::after{content:"";position:absolute;right:-5px;top:36px;width:7px;height:7px;
  border-top:2px solid var(--ink-3);border-right:2px solid var(--ink-3);transform:rotate(45deg)}
.lbox{border:1px solid var(--line);border-top:3px solid var(--c);border-radius:9px;background:var(--panel-2);padding:12px 13px;height:100%}
.lnum{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:5px;
  background:var(--c);color:#fff;font-family:var(--f-mono);font-weight:700;font-size:10.5px}
.ltitle{font-family:var(--f-display);font-weight:600;font-size:13.5px;margin-left:7px}
.lrole{font-size:10.5px;color:var(--ink-2);margin:8px 0 10px;min-height:30px}
.lmetric{display:flex;align-items:baseline;gap:5px}
.lmetric b{font-family:var(--f-display);font-size:22px;font-weight:600}
.lmetric span{font-size:10.5px;color:var(--ink-3)}
.lcap{font-size:10.5px;color:var(--ink-3);margin-top:7px;border-top:1px dashed var(--line);padding-top:6px}

/* ---------- Thẻ xưởng ở trang tổng quan ---------- */
.wsgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:16px}
.wscard{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--c);border-radius:var(--r);
  box-shadow:var(--shadow);padding:16px 18px;text-decoration:none;color:inherit;display:block;transition:.15s}
.wscard:hover{border-color:var(--c)}
.wscard h3{font-size:17px;margin:0 0 3px}
.wscard .u{font-size:10.5px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.6px}
.wsstats{display:grid;grid-template-columns:repeat(2,1fr);gap:9px;margin:13px 0 11px}
.wsstats div{background:var(--panel-2);border:1px solid var(--line);border-radius:6px;padding:7px 9px}
.wsstats .l{font-size:10px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.4px}
.wsstats .v{font-family:var(--f-mono);font-size:16px;font-weight:600;margin-top:2px}
.wschain{display:flex;gap:5px;flex-wrap:wrap}
.wschain span{font-size:10px;padding:2px 7px;border-radius:20px;background:var(--panel-2);border:1px solid var(--line);color:var(--ink-2)}

/* ---------- Cảnh báo ---------- */
.alert{border:1px solid var(--crit);background:var(--crit-soft);color:var(--crit-ink);border-radius:9px;
  padding:12px 14px;margin-bottom:13px;font-size:12.5px}
.alert b{display:block;margin-bottom:4px;font-family:var(--f-display)}
.alert ul{margin:5px 0 0;padding-left:18px}
.alert.warn{border-color:var(--warn);background:var(--warn-soft);color:var(--warn-ink)}
.note{border:1px solid var(--line);background:var(--panel-2);border-radius:9px;padding:11px 13px;
  font-size:12px;color:var(--ink-2);margin-bottom:13px}
.note b{color:var(--ink)}

/* ---------- Modal / toast ---------- */
.ovl{position:fixed;inset:0;background:rgba(20,16,10,.6);display:grid;place-items:center;z-index:80;padding:20px}
.modal{background:var(--panel);border:1px solid var(--line-2);border-radius:10px;box-shadow:0 16px 48px rgba(0,0,0,.18);
  width:min(580px,100%);max-height:86vh;overflow:auto;padding:20px 22px}
.modal h3{margin:0 0 3px;font-size:17px}
.modal .ms{font-size:11.5px;color:var(--ink-3);margin-bottom:15px}
.mgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:15px}
.mact{display:flex;gap:9px;justify-content:flex-end;border-top:1px solid var(--line);padding-top:14px}
#toast{position:fixed;right:16px;bottom:16px;z-index:90;display:flex;flex-direction:column;gap:8px}
.tst{background:var(--ink);color:var(--bg);padding:10px 15px;border-radius:8px;font-size:12.5px;font-weight:600;
  box-shadow:0 8px 24px rgba(0,0,0,.16);max-width:360px;animation:sl .22s ease}
.tst.ok{background:var(--ok);color:#fff} .tst.err{background:var(--crit);color:#fff}
@keyframes sl{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.spin{display:inline-block;width:13px;height:13px;border:2px solid var(--line-2);border-top-color:var(--brand);
  border-radius:50%;animation:sp .7s linear infinite;vertical-align:-2px}
@keyframes sp{to{transform:rotate(360deg)}}

@media (max-width:1180px){.k6,.k5{grid-template-columns:repeat(3,1fr)}.k4{grid-template-columns:repeat(2,1fr)}
  .wsgrid{grid-template-columns:1fr}}
@media (max-width:1080px){.omni span{display:none}.omni{flex:none;max-width:44px;justify-content:center}
  .brand span{display:none}}
@media (max-width:900px){
  /* Thanh trên cao gấp đôi và xuống hàng: phân hệ cần chỗ, không được nuốt mất
     ô tìm kiếm hay nút người dùng. */
  :root{--toph:100px}
  .top{flex-wrap:wrap;height:auto;min-height:var(--toph);padding:8px 12px;row-gap:8px}
  .mods{order:3;width:100%}
  .top-r{order:2}
  .shell{grid-template-columns:1fr}
  /* Menu thành MỘT HÀNG cuộn ngang, không xuống dòng. Trước đây 8 mục xếp dọc
     chiếm gần hết màn điện thoại: thợ mở màn Chấm công phải cuộn qua cả menu mới
     thấy cái nút — đúng thứ giết một màn hình được thiết kế để bấm trong 3 giây. */
  .side{position:static;height:auto;flex-direction:row;flex-wrap:nowrap;border-right:0;
    border-bottom:1px solid var(--line);padding:7px 10px;overflow-x:auto;
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .side::-webkit-scrollbar{display:none}
  .side #nav{display:flex;flex-direction:row;gap:6px;flex:none}
  .side .nv{white-space:nowrap;flex:none;padding:7px 11px}
  .side .nv .bdg{margin-left:5px}
  .side-foot{display:none}
  .k6,.k5,.k4,.k3,.k2{grid-template-columns:repeat(2,1fr)}.mgrid{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ---------- Bảng kế hoạch sản xuất theo đơn (nhóm cột như sheet) ---------- */
table.t.plan{font-size:11.5px}
table.t.plan th,table.t.plan td{padding:6px 7px;white-space:nowrap}
table.t.plan tr.grp th{font-size:10px;text-transform:uppercase;letter-spacing:.6px;text-align:center;
  border-bottom:2px solid var(--line-2);padding:5px 7px;color:#fff}
table.t.plan tr.grp th.g0{background:var(--ink-3)}
table.t.plan tr.grp th.g1{background:var(--brand)}
table.t.plan tr.grp th.g2{background:var(--warn)}
table.t.plan tr.grp th.g3{background:var(--plum)}
table.t.plan tr.grp th.g4{background:var(--info)}
table.t.plan tr.grp th.g5{background:var(--vulcan)}
/* Chữ trên dải màu đậm: dùng trắng cố định vì các dải này luôn đậm ở cả 2 nền */
table.t.plan tr.grp th.g0,table.t.plan tr.grp th.g1,table.t.plan tr.grp th.g2,
table.t.plan tr.grp th.g3,table.t.plan tr.grp th.g4,table.t.plan tr.grp th.g5{color:#fff}
table.t.plan thead tr:nth-child(2) th{top:27px}
table.t.plan input{padding:3px 6px;font-size:11px}
.ico.rot{transform:rotate(90deg)}
tr.plan-row td{border-bottom:2px solid var(--line-2)}

/* ---------- Màn hình CÔNG NHÂN: to, đơn giản, bấm được bằng ngón tay ---------- */
.wk{max-width:640px}
.wk-head{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--brand);
  border-radius:var(--r);padding:14px 16px;margin-bottom:14px;box-shadow:var(--shadow)}
.wk-code{font-family:var(--f-display);font-size:22px;font-weight:600;letter-spacing:-.3px}
.wk-sub{font-size:12.5px;color:var(--ink-2);margin-top:3px}
.wk-row{display:flex;align-items:center;gap:14px;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r);padding:14px 16px;margin-bottom:10px;box-shadow:var(--shadow)}
.wk-label{flex:1;font-size:15px;font-weight:600;line-height:1.35}
.wk-label span{display:block;font-size:12px;color:var(--ink-3);font-weight:400;margin-top:2px}
.wk-in{width:118px;flex:none;font-family:var(--f-mono);font-size:30px;font-weight:600;text-align:center;
  padding:10px 8px;border:2px solid var(--line-2);border-radius:var(--r)}
.wk-in:focus{border-color:var(--brand);box-shadow:0 0 0 4px var(--brand-soft)}
.wk-foot{display:flex;gap:12px;margin:14px 0 12px;flex-wrap:wrap}
.wk-send{width:100%;padding:18px;font-family:var(--f-display);font-size:20px;font-weight:700;letter-spacing:.5px;
  color:var(--on-brand);background:var(--brand);border:0;border-radius:var(--r);cursor:pointer;box-shadow:var(--shadow)}
.wk-send:hover{background:var(--brand-2)}
.wk-send:disabled{opacity:.6;cursor:not-allowed}
.wk-send .ico{width:22px;height:22px;vertical-align:-4px;margin-right:6px}
.wk-card{display:flex;align-items:center;gap:12px;background:var(--panel);border:1px solid var(--line);
  border-left:4px solid var(--warn);border-radius:var(--r);padding:15px 17px;margin-bottom:11px;
  text-decoration:none;color:inherit;box-shadow:var(--shadow);max-width:640px}
.wk-card:hover{border-color:var(--warn);transform:translateY(-1px)}
.wk-go{color:var(--ink-3);display:flex}
@media (max-width:620px){.wk-row{flex-wrap:wrap}.wk-in{width:100%;font-size:34px}}

/* ═══════════ MÀN HÌNH ĐĂNG NHẬP ═══════════
   Bàn số PIN cố ý to: công nhân bấm bằng ngón tay trên máy tính bảng ở xưởng,
   không phải trỏ chuột. Nút tối thiểu 64px cho ngón tay có găng. */
#gate{position:fixed;inset:0;z-index:80;display:grid;place-items:center;padding:20px;
  background:var(--bg);overflow:auto}
.gate-card{width:100%;max-width:430px;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r);padding:26px;box-shadow:var(--shadow)}
.gate-hd{display:flex;gap:12px;align-items:center;margin-bottom:20px}
.gate-hd .mk{width:40px;height:40px;border-radius:11px;background:var(--brand);color:var(--on-brand);
  display:grid;place-items:center;font:700 20px/1 var(--f-display)}
.gate-hd b{display:block;font:600 19px/1.2 var(--f-display);letter-spacing:.2px}
.gate-hd span{font-size:12px;color:var(--ink-3)}
.gate-p{font-size:13px;color:var(--ink-3);margin:0 0 12px}
.gate-err{margin-top:14px;padding:10px 12px;border-radius:9px;font-size:13px;
  background:color-mix(in srgb,var(--crit) 12%,transparent);color:var(--crit);
  border:1px solid color-mix(in srgb,var(--crit) 30%,transparent)}
.gate-who{display:grid;gap:8px;max-height:46vh;overflow:auto}
/* <button> KHÔNG thừa hưởng color/font từ body — thiếu 2 dòng này là chữ dùng màu
   mặc định của nút (gần đen) trên nền tối, đọc không nổi. */
.gate-who .who{text-align:left;padding:15px 16px;border:1px solid var(--line);border-radius:11px;
  background:var(--panel);cursor:pointer;display:block;width:100%;
  color:var(--ink);font-family:var(--f-sans)}
.gate-who .who:hover{border-color:var(--brand);background:var(--bg-2)}
.gate-who .who b{display:block;font:600 16px/1.3 var(--f-sans)}
.gate-who .who span{font-size:12px;color:var(--ink-2)}
.btn.big{padding:15px;font-size:15px;width:100%;justify-content:center;margin-top:6px}

/* chip người đang đăng nhập, đáy thanh bên.
   Tên một dòng, hai nút xuống dòng dưới: thanh bên hẹp, nhồi ngang là cắt mất tên. */
.who-chip{padding:9px 8px;margin-top:8px;border-top:1px solid var(--line)}
.who-top{display:flex;gap:9px;align-items:center}
.who-top .ic{width:30px;height:30px;border-radius:9px;background:var(--bg-2);display:grid;
  place-items:center;flex:0 0 auto}
.who-top .ic .ico{width:15px;height:15px;color:var(--brand)}
.who-top>div{min-width:0;flex:1}
.who-chip b{display:block;font:600 12px/1.3 var(--f-sans);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.who-chip span{font-size:10px;color:var(--ink-3)}
.who-act{display:flex;gap:6px;margin-top:8px}
.who-act .btn{flex:1;justify-content:center;padding:6px 4px;font-size:10.5px;gap:4px;
  white-space:nowrap}
/* "Đổi mật khẩu" dài hơn "Đổi mã" cũ nên gãy hai dòng trong thanh bên hẹp. Cho nút
   mật khẩu rộng gấp đôi nút Thoát thay vì chia đều — Thoát chỉ cần vừa chữ. */
.who-act .btn:first-child{flex:2}
.who-act .btn .ico{width:12px;height:12px}
/* Ai đang đăng nhập — thay cho ô "gõ tên bạn" ở phiếu giao/nhận */
.wk-me{display:flex;gap:7px;align-items:center;font-size:13px;color:var(--ink-3);
  padding:9px 12px;background:var(--bg-2);border-radius:9px}
.wk-me .ico{width:15px;height:15px;color:var(--brand)}
.wk-me b{color:var(--ink)}

/* Ô nhập trong màn hình đăng nhập và trong modal: to hơn mặc định của bảng biểu.
   Mặc định input 12.5px/padding 6px là cho bảng dữ liệu dày — gõ mật khẩu hoặc
   bấm trên máy tính bảng thì quá nhỏ. */
.gate-card label.fld{gap:6px;margin-bottom:12px;font-size:10.5px}
.gate-card label.fld input{width:100%;padding:12px;font-size:15px;border-radius:9px}
.modal label.fld{gap:6px;margin-bottom:11px}
.modal label.fld input,.modal label.fld select{width:100%;padding:9px 11px;font-size:13.5px;border-radius:7px}

/* Ô hiện mã nhân viên đang gõ (bước 1 của bàn số) */

/* ═══════════ MÀN HÌNH HƯỚNG DẪN ═══════════ */
.gd-top{display:flex;gap:20px;align-items:center;justify-content:space-between;flex-wrap:wrap;
  padding:18px 20px;border-radius:var(--r);margin-bottom:16px;border:1px solid var(--line)}
.gd-top.ok{background:var(--ok-soft);border-color:var(--ok)}
.gd-top.no{background:var(--warn-soft);border-color:var(--warn)}
.gd-top-k{font:700 15px/1.3 var(--f-sans);letter-spacing:.3px}
.gd-top.ok .gd-top-k{color:var(--ok-ink)} .gd-top.no .gd-top-k{color:var(--warn-ink)}
.gd-top-s{font-size:12.5px;color:var(--ink-2);margin-top:4px;max-width:62ch}
.gd-top-n{display:flex;gap:18px;flex-wrap:wrap}
.gd-top-n>div{text-align:right}
.gd-top-n b{display:block;font:700 20px/1 var(--f-mono)}
.gd-top-n span{font-size:10px;color:var(--ink-2)}

.gd-what h2{font:600 16px/1.3 var(--f-display);margin:0 0 8px}
.gd-what p{font-size:13.5px;line-height:1.65;color:var(--ink-2);margin:0 0 14px;max-width:82ch}
.gd-flow{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.gd-flow span{font-size:11.5px;padding:5px 10px;border-radius:20px;background:var(--bg-2);
  border:1px solid var(--line);white-space:nowrap}
.gd-flow span.hi{background:var(--brand);color:var(--on-brand);border-color:var(--brand);font-weight:600}
.gd-flow .ico{width:12px;height:12px;color:var(--ink-3);flex:none}
.gd-note{font-size:12px;color:var(--ink-2);padding:10px 12px;background:var(--bg-2);border-radius:9px}

.gd-h{font:600 15px/1.3 var(--f-display);margin:22px 0 10px;display:flex;gap:9px;align-items:baseline}
.gd-h span{font:400 11.5px/1 var(--f-sans);color:var(--ink-3);text-transform:none;letter-spacing:0}

.gd-steps{display:grid;gap:8px}
.gd-step{display:flex;gap:14px;align-items:flex-start;padding:14px 16px;background:var(--panel);
  border:1px solid var(--line);border-radius:var(--r)}
.gd-step.nx{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.gd-step.todo .gd-no{background:var(--crit-soft);color:var(--crit-ink)}
.gd-step.warn .gd-no{background:var(--warn-soft);color:var(--warn-ink)}
.gd-step.ok   .gd-no{background:var(--ok-soft);color:var(--ok-ink)}
.gd-no{width:28px;height:28px;border-radius:8px;display:grid;place-items:center;flex:none;
  font:700 14px/1 var(--f-mono)}
.gd-body{flex:1;min-width:0}
.gd-hd{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.gd-hd b{font:600 13.5px/1.3 var(--f-sans)}
.gd-val{display:flex;gap:6px;align-items:center;font:500 12px/1.4 var(--f-mono);color:var(--ink-2);margin-top:5px}
.gd-val .ico{width:13px;height:13px;flex:none}
.gd-why{font-size:12px;line-height:1.6;color:var(--ink-2);margin:6px 0 0;max-width:88ch}
.gd-step .btn{flex:none;align-self:center}

.gd-day{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px}
.gd-day>div{padding:14px 15px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r)}
.gd-when{font:700 9.5px/1 var(--f-sans);letter-spacing:.7px;text-transform:uppercase;color:var(--brand-ink);
  margin-bottom:7px}
.gd-day b{font:600 13.5px/1.3 var(--f-sans)}
.gd-day p{font-size:12px;line-height:1.6;color:var(--ink-2);margin:6px 0 0}

.gd-auto{display:grid;grid-template-columns:repeat(auto-fit,minmax(255px,1fr));gap:10px}
.gd-auto>div{padding:13px 15px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r)}
.gd-auto .ico{width:16px;height:16px;color:var(--brand);margin-bottom:7px}
.gd-auto b{display:block;font:600 12.5px/1.35 var(--f-sans)}
.gd-auto span{display:block;font-size:11.5px;line-height:1.55;color:var(--ink-2);margin-top:4px}

.gd-bad{margin:0;padding:0 0 0 22px;display:grid;gap:8px}
.gd-bad li{font-size:12.5px;line-height:1.6;color:var(--ink-2)}
.gd-bad b{color:var(--crit-ink)}
/* Hai cột quyết định trên bảng Kế hoạch: "Từ Bán TP" và "Net làm từ đầu" */
table.t th.bd,table.t td.bd{border-left:2px solid var(--line-2)}
table.t td.bd{background:var(--bg-2)}
/* Cột "Đang làm ở lệnh nào" trên bảng Kế hoạch: mỗi PO một dòng nhỏ */
.po-mini{display:flex;gap:6px;align-items:center;flex-wrap:wrap;font-size:11px;
  padding:3px 0;white-space:nowrap}
.po-mini+.po-mini{border-top:1px dashed var(--line)}
.po-mini .code{font-size:11.5px}
.po-q{font-family:var(--f-mono);color:var(--ink-2)}
.po-eta{color:var(--ink-3)}
/* Mã PO trong bảng kế hoạch của đơn — bấm được */
.po-tag{text-decoration:none;border-color:var(--brand);color:var(--brand-ink);font-weight:600}
.po-tag:hover{background:var(--brand-soft)}

/* ── Tiến độ đơn hàng ── */
.pv-top { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 12px; }
.pv-t { border: 1px solid var(--line); border-left: 3px solid var(--c); border-radius: 6px;
        background: var(--card); padding: 12px 14px; }
.pv-n { font-size: 26px; font-weight: 700; line-height: 1.1; color: var(--c); font-variant-numeric: tabular-nums; }
.pv-l { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
/* Vạch màu bên trái: nặng nhẹ đọc được bằng mắt, không phải đọc chữ. */
.pv-r > td:first-child { border-left: 3px solid transparent; }
.pv-red   > td:first-child { border-left-color: var(--crit-ink); }
.pv-yellow > td:first-child { border-left-color: var(--warn-ink); }
.pv-green > td:first-child { border-left-color: var(--ok-ink); }
/* Bảng bày lại đúng sheet nên nhiều cột — chữ nhỏ hơn, ô sát hơn, và cột "phải xử
   lý" được nới rộng vì đó là thứ người ta đọc. */
.pv-tb { font-size: 12px; }
.pv-tb th, .pv-tb td { padding: 5px 7px; white-space: nowrap; }
/* Dòng phụ giải thích: không viền trên (nó thuộc dòng ngay trên), chữ xuống dòng
   được, các lý do xếp ngang cho gọn. */
.pv-tb tr.pv-why > td { border-top: 0; padding-top: 0; white-space: normal; }
/* display:flex ĐẶT TRÊN <td> sẽ huỷ luôn cơ chế colspan — ô co lại còn mấy chục px
   và chữ rơi từng từ một dòng. Nên flex phải nằm ở <div> bên trong, td giữ nguyên
   là table-cell. */
.pv-tb .pv-x { display: flex; flex-wrap: wrap; gap: 3px 16px; }
.pv-i { font-size: 11.5px; line-height: 1.5; color: var(--ink-2); }
.pv-d { width: 14px; padding-right: 0 !important; }
/* Dòng đầu của mỗi đơn có vạch trên: nhóm đơn nhiều PO đọc ra được ranh giới. */
.pv-tb tbody tr.pv-h > td { border-top: 1px solid var(--line-2); }
.pv-t { text-decoration: none; color: inherit; display: block; }
.pv-t:hover { border-color: var(--c); }
.pv-i span { font-weight: 700; font-size: 10.5px; letter-spacing: .03em; }
/* Trong .alert thì <b> là dòng tiêu đề (display:block), nên danh sách trong thân
   phải dùng thẻ riêng — không thì mỗi tên cột rơi xuống một dòng kèm dấu phẩy lạc. */
.pv-k { font-weight: 650; white-space: nowrap; }
/* Tên khách dài (SakkarinCd Kongthon) đẩy cột Status ra ngoài mép — cắt bớt bằng
   ellipsis chứ đừng để mất cột trạng thái, đó là cột luật bắt phải soi. */
.pv-tb .pv-c { max-width: 118px; overflow: hidden; text-overflow: ellipsis; }
.alert > div { margin-top: 4px; }
.alert > div > b { font-family: inherit; margin: 0; }

/* ── Biểu đồ tiến độ ── */
.pv-g2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); gap: 12px; margin-bottom: 12px; }
.pv-ch { padding: 13px 15px; }
.pv-ch h3 { font-family: var(--f-display); font-size: 14px; margin: 0 0 9px; }
.pv-legend { display: flex; flex-wrap: wrap; gap: 3px 13px; margin-bottom: 9px; }
.pv-lg { font-size: 11px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px; }
.pv-lg i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.pv-row { display: grid; grid-template-columns: 118px 1fr auto; gap: 9px; align-items: center; margin-bottom: 6px; }
.pv-lb { font-size: 12px; color: var(--ink-2); }
.pv-rt { font-size: 11px; white-space: nowrap; }
.pv-bar { display: flex; height: 20px; border-radius: 3px; overflow: hidden; background: var(--panel-2); }
.pv-sg { display: grid; place-items: center; font-size: 10.5px; font-weight: 700; color: var(--on-brand);
         min-width: 3px; font-variant-numeric: tabular-nums; }
/* Cột dọc: chiều cao theo tỷ lệ, số đặt trên đầu cột để đọc được cả khi cột thấp. */
.pv-bars { display: flex; gap: 14px; align-items: flex-end; height: 104px; padding: 0 4px; }
.pv-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.pv-cv { border-radius: 3px 3px 0 0; min-height: 2px; }
.pv-cn { font-size: 13px; font-weight: 700; text-align: center; font-variant-numeric: tabular-nums; }
.pv-cl { font-size: 10.5px; color: var(--ink-3); text-align: center; }
.pv-foot { font-size: 11px; color: var(--ink-3); line-height: 1.5; margin-top: 8px; }
/* Dòng thời gian: mốc đặt theo phần trăm nên tự co theo khung, không cần tính viewBox. */
.pv-tl { max-height: 250px; overflow-y: auto; }
.pv-tl-r { display: grid; grid-template-columns: 132px 1fr; gap: 8px; align-items: center; margin-bottom: 3px; }
.pv-tl-n { font-size: 11px; display: flex; flex-direction: column; line-height: 1.25; overflow: hidden; }
.pv-tl-n span { font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pv-tl-t { position: relative; height: 19px; border-bottom: 1px solid var(--line); }
.pv-pt { position: absolute; top: 0; transform: translateX(-50%); width: 17px; height: 17px;
         border-radius: 50%; display: grid; place-items: center; font-size: 9.5px; font-weight: 700;
         background: var(--ok-soft); color: var(--ok-ink); border: 1px solid var(--ok-ink); }
.pv-pt-s { background: var(--warn-soft); color: var(--warn-ink); border-color: var(--warn-ink); }
.pv-pt-l { background: var(--crit-soft); color: var(--crit-ink); border-color: var(--crit-ink); }
.pv-now { position: absolute; top: -2px; bottom: -1px; width: 1px; background: var(--ink-2); opacity: .75; }
/* Mốc quá hạn nằm TRÊN các mốc khác: hai mốc sát ngày nhau thì cái đang cháy phải
   là cái nhìn thấy, không phải cái vẽ sau cùng. */
.pv-pt { z-index: 1; }
.pv-pt-s { z-index: 2; }
.pv-pt-l { z-index: 3; }
/* Vạch hôm nay nằm TRÊN mốc: để dưới thì dòng nào có mốc sát hôm nay là vạch biến
   mất, mà đó đúng là những dòng cần đọc mốc so với hôm nay nhất. */
.pv-now { z-index: 4; }
.pv-em { font-size: 11px; color: var(--ink-3); padding-left: 7px; align-self: center; }

/* ---------- Ô hiện mật khẩu vừa cấp ---------- */
/* To và thưa chữ: bảng này được đọc to hoặc chép tay ở xưởng, nhầm một ký tự là
   người ta không vào được. user-select:all để bấm một lần chọn cả chuỗi. */
.pw-show{ font:700 34px/1 var(--f-mono); letter-spacing:.18em; text-align:center;
  padding:20px; margin:12px 0; background:var(--bg-2);
  border:1px dashed var(--line-2); border-radius:var(--r); user-select:all }

/* ---------- Ma trận vai trò × quyền ---------- */
/* Cột đầu dính trái: cuộn ngang qua 7 vai trò mà vẫn đọc được đang tick quyền nào. */
.perm-mx th:first-child, .perm-mx td:first-child{
  position:sticky; left:0; background:var(--card); z-index:1; min-width:290px }
.perm-mx th.n, .perm-mx td.n{ text-align:center; min-width:98px }
.perm-mx input[type=checkbox]{ width:17px; height:17px; cursor:pointer }
.perm-mx input:disabled{ opacity:.45; cursor:not-allowed }
.perm-grp td{ background:var(--bg-2); font-weight:650; font-size:11.5px;
  letter-spacing:.04em; text-transform:uppercase; color:var(--muted) }
/* Nhãn phụ trong đầu cột ma trận và mã quyền dưới nhãn — nhỏ, không tranh chỗ */
.mx-sub{font:400 10px/1.35 var(--f-sans);color:var(--ink-3);margin-top:3px;text-transform:none;letter-spacing:0}
.mx-code{font:400 10px/1.3 var(--f-mono);color:var(--ink-3);margin-top:2px}
/* Thẻ team: mỗi team một khối, team ngừng dùng thì mờ đi chứ không ẩn — còn phải
   thấy để bật lại. */
.tm-card{margin-bottom:12px}
.tm-card.off{opacity:.55}
.tm-card .t td{padding:6px 9px}
.tm-card select{padding:4px 7px;font-size:12px}

/* ═══════════ Ent — bộ renderer thực thể dùng chung ═══════════
   Một hình dạng cho mã hàng ở MỌI màn: mã đậm mono, tên phụ nhỏ bên dưới.
   Trước đây mỗi màn tự bày một kiểu nên overview và chi tiết đọc ra hai thứ. */
.ent{display:inline-flex;flex-direction:column;gap:1px;min-width:0;vertical-align:top}
.ent>b.code{font:650 12.5px/1.25 var(--f-mono);letter-spacing:.01em}
.ent-name{font-size:11px;color:var(--ink-3);line-height:1.3;overflow:hidden;
  text-overflow:ellipsis;display:block;max-width:34ch}
.ent-code{font:650 12.5px/1.25 var(--f-mono);color:var(--brand-ink,inherit)}
a.ent-code{text-decoration:none;border-bottom:1px dotted currentColor}
a.ent-code:hover{color:var(--brand)}
.ent-stage{font-size:12px}

/* Số lượng: số chính theo đơn vị xưởng, quy đổi làm phụ. Chữ số bảng (tabular-nums)
   để các dòng thẳng cột khi đọc nhanh. */
.qty{white-space:nowrap;font-variant-numeric:tabular-nums}
.qty>b{font-weight:650}
.qty>i{display:block;font-style:normal;font-size:10.5px;color:var(--ink-3)}
/* Hàng biểu đồ cột ngang (Ent.hbar) — cao hơn thanh tiến độ để đọc từ xa */
.bar.hbar{height:19px}
/* Hộp tìm kiếm không được đẻ thanh cuộn ngang: nội dung kết quả có thể dài hơn ô */
.omni-box{overflow-x:hidden}
.omni-box .omni-hit{min-width:0}

/* ═══════════ BẢNG ĐIỀU HÀNH ═══════════ */
/* Việc cần xử lý: mỗi dòng là một hành động, có vạch màu bên trái để mức độ đọc
   được bằng mắt chứ không phải đọc chữ. */
.todo-card{margin-top:13px}
.todo{display:flex;align-items:center;gap:12px;padding:11px 13px;margin-bottom:7px;
  border:1px solid var(--line);border-left:3px solid var(--line-2);border-radius:9px;
  background:var(--bg-2);text-decoration:none;color:inherit}
.todo:hover{border-color:var(--brand);background:var(--panel-2)}
.todo.crit{border-left-color:var(--crit)}
.todo.warn{border-left-color:var(--warn)}
.todo.info{border-left-color:var(--info)}
.td-ic{width:30px;height:30px;flex:none;display:grid;place-items:center;border-radius:8px;
  background:var(--card)}
.td-ic .ico{width:15px;height:15px}
.todo.crit .td-ic{background:var(--crit-soft)} .todo.crit .td-ic .ico{color:var(--crit-ink)}
.todo.warn .td-ic{background:var(--warn-soft)} .todo.warn .td-ic .ico{color:var(--warn-ink)}
.todo.info .td-ic{background:var(--info-soft)} .todo.info .td-ic .ico{color:var(--info-ink)}
.td-b{flex:1;min-width:0}
.td-b b{display:block;font:600 13px/1.35 var(--f-sans)}
.td-b span{display:block;font-size:11.5px;color:var(--ink-3);margin-top:1px}
.td-go{flex:none;display:inline-flex;align-items:center;gap:4px;font:600 11.5px/1 var(--f-sans);
  color:var(--brand-ink);white-space:nowrap}
.td-go .ico{width:12px;height:12px}
/* Dòng cảnh báo giờ có nút "Đã nhận" bên cạnh, nên phần bấm-để-đi phải là một
   thẻ <a> riêng bên trong — lồng <button> vào <a> là HTML sai và bàn phím đi lạc. */
.td-hit{flex:1;min-width:0;display:flex;align-items:center;gap:12px;
  text-decoration:none;color:inherit}
.todo.gray{opacity:.62;border-left-color:var(--line-2)}
.todo.gray .td-ic{background:var(--bg-2)}
.btn.ghost{background:transparent;border-style:dashed;color:var(--ink-3)}
.btn.ghost:hover{border-style:solid;color:var(--brand-2)}

/* ── Ô sửa tại chỗ ──
   Ô sửa được phải TRÔNG khác ô chỉ đọc kể cả khi chưa rê chuột: gạch chân mờ.
   Không có dấu hiệu gì thì người ta không biết bấm được, và tính năng coi như
   không tồn tại với người không được ai chỉ. */
.ed{position:relative;cursor:text;border-bottom:1px dashed var(--line-2);
  padding-bottom:1px;display:inline-flex;align-items:center;gap:4px}
.ed:hover,.ed:focus-visible{border-bottom-color:var(--brand);outline:none;color:var(--brand-2)}
.ed-p{display:none;line-height:0}
.ed-p .ico{width:11px;height:11px;color:var(--ink-3)}
.ed:hover .ed-p,.ed:focus-visible .ed-p{display:inline-flex}
.ed-in{font:inherit;font-family:var(--f-sans);padding:2px 5px;min-width:66px;max-width:190px;
  border:1px solid var(--brand);border-radius:4px;background:var(--panel);color:var(--ink)}
.ed-ok{animation:edok 1.4s ease-out}
@keyframes edok{0%{background:var(--ok-soft)}100%{background:transparent}}

/* ── Điểm đứt ──
   Hai loại đứt đọc khác nhau nên phải tách hai cột, không trộn một danh sách:
   đứt DÒNG CHẢY thấy được trên sàn, đứt ĐỘ TIN CẬY chỉ lộ ra qua số liệu. */
.fl-wrap{display:grid;grid-template-columns:1fr 1fr;gap:13px}
.fl-h{font:600 12px/1 var(--f-sans);letter-spacing:.2px;margin-bottom:3px}
.fl-row{display:flex;align-items:flex-start;gap:9px;padding:9px 11px;margin-top:7px;
  border:1px solid var(--line);border-left:3px solid var(--line-2);border-radius:8px;
  background:var(--bg-2);text-decoration:none;color:inherit}
.fl-row:hover{border-color:var(--brand);background:var(--panel-2)}
.fl-row.crit{border-left-color:var(--crit)}
.fl-row.warn{border-left-color:var(--warn)}
.fl-row b{flex:none;max-width:34%;font:600 12px/1.4 var(--f-sans)}
.fl-row span{flex:1;font-size:11.5px;line-height:1.5;color:var(--ink-3)}
.fl-row .ico{flex:none;width:13px;height:13px;margin-top:2px;color:var(--ink-3)}
@media (max-width:860px){.fl-wrap{grid-template-columns:1fr}}

/* ── Biểu đồ cột chồng ── */
.ch{position:relative}
.ch-svg{width:100%;height:148px;display:block;overflow:visible}
.ch-hit{cursor:crosshair}
.ch-x{position:relative;height:15px;margin-top:5px}
.ch-xl{position:absolute;transform:translateX(-50%);font:400 10px/1 var(--f-mono);color:var(--ink-3);
  white-space:nowrap}
/* Chú giải LUÔN có khi từ 2 series: nhận dạng không được chỉ dựa vào màu. */
.ch-lg{display:flex;flex-wrap:wrap;gap:4px 14px;margin-top:11px;padding-top:9px;
  border-top:1px solid var(--line)}
.ch-li{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--ink-2)}
.ch-li i{width:9px;height:9px;border-radius:2px;flex:none}
.ch-li b{font-family:var(--f-mono);font-size:11.5px;color:var(--ink)}
.ch-peak{margin-top:6px;font-size:11px;color:var(--ink-3)}

/* ── Biểu đồ cột ngang một series: không cần chú giải, nhãn hiện trực tiếp ── */
.hbw{display:flex;flex-direction:column;gap:8px}
.hbr{display:grid;grid-template-columns:minmax(90px,26%) 1fr auto;gap:10px;align-items:center}
.hbl{font-size:12px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hbt{height:14px;background:var(--bg-2);border-radius:4px;overflow:hidden}
.hbt>i{display:block;height:100%;background:var(--c1);border-radius:4px}
.hbr.warn .hbt>i{background:var(--warn)}
.hbv{font-size:11px;color:var(--ink-3);white-space:nowrap;font-variant-numeric:tabular-nums}
.hbv b{font-family:var(--f-mono);font-size:13px;color:var(--ink)}
.hbv span{display:block;font-size:10px}

/* ═══════════ BẢNG PHÒNG BAN (treo TV ở xưởng) ═══════════
   Chữ to hơn hẳn các màn khác: đọc từ giữa xưởng, không phải từ ghế ngồi. */
.bd{display:flex;flex-direction:column;gap:14px}
.bd-top{display:flex;align-items:center;gap:16px;font:600 17px/1 var(--f-sans)}
.bd-clock{margin-left:auto;font:700 26px/1 var(--f-mono);letter-spacing:.02em}
/* Chấm sống: bảng treo tường mà đứng im thì không ai biết nó còn chạy hay đã treo. */
.bd-live{display:flex;align-items:center;gap:7px;font:400 12px/1 var(--f-sans);color:var(--ink-3)}
.bd-live i{width:8px;height:8px;border-radius:50%;background:var(--ok);animation:bdp 2s infinite}
@keyframes bdp{0%,100%{opacity:1}50%{opacity:.25}}

.bd-cols{display:grid;gap:12px}
.bd-col{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:16px 18px}
.bd-st{font:700 13px/1 var(--f-sans);text-transform:uppercase;letter-spacing:.9px;color:var(--ink-3)}
.bd-big{margin:9px 0 11px;font:700 42px/1 var(--f-mono);letter-spacing:-.02em}
.bd-big span{font:400 16px/1 var(--f-mono);color:var(--ink-3);margin-left:5px}
.bd-col .bar{height:12px}
.bd-sub{margin-top:9px;font-size:12.5px;color:var(--ink-3)}

.bd-2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.bd-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px}
.bd-h{font:700 12px/1 var(--f-sans);text-transform:uppercase;letter-spacing:.9px;
  color:var(--ink-3);margin-bottom:11px}
.bd-row{display:flex;align-items:baseline;gap:10px;padding:7px 0;border-bottom:1px solid var(--line);
  font-size:14.5px}
.bd-row:last-child{border-bottom:0}
.bd-row b{font-family:var(--f-mono);font-size:14px;flex:none}
.bd-row span{color:var(--ink-2);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bd-row i{font-style:normal;font-family:var(--f-mono);font-weight:700;flex:none}
.bd-none{color:var(--ink-3);font-size:13.5px;padding:8px 0}
.bd-alert{margin-top:10px;padding:9px 11px;border-radius:8px;background:var(--crit-soft);
  color:var(--crit-ink);font:600 13.5px/1.3 var(--f-sans);display:flex;align-items:center;gap:7px}
.bd-alert .ico{width:15px;height:15px}
@media (max-width:900px){.bd-2{grid-template-columns:1fr}.bd-big{font-size:34px}}
/* % để NGOÀI cột, không đè lên mép: chữ trên đúng chỗ chuyển màu là chỗ không
   đọc được ở cả nền sáng lẫn nền tối. */
.bd-bar{display:flex;align-items:center;gap:10px}
.bd-bar .bar{flex:1}
.bd-bar>span{font:700 15px/1 var(--f-mono);color:var(--ink-2);flex:none;min-width:44px;text-align:right}

/* Thẻ chọn xưởng ở trang gốc — dành cho người làm trong xưởng, không ở cấp nhà máy */
.wsx-card{display:flex;flex-direction:column;gap:5px;text-decoration:none;color:inherit;
  padding:20px 22px;transition:border-color .12s}
.wsx-card:hover{border-color:var(--brand)}
.wsx-card .dot{width:11px;height:11px;border-radius:3px}
.wsx-card b{font:700 17px/1.2 var(--f-display)}
.wsx-card .muted{font-size:12px}

/* ---------- Ô chỉ số bấm được (D365 gọi là tile dẫn vào danh sách đã lọc) ---------- */
.kpi-go{display:block;position:relative;text-decoration:none;color:inherit;transition:border-color .12s,transform .12s}
.kpi-go:hover{border-color:var(--brand)}
.kpi-go:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.kpi-go .kgo{position:absolute;top:12px;right:11px;color:var(--ink-3);opacity:0;transition:opacity .12s}
.kpi-go:hover .kgo,.kpi-go:focus-visible .kgo{opacity:1}

/* ---------- Sắp xếp theo cột ---------- */
table.t th.srt-on{cursor:pointer;user-select:none}
table.t th.srt-on:hover{color:var(--ink);background:var(--panel-2)}
table.t th.srt-a{color:var(--brand)}
table.t th .srt-i{display:inline-block;width:11px;margin-left:3px;font-size:8px;vertical-align:1px}
.tw-tools{display:flex;align-items:center;gap:9px;margin-bottom:9px;flex-wrap:wrap}
.tw-tools input{width:230px}
.tw-tools .cnt{font-size:11px;color:var(--ink-3)}

/* ---------- Chế độ TV: bảng treo giữa xưởng, không ai bấm ---------- */
body.tv .top,body.tv .side,body.tv .hdr{display:none}
body.tv .shell{grid-template-columns:1fr}
body.tv .main{padding:18px 26px;max-width:none;min-height:100vh;display:flex;flex-direction:column}
body.tv #view{flex:1;display:flex;flex-direction:column}
/* Bảng treo tường thì chiều cao là tài nguyên, không phải chỗ trống: cho các
   khối giãn hết màn để đứng xa vẫn đọc được, thay vì dồn lên một phần tư trên. */
body.tv .bd{flex:1}
body.tv .bd-cols{flex:1;align-content:stretch}
body.tv .bd-col{display:flex;flex-direction:column;justify-content:center}
body.tv .bd-2{flex:0 0 auto;min-height:230px}
body.tv .bd{gap:20px}
body.tv .bd-top{font-size:26px}
body.tv .bd-clock{font-size:42px}
body.tv .bd-st{font-size:17px}
body.tv .bd-big{font-size:72px;margin:14px 0 16px}
body.tv .bd-big span{font-size:24px}
body.tv .bd-sub{font-size:17px}
body.tv .bd-col{padding:22px 26px}
body.tv .bd-col .bar{height:18px}
body.tv .bd-card{padding:20px 24px;font-size:17px}
.bd-exit{margin-left:14px;font-size:12px;color:var(--ink-3);text-decoration:none;opacity:.35;
  border:1px solid var(--line);border-radius:6px;padding:4px 9px;transition:opacity .12s}
.bd-exit:hover,.bd-exit:focus-visible{opacity:1;color:var(--ink);border-color:var(--brand)}

/* ---------- Chuông: việc phải xử lý ngay ---------- */
.note-warn{border-color:var(--warn);background:var(--warn-soft,var(--panel-2))}
.bellw{position:relative}
.ico-btn.bell{position:relative}
.ico-btn.bell.has{color:var(--crit-ink,var(--crit))}
.bell-n{position:absolute;top:2px;right:1px;min-width:15px;height:15px;padding:0 3px;
  border-radius:8px;background:var(--crit);color:#fff;font:700 9.5px/15px var(--f-sans);
  text-align:center;box-shadow:0 0 0 2px var(--panel)}
.bellp{position:absolute;top:calc(100% + 8px);right:0;width:380px;max-height:70vh;overflow:auto;
  background:var(--card);border:1px solid var(--line-2);border-radius:11px;z-index:60;
  box-shadow:0 12px 34px rgba(0,0,0,.22)}
.bellp-h{display:flex;align-items:center;gap:9px;padding:12px 14px;border-bottom:1px solid var(--line)}
.bellp-h b{font-size:13px}
.bellp-l{display:flex;flex-direction:column}
.bell-it{display:block;padding:10px 14px;border-bottom:1px solid var(--line);
  text-decoration:none;color:inherit}
.bell-it:hover{background:var(--panel-2)}
.bell-t{font-size:12.5px;font-weight:600}
.bell-s{font-size:11.5px;color:var(--ink-2);margin-top:2px}
.bellp-f{padding:10px 14px;font-size:11px;color:var(--ink-3)}

/* ---------- Chấm công: màn cho ĐIỆN THOẠI, ngón tay cái ---------- */
.ci{max-width:520px;margin:0 auto}
.ci-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:22px 20px 18px;margin-bottom:13px;text-align:center}
.ci-st{font-size:14px;color:var(--ink-2);margin-bottom:16px}
.ci-btn{width:100%;min-height:104px;border:0;border-radius:14px;cursor:pointer;
  font:700 27px/1.1 var(--f-display);letter-spacing:.5px;color:#fff;
  display:flex;align-items:center;justify-content:center;gap:11px;
  transition:transform .08s,filter .12s}
.ci-btn .ico{width:27px;height:27px}
.ci-btn.in{background:var(--brand)}
.ci-btn.out{background:var(--warn)}
.ci-btn:active{transform:scale(.985)}
.ci-btn:disabled{filter:grayscale(.6);opacity:.65;cursor:wait}
.ci-btn:focus-visible{outline:3px solid var(--ink);outline-offset:3px}
.ci-qr{margin-top:14px;display:flex;align-items:center;gap:6px}
.ci-qr input{flex:1;font:600 19px/1 var(--f-mono);letter-spacing:4px;text-transform:uppercase;
  text-align:center;padding:12px 10px}
.ci-st{display:flex;align-items:center;justify-content:center;gap:2px}
.ci-sub{display:block;font-weight:400;color:var(--ink-2);margin-top:2px}
.ci-mu{color:var(--ink-3)}
.ci-gps{display:block;margin-top:13px;font-size:12.5px;line-height:1.5}
.ci-ok{color:var(--ok-ink,var(--ok))}
.ci-bad{color:var(--warn-ink)}
.ci-note{margin-top:9px;font-size:11px;color:var(--ink-3)}
@media (max-width:620px){
  .ci-btn{min-height:128px;font-size:31px}
  .ci-card{padding:18px 14px 14px}
}

/* ---------- Màn mã cổng: treo ở cổng, đọc từ xa ---------- */
.gatew{max-width:640px;margin:6vh auto 0;text-align:center}
.gate-ws{font:600 19px/1 var(--f-sans);color:var(--ink-2);text-transform:uppercase;letter-spacing:2px}
.gate-code{font:700 clamp(62px,17vw,132px)/1 var(--f-mono);letter-spacing:9px;
  margin:18px 0 12px;color:var(--brand)}
.gate-sub{font-size:14px;color:var(--ink-2);max-width:42ch;margin:0 auto}
.gate-bar{height:7px;border-radius:5px;background:var(--grid);overflow:hidden;margin:22px auto 0;max-width:340px}
.gate-bar>i{display:block;height:100%;width:100%;background:var(--brand);transition:width 1s linear}

/* ---------- Dấu (!) ---------- */
.hint-b{display:inline-flex;align-items:center;justify-content:center;width:19px;height:19px;
  padding:0;margin-left:5px;border:0;border-radius:50%;background:var(--panel-2);color:var(--ink-3);
  cursor:pointer;vertical-align:-4px;flex:none;transition:background .12s,color .12s}
.hint-b:hover,.hint-b[aria-expanded="true"]{background:var(--brand-soft);color:var(--brand-ink)}
.hint-b:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.hint-b .ico{width:13px;height:13px;vertical-align:0}
.hint-p{position:absolute;z-index:70;max-width:min(300px,86vw);margin-top:6px;
  background:var(--card);border:1px solid var(--line-2);border-radius:9px;padding:10px 12px;
  font:400 12px/1.55 var(--f-sans);color:var(--ink-2);box-shadow:0 10px 28px rgba(0,0,0,.2)}

/* ---------- Bản đồ tile (OpenStreetMap) ---------- */
.ci-map-card{padding:14px}
.ci-map{position:relative;height:230px;border-radius:11px;overflow:hidden;
  background:var(--panel-2);border:1px solid var(--line)}
.ci-map.empty{display:grid;place-items:center;text-align:center;padding:0 18px;
  font-size:12.5px;color:var(--ink-3);height:130px}
.tm-layer{position:absolute;inset:0}
.tm-t{position:absolute;width:256px;height:256px;user-select:none}
/* Nền tối: OSM chỉ có tile sáng. Đảo màu rồi xoay sắc độ cho ra bản đồ tối mà
   vẫn giữ đúng màu cây xanh và đường — rẻ hơn nhiều so với nuôi một bộ tile riêng. */
:root[data-theme="dark"] .tm-layer{filter:invert(1) hue-rotate(180deg) brightness(.92) contrast(.9)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .tm-layer{filter:invert(1) hue-rotate(180deg) brightness(.92) contrast(.9)}}
.tm-ov{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.tm-attr{position:absolute;right:0;bottom:0;font:400 9.5px/1 var(--f-sans);padding:3px 5px;
  background:rgba(255,255,255,.72);color:#333;text-decoration:none;border-top-left-radius:5px}
.tm-scale{position:absolute;left:8px;bottom:8px;font:600 10px/1 var(--f-mono);padding:4px 7px;
  border-radius:5px;background:var(--card);color:var(--ink-2);border:1px solid var(--line)}
.m-zone{fill:var(--brand);fill-opacity:.16;stroke:var(--brand);stroke-width:2;stroke-dasharray:6 4}
.m-acc{fill:var(--info);fill-opacity:.16;stroke:var(--info);stroke-opacity:.5;stroke-width:1}
.m-me{stroke:#fff;stroke-width:2.5}
.m-me.ok{fill:var(--ok)}
.m-me.far{fill:var(--crit)}
.m-line{stroke:var(--ink);stroke-width:1.6;stroke-opacity:.55;stroke-dasharray:5 4}
.m-pin path{fill:var(--brand);stroke:#fff;stroke-width:1.6}
.m-pin-h{fill:#fff}

.ci-dist{font:600 12px var(--f-mono);color:var(--ink-2)}
.ci-addr{margin-top:11px;font-size:12.5px;display:flex;flex-direction:column;gap:7px}
.ci-addr-row{display:flex;gap:10px;align-items:baseline}
.ci-addr-row .k{flex:0 0 130px;color:var(--ink-3);font-size:11px;display:flex;align-items:center;gap:5px}
.ci-addr-row .k .ico{width:13px;height:13px}
.ci-addr .btn{align-self:flex-start;margin-top:2px}
