/* theme.css - LỚP GIAO DIỆN HIỆN ĐẠI (nạp SAU app.css, chỉ tinh chỉnh thị giác)
   Phong cách: tinh gọn, nhiều khoảng thở, bóng đổ nhiều lớp, 1 màu nhấn tự tin
   - tham chiếu Google Maps / Material. Không đổi cấu trúc DOM. */

/* ---------- Tokens ---------- */
:root{
  --brand:#1a73e8; --brand-ink:#1558b8; --brand-weak:#e8f0fe;
  --accent:#1a73e8;
  --ink:#202124; --ink-soft:#5f6368; --ink-faint:#80868b;
  --line:#dadce0; --line-soft:#e8eaed;
  --panel:#ffffff; --surface:#f8f9fa;
  --danger:#d93025; --ok:#188038; --warn:#e37400;
  --radius:12px; --radius-sm:8px; --radius-lg:16px;
  --shadow-1:0 1px 2px rgba(60,64,67,.12), 0 1px 3px rgba(60,64,67,.10);
  --shadow-2:0 2px 6px rgba(60,64,67,.12), 0 6px 14px rgba(60,64,67,.12);
  --shadow-3:0 4px 12px rgba(60,64,67,.14), 0 12px 30px rgba(60,64,67,.16);
  --shadow:var(--shadow-2); --shadow-sm:var(--shadow-1);
  --ring:0 0 0 3px rgba(26,115,232,.28);

  /* ===== HE THONG THIET KE 23/10/2026 (docs/reports/He thong thiet ke giao dien 20261023.md) =====
     Moi mau nhan SUY RA tu --brand (quan tri doi mau o «Tùy biến giao diện» -> ca he thong doi theo).
     KHONG ap dung cho kieu hien thi lop ban do. Thanh phan dung chung: css/he-thong.css */
  --font-sans:"Inter","Segoe UI Variable Text","Segoe UI",Roboto,"Noto Sans","Helvetica Neue",system-ui,Arial,sans-serif;
  --font-mono:ui-monospace,"Cascadia Mono",Consolas,"Liberation Mono",monospace;
  --fs-2xs:10.5px; --fs-xs:11.5px; --fs-sm:12.5px; --fs-base:13.5px; --fs-md:14px; --fs-lg:16px; --fs-xl:18px; --fs-2xl:22px;
  --lh-tight:1.25; --lh-base:1.45; --lh-loose:1.6;
  --fw-med:500; --fw-semi:600; --fw-bold:700;
  --sp-0:2px; --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-8:32px;
  --radius-xs:6px; --radius-pill:999px;
  --ctl-h:32px; --ctl-h-sm:28px; --ctl-h-lg:38px;
  --hover:rgba(60,64,67,.08); --pressed:rgba(60,64,67,.14);
  --glass:rgba(255,255,255,.96); --overlay:rgba(32,33,36,.55);
  --brand-a12:rgba(26,115,232,.12); --brand-a35:rgba(26,115,232,.35); --brand-2:#4285f4;
  --ok-weak:#e6f4ea; --ok-ink:#137333; --warn-weak:#fef7e0; --warn-ink:#8a4b00;
  --danger-weak:#fce8e6; --danger-ink:#b3261e; --info:var(--brand); --info-weak:var(--brand-weak);
  --dur-fast:.12s; --dur:.18s; --ease:cubic-bezier(.2,.7,.3,1);
}
@supports (color:color-mix(in srgb,red,blue)){
  :root{
    --brand-a12:color-mix(in srgb,var(--brand) 12%,transparent);
    --brand-a35:color-mix(in srgb,var(--brand) 35%,transparent);
    --brand-2:color-mix(in srgb,var(--brand) 78%,#ffffff);
  }
}

body{
  font-family:var(--font-sans);
  color:var(--ink);background:var(--surface);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
[hidden]{display:none!important}
::selection{background:var(--brand-a12)}

/* ---------- Icon ---------- */
.ic{width:1.15em;height:1.15em;flex:0 0 auto;vertical-align:-.18em;pointer-events:none}
.has-ic{display:inline-flex;align-items:center;justify-content:center;gap:7px}
.tool.has-ic,.icon-btn.has-ic,.dock-modes button.has-ic,.pi-ic.has-ic,
.lt-tbl.has-ic,.lt-sty.has-ic,.lt-del.has-ic,.lt-ren.has-ic,.dock-bar .btn-sm.has-ic{gap:0}
.tool .ic{width:20px;height:20px}
.icon-btn .ic{width:18px;height:18px}
.chip .ic,.btn-sm .ic{width:15px;height:15px}

/* ---------- Scrollbar ---------- */
*{scrollbar-width:thin;scrollbar-color:#c4c7c5 transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-thumb{background:#c4c7c5;border:3px solid transparent;
  border-radius:999px;background-clip:content-box}
*::-webkit-scrollbar-thumb:hover{background:#9aa0a6;background-clip:content-box}
*::-webkit-scrollbar-track{background:transparent}

/* ---------- Sidebar ---------- */
#sidebar{border-right:1px solid var(--line-soft);box-shadow:1px 0 0 rgba(0,0,0,.02)}
.side-head{padding:18px 18px 14px}
.brand-mark{border-radius:12px;box-shadow:var(--shadow-1);
  background:linear-gradient(140deg,var(--brand),var(--brand-2))}
.brand-title{font-weight:700;letter-spacing:-.01em}
.side-tabs{padding:0 8px;gap:2px}
.side-tabs .stab{border-radius:9px 9px 0 0;transition:color .15s,background .15s}
.side-tabs .stab:hover:not(:disabled){background:var(--surface)}
.side-tabs .stab.is-active{border-bottom-width:2.5px}
.panel-head h3{font-size:11.5px;font-weight:700;letter-spacing:.01em;text-transform:none;color:var(--ink-faint)}
.side-proj{background:var(--surface);border-bottom:1px solid var(--line-soft)}

/* ---------- Buttons / chips ---------- */
.btn{
  border-radius:999px;font-weight:600;transition:background .15s,border-color .15s,box-shadow .15s,transform .05s;
  border:1px solid var(--line);
}
.btn:hover{border-color:#c0c4c9;background:var(--surface,#f8f9fa);box-shadow:var(--shadow-1)}
.btn:active{transform:translateY(.5px)}
.btn:focus-visible{outline:none;box-shadow:var(--ring)}
.btn-primary{background:var(--brand);border-color:var(--brand);box-shadow:0 1px 2px var(--brand-a35)}
.btn-primary:hover{background:var(--brand-ink);border-color:var(--brand-ink);box-shadow:0 2px 8px var(--brand-a35)}
.btn-danger{border-color:#f2b8b5}
.btn-danger:hover{background:var(--danger);border-color:var(--danger)}
.chip{
  border-radius:999px;font-weight:600;color:var(--ink-soft);
  transition:background .15s,border-color .15s,color .15s,box-shadow .15s;
}
.chip:hover{background:var(--brand-weak);border-color:transparent;color:var(--brand-ink)}
.chip:focus-visible{outline:none;box-shadow:var(--ring)}
.icon-btn{background:transparent;color:var(--ink-soft);border-radius:999px;
  transition:background .15s,color .15s}
.icon-btn:hover{background:var(--hover);color:var(--ink)}
.icon-btn:focus-visible{outline:none;box-shadow:var(--ring)}

/* ---------- Inputs ---------- */
#project-search,.form input,.form select,.form textarea,.mini-select,
.dock-bar #tbl-search,#tbl-search,#imp-crs,.filters select,.doc-add input,.doc-add select{
  border:1px solid var(--line);border-radius:10px;background:var(--panel);
  transition:border-color .15s,box-shadow .15s;
}
#project-search:focus,.form input:focus,.form select:focus,.form textarea:focus,
.mini-select:focus,#tbl-search:focus,.dock-bar #tbl-search:focus{
  outline:none;border-color:var(--brand);box-shadow:var(--ring);
}
.proj-search::before{
  content:"";position:absolute;left:11px;top:50%;width:15px;height:15px;
  transform:translateY(-50%);opacity:.5;pointer-events:none;
  background:currentColor;color:var(--ink-faint);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E") center/contain no-repeat;
}
#project-search{padding-left:32px}

/* ---------- Thanh công cụ: RAIL DỌC gọn, sát mép — ưu tiên bản đồ ---------- */
.toolbar{
  top:14px;right:14px;left:auto;flex-direction:column;width:auto;
  padding:5px;gap:3px;border:0;border-radius:13px;
  box-shadow:var(--shadow-2);background:var(--glass);backdrop-filter:blur(8px);
}
.toolbar .tool-body{display:flex;flex-direction:column;gap:3px;overflow:hidden;
  transition:max-height .22s ease,opacity .18s ease}
.toolbar.collapsed .tool-body{max-height:0;opacity:0;pointer-events:none}
.tool-toggle{color:var(--ink-faint)}
.toolbar.collapsed .tool-toggle .ic{transform:rotate(180deg)}
.tool-cluster{flex-direction:column;gap:3px}
.tool{
  width:38px;height:38px;border-radius:10px;color:var(--ink-soft);
  transition:background .13s,color .13s,transform .05s;
}
.tool:hover{background:var(--hover);color:var(--ink)}
.tool:active{transform:scale(.92)}
.tool.active{background:var(--brand);color:#fff;box-shadow:0 2px 8px var(--brand-a35)}
.toolbar .tool-sep{width:22px;height:1px;margin:3px auto;background:var(--line-soft)}

/* Bản đồ nền: nút CHỈ ICON, góc dưới-trái (kiểu Google Maps) — bấm mở danh sách */
.basemap-ctrl{
  position:absolute;left:14px;bottom:84px;z-index:3;
  width:38px;height:38px;display:grid;place-items:center;
  background:var(--glass);border:1px solid var(--line-soft);border-radius:11px;
  box-shadow:var(--shadow-1);backdrop-filter:blur(8px);cursor:pointer;overflow:hidden;
  transition:color .13s,box-shadow .13s;
}
.basemap-ctrl:hover{color:var(--brand)}
.basemap-ctrl .bmc-ic{color:var(--ink-soft);display:inline-flex;pointer-events:none}
.basemap-ctrl:hover .bmc-ic{color:var(--brand)}
.basemap-ctrl .bmc-ic .ic{width:19px;height:19px}
/* select phủ trong suốt lên toàn nút -> bấm đâu cũng mở dropdown gốc */
.basemap-select{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;border:0;background:transparent;cursor:pointer;font-size:16px;
}
.basemap-ctrl:focus-within{border-color:var(--brand);box-shadow:var(--ring)}

/* ---------- Cổng đăng nhập toàn màn hình ---------- */
body.gated #app{filter:blur(3px);pointer-events:none;user-select:none}
.login-gate{
  position:fixed;inset:0;z-index:200;display:grid;place-items:center;padding:24px;
  background:
    radial-gradient(1200px 600px at 20% -10%, var(--brand-a12), transparent 60%),
    radial-gradient(1000px 700px at 100% 110%, rgba(66,133,244,.14), transparent 55%),
    #eef2f7;
}
.login-gate[hidden]{display:none}
.lg-card{
  width:min(400px,94vw);background:var(--panel);border-radius:20px;padding:30px 30px 22px;
  box-shadow:0 24px 60px rgba(32,33,36,.28),0 4px 14px rgba(32,33,36,.12);
  animation:lgIn .3s cubic-bezier(.2,.7,.3,1);
}
@keyframes lgIn{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}
.lg-brand{display:flex;align-items:center;gap:12px;margin-bottom:20px}
.lg-brand .brand-mark{width:44px;height:44px;flex:0 0 44px;border-radius:13px}
.lg-brand .lg-title{font-weight:800;font-size:15.5px;letter-spacing:-.01em;color:var(--ink)}
.lg-brand .lg-sub{font-size:11.5px;color:var(--ink-soft);line-height:1.35}
.lg-card h2{font-size:17px;font-weight:700;margin:0 0 16px;color:var(--ink)}
.lg-field{display:flex;flex-direction:column;gap:5px;margin-bottom:13px}
.lg-field span{font-size:12px;font-weight:600;color:var(--ink-soft)}
.lg-field input{
  border:1px solid var(--line);border-radius:11px;padding:11px 13px;font-size:14px;
  font-family:inherit;transition:border-color .15s,box-shadow .15s;
}
.lg-field input:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}
.lg-err{background:var(--danger-weak,#fce8e6);color:var(--danger);border-radius:10px;padding:9px 12px;
  font-size:12.5px;margin-bottom:12px}
.lg-submit{width:100%;justify-content:center;padding:12px;font-size:14px;font-weight:700;border-radius:11px}
.lg-foot{margin-top:14px;font-size:11px;color:var(--ink-faint);text-align:center;line-height:1.5}

/* ---------- Chú giải: danh sách phẳng, gọn, chữ hiện đại ---------- */
#panel-legend{padding-top:12px}
.legend{
  gap:0;font-size:11.5px;line-height:1.4;
  letter-spacing:.002em;-webkit-font-smoothing:antialiased;
}
.legend .lg-standard{
  font-size:10.5px;font-weight:600;letter-spacing:0;text-transform:none;
  color:var(--ink-faint);background:none;border:0;border-radius:0;
  padding:2px 2px 8px;margin:2px 0 3px;text-align:left;
  border-bottom:1px solid var(--line-soft);
}
.legend .lg-block{
  border:0;border-radius:0;padding:7px 2px;margin:0;
  border-bottom:1px solid var(--line-soft);
}
.legend .lg-block:last-child{border-bottom:0}
.legend .lg-block-1{padding:5px 2px}
.legend .lg-title{
  font-weight:600;font-size:11px;letter-spacing:0;line-height:1.35;
  color:var(--ink-faint);margin-bottom:5px;text-transform:none;
}
.legend .lg-row{gap:8px;margin:2px 0;align-items:center;line-height:1.3}
.legend .lg-label{color:var(--ink-soft);font-size:11.5px}
.legend .lg-label-main{color:var(--ink);font-weight:500}
.legend .lg-mark{width:15px;height:13px;border-radius:3px;flex-basis:15px}
.legend .lg-mark.point{width:10px;height:10px;flex-basis:10px}
.legend .lg-mark.line{border-top-width:3px}

/* Tài khoản chỉ-xem: ẩn nút thêm / tải dữ liệu */
body.no-edit #btn-add,
body.no-edit #es-add{display:none!important}

/* ---------- Quản lý người dùng ---------- */
.users-list{overflow:auto;max-height:44vh}
.users-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.users-tbl th{text-align:left;color:var(--ink-faint);font-weight:700;font-size:11px;
  letter-spacing:.4px;text-transform:uppercase;padding:6px 8px;border-bottom:1px solid var(--line)}
.users-tbl td{padding:7px 8px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
.users-tbl tr:hover td{background:var(--surface)}
.users-tbl select{border:1px solid var(--line);border-radius:8px;padding:4px 6px;font-size:12px;background:var(--panel)}
.users-tbl .u-act-lbl{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--ink-soft)}
.users-tbl .u-actions{display:flex;gap:5px;justify-content:flex-end;white-space:nowrap}
.users-tbl .chip.del{color:var(--danger);border-color:#f2b8b5}
.users-tbl .chip.del:hover{background:var(--danger-weak,#fce8e6);color:var(--danger)}
.users-tbl .u-groups{font-size:12px;max-width:260px}
.users-tbl .u-groups .chip{padding:2px 8px;font-size:11px;margin-left:4px}

/* ---- Phân quyền theo nhóm / đơn vị (groups.js) ---- */
.ug-tabs{display:flex;gap:4px;padding:0 18px;border-bottom:1px solid var(--line-soft)}
.ug-tab{border:0;background:none;font:inherit;font-size:13px;font-weight:600;color:var(--ink-soft);
  padding:10px 12px;border-bottom:2px solid transparent;cursor:pointer;margin-bottom:-1px}
.ug-tab.is-active{color:var(--brand);border-bottom-color:var(--brand)}
.ug-pane{padding-top:12px}
.gr-intro{font-size:12px;line-height:1.5;margin-bottom:10px}
.gr-bar{display:flex;gap:8px;justify-content:flex-end;margin:6px 0 10px}
.gr-tbl td{vertical-align:top}
.gr-perm{display:inline-block;font-size:11px;font-weight:700;border-radius:999px;padding:2px 9px;white-space:nowrap}
.gr-view{background:#e0f2fe;color:#075985}
.gr-edit{background:var(--ok-weak,#dcfce7);color:var(--ok-ink,#166534)}
.gr-warn{color:var(--warn);font-weight:600}
.gr-edit h4,.gr-edit > h4{margin:0 0 10px;font-size:14px}
.gr-edit{display:flex;flex-direction:column;gap:10px}
.ge-chk{display:flex;align-items:center;gap:7px;font-size:13px;margin-bottom:6px}
.ge-rule.is-off{opacity:.45;pointer-events:none}
.ge-list{display:flex;flex-direction:column;gap:2px;max-height:210px;overflow:auto;padding:6px;
  border:1px solid var(--line-soft);border-radius:8px;background:var(--panel)}
.ge-list label{display:flex;align-items:baseline;gap:7px;font-size:12.5px;padding:3px 4px;border-radius:6px;cursor:pointer}
.ge-list label:hover{background:var(--surface)}
.ge-list label[hidden]{display:none}
.ge-pq{margin-bottom:5px}
.gr-preview{margin-top:8px;display:flex;flex-direction:column;gap:5px}
.ge-prev{font-size:12px;line-height:1.5}
.gr-pick{z-index:60}
.gr-mgr{display:inline-block;font-size:9.5px;font-weight:800;letter-spacing:.03em;color:#7c2d12;background:#ffedd5;
  border:1px solid #fdba74;border-radius:5px;padding:0 4px;vertical-align:1px}
.ge-mrow{display:flex;align-items:center;gap:6px}
.ge-mrow > label:first-child{flex:1}
.ge-mgr{flex:0 0 auto;font-size:11.5px !important;color:var(--ink-soft)}
.gm-body{gap:12px}
.gm-add{display:flex;flex-direction:column;gap:6px;margin-top:8px}
.gm-grp legend .gr-perm{margin-left:4px}
/* khoá đồ án */
.pi-badge.lock{background:var(--warn-weak,#fef3c7);color:var(--warn-ink,#92400e);border-color:#fcd34d}
.lock-bar{margin:8px 0;padding:9px 11px;border-radius:10px;background:var(--warn-weak,#fffbeb);border:1px solid #fcd34d;
  color:#78350f;font-size:12.5px;line-height:1.5;display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.lock-bar .lock-note{flex-basis:100%;color:var(--warn-ink,#92400e)}
.lock-bar .btn{margin-left:auto}
.gr-pick .ge-list{max-height:50vh}

/* ==== Quản lý người dùng & phân quyền: chịu tải 1000+ người / 200+ nhóm, co giãn điện thoại ==== */
.modal-box.ug-box{width:min(1200px,97vw);height:min(90vh,980px);max-height:none;display:flex;flex-direction:column;overflow:hidden}
.ug-box .modal-head,.ug-box .ug-tabs,.ug-box .modal-foot{flex:0 0 auto}
.ug-tabs{overflow-x:auto;scrollbar-width:none}
.ug-tab{white-space:nowrap;display:inline-flex;align-items:center;gap:6px}
.ug-n{font-size:10.5px;font-weight:700;background:var(--surface);color:var(--ink-soft);border:1px solid var(--line-soft);
  border-radius:999px;padding:0 7px;line-height:17px;min-width:18px;text-align:center}
.ug-n:empty{display:none}
.ug-tab.is-active .ug-n{background:var(--brand-weak);color:var(--brand);border-color:transparent}
.ug-box .ug-pane{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:10px;padding:12px 18px 0}
.ug-box .ug-pane[hidden]{display:none}
.ug-gbox{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:10px}
.ug-tools{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.ug-tools,.ug-stats,.ug-add,.gr-intro,.ug-bulk{flex:0 0 auto}
.ug-search{flex:1 1 240px;position:relative}
.ug-search input{width:100%;height:36px;border:1px solid var(--line);border-radius:10px;padding:0 12px 0 34px;font:inherit;font-size:13px;
  background:var(--panel) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%235f6368' stroke-width='2' stroke-linecap='round' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E") no-repeat 11px 50%}
.ug-search input:focus,.ug-sel:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}
.ug-sel{height:36px;border:1px solid var(--line);border-radius:10px;padding:0 8px;font:inherit;font-size:12.5px;background:var(--panel);max-width:220px}
.ug-new{height:36px;white-space:nowrap}
.ug-new.is-on{filter:brightness(.92)}
.ug-stats{display:flex;flex-wrap:wrap;gap:6px}
.ug-stat{border:1px solid var(--line-soft);background:var(--panel);border-radius:999px;padding:3px 11px;font:inherit;font-size:12px;
  color:var(--ink-soft);cursor:pointer;transition:background .15s,border-color .15s}
.ug-stat b{color:var(--ink);font-weight:700}
.ug-stat:hover{background:var(--surface)}
.ug-stat.is-on{background:var(--brand-weak);border-color:var(--brand);color:var(--brand)}
.ug-stat.is-on b{color:var(--brand)}
.ug-stat.warn b{color:var(--warn)}
.gr-intro{font-size:12px;line-height:1.55;color:var(--ink-soft);margin:0}
.gr-intro summary{cursor:pointer;color:var(--brand);font-weight:600;width:max-content}
/* form thêm người dùng (gập) */
.ug-add{border:1px solid var(--line-soft);background:var(--surface);border-radius:12px;padding:12px}
.ug-add[hidden]{display:none}
.ug-add-grid{display:grid;grid-template-columns:1fr 1fr 1.2fr auto;gap:10px;align-items:end}
.ug-add label{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:600;color:var(--ink-soft)}
.ug-add input,.ug-add select{height:36px;border:1px solid var(--line);border-radius:9px;padding:0 10px;font:inherit;font-size:13px;background:var(--panel)}
.ug-add-act{display:flex;gap:6px}
.ug-add-hint{font-size:11.5px;color:var(--ink-faint);margin-top:8px}
/* danh sách: khung cuộn, tiêu đề dính */
.ug-list{flex:1 1 auto;min-height:120px;overflow:auto;border:1px solid var(--line-soft);border-radius:12px;background:var(--panel);
  transition:opacity .15s;overscroll-behavior:contain}
.ug-list.is-loading{opacity:.55;pointer-events:none}
.ug-empty{padding:28px 16px;text-align:center;color:var(--ink-faint);font-size:13px}
.ug-muted{color:var(--ink-faint);font-size:12px}
.ug-warn{color:var(--warn);font-weight:600;font-size:12px}
.ug-grid{display:grid;font-size:12.5px;min-width:0}
.ug-hd,.ug-row{display:grid;grid-column:1 / -1;grid-template-columns:subgrid;align-items:center}
.ug-users{grid-template-columns:36px minmax(150px,1.2fr) 124px minmax(200px,2fr) 124px 92px 78px}
.ug-groups{grid-template-columns:minmax(190px,1.8fr) 124px 96px minmax(190px,1.8fr) minmax(160px,1.3fr) 78px}
.ug-hd{position:sticky;top:0;z-index:2;background:var(--surface);border-bottom:1px solid var(--line);
  font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint)}
.ug-hd > *{padding:8px 10px;text-align:left}
.ug-sort{border:0;background:none;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit;cursor:pointer}
.ug-sort:hover{color:var(--brand)}
.ug-arr{font-style:normal;font-size:9px}
.ug-row{border-bottom:1px solid var(--line-soft);min-height:50px;transition:background .12s}
.ug-row > *{padding:7px 10px;min-width:0}
.ug-row:hover{background:var(--surface)}
.ug-row.is-sel{background:var(--brand-weak)}
.ug-row.off .ug-uname b{color:var(--ink-faint);text-decoration:line-through}
.ug-ck{display:flex;align-items:center;justify-content:center;cursor:pointer}
.ug-ck input{width:16px;height:16px;cursor:pointer;accent-color:var(--brand)}
.ug-user{display:flex;align-items:center;gap:9px}
.ug-uname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ug-me{font-size:10px;font-weight:700;color:var(--brand);background:var(--brand-weak);border-radius:5px;padding:0 5px;vertical-align:1px}
.ug-av{flex:0 0 30px;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;font-weight:700;font-size:12.5px;
  color:#fff;background:#94a3b8}
.ug-av.r-admin{background:#c2410c}.ug-av.r-editor{background:#15803d}.ug-av.r-viewer{background:#0369a1}
.ug-role select{width:100%;height:32px;border:1px solid var(--line);border-radius:8px;padding:0 6px;font:inherit;font-size:12px;background:var(--panel)}
.ug-ugrp{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
.ug-gchip{display:inline-flex;align-items:center;gap:3px;max-width:190px;font-size:11.5px;background:var(--surface,#f1f5f9);border:1px solid var(--line-soft);
  border-radius:999px;padding:1px 9px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink)}
.ug-gchip.mgr{background:var(--warn-weak,#fff7ed);border-color:#fdba74;color:#7c2d12}
.ug-gchip.more{background:var(--panel);color:var(--ink-soft);cursor:help}
.ug-gchip button{border:0;background:none;cursor:pointer;color:var(--ink-faint);font-size:14px;line-height:1;padding:0 0 0 2px}
.ug-gchip button:hover{color:var(--danger)}
.ug-link{border:0;background:none;color:var(--brand);font:inherit;font-size:12px;font-weight:600;cursor:pointer;padding:2px 4px;border-radius:6px}
.ug-link:hover{background:var(--brand-weak)}
.ug-switch{display:inline-flex;align-items:center;gap:7px;cursor:pointer;font-size:12px;color:var(--ink-soft);user-select:none}
.ug-switch input{position:absolute;opacity:0;width:0;height:0}
.ug-switch i{position:relative;width:32px;height:18px;border-radius:999px;background:#cbd5e1;transition:background .15s;flex:0 0 32px}
.ug-switch i::after{content:"";position:absolute;left:2px;top:2px;width:14px;height:14px;border-radius:50%;background:#fff;
  box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
.ug-switch input:checked + i{background:#16a34a}
.ug-switch input:checked + i::after{transform:translateX(14px)}
.ug-switch input:disabled + i{opacity:.5}
.ug-switch input:focus-visible + i{box-shadow:var(--ring)}
.ug-date{color:var(--ink-faint);font-size:11.5px;white-space:nowrap}
.ug-act{display:flex;gap:4px;justify-content:flex-end}
/* nhóm */
.gg-name b{display:block;overflow:hidden;text-overflow:ellipsis}
.gg-name small,.gg-mem small{display:block;color:var(--ink-faint);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gg-kchip{font-size:11.5px;color:var(--ink-soft);background:var(--surface);border:1px solid var(--line-soft);border-radius:6px;padding:1px 7px;white-space:nowrap}
.gg-scope{font-size:12px;line-height:1.45}
.gg-cov{display:inline-block;font-size:11px;font-weight:700;color:var(--brand);background:var(--brand-weak);border-radius:999px;padding:0 7px}
.gg-mcount{font-weight:700;margin-right:6px}
.gg-mgrs{font-size:11.5px;color:#9a3412}
/* phân trang + thanh thao tác hàng loạt */
.ug-pager{flex:0 0 auto;display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 0 10px;font-size:12.5px;color:var(--ink-soft)}
.ug-pager:empty{display:none}
.ug-pages{display:flex;gap:3px;margin:0 auto}
.ug-pg{min-width:32px;height:32px;border:1px solid var(--line-soft);background:var(--panel);border-radius:8px;font:inherit;font-size:12.5px;cursor:pointer;color:var(--ink)}
.ug-pg:hover:not(:disabled){border-color:var(--brand);color:var(--brand)}
.ug-pg.is-on{background:var(--brand);border-color:var(--brand);color:#fff;font-weight:700}
.ug-pg:disabled{opacity:.4;cursor:default}
.ug-dots{align-self:center;padding:0 2px;color:var(--ink-faint)}
.ug-size{height:32px;border:1px solid var(--line);border-radius:8px;font:inherit;font-size:12px;background:var(--panel);padding:0 6px}
.ug-bulk{flex:0 0 auto;display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:8px 10px;border-radius:12px;
  background:var(--brand-weak);border:1px solid #c6dafc;font-size:12.5px;color:var(--brand-ink);margin-top:2px}
.ug-bulk > b{margin-right:4px}
.ug-bulk .chip{background:var(--panel)}
.ug-bsel{height:30px;border:1px solid var(--line);border-radius:999px;font:inherit;font-size:12px;background:var(--panel);padding:0 8px}
.ug-bx{margin-left:auto}
.ug-foot-hint{margin-right:auto;font-size:11.5px}
/* trình sửa nhóm */
.ge-wrap{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.ge-head{display:flex;align-items:center;gap:10px;padding-bottom:8px;flex-wrap:wrap}
.ge-head h4{margin:0;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex:1}
.ug-back{border:1px solid var(--line-soft);background:var(--panel);border-radius:999px;padding:5px 12px;font:inherit;font-size:12.5px;cursor:pointer;color:var(--brand)}
.ug-back:hover{background:var(--brand-weak)}
.ge-body{flex:1 1 auto;min-height:0;overflow:auto;display:grid;grid-template-columns:1fr 1fr;gap:12px;align-content:start;padding-bottom:12px;overscroll-behavior:contain}
.ge-card{border:1px solid var(--line-soft);border-radius:12px;padding:12px 14px;background:var(--panel);display:flex;flex-direction:column;gap:10px;min-width:0}
.ge-card:first-child{grid-column:1 / -1}
.ge-card h5{margin:0;font-size:13px;font-weight:700;color:var(--ink)}
.ge-cnt{font-weight:600;color:var(--ink-faint);font-size:12px}
.ge-card label{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:600;color:var(--ink-soft);position:relative}
.ge-card input:not([type=checkbox]),.ge-card select{height:36px;border:1px solid var(--line);border-radius:9px;padding:0 10px;font:inherit;font-size:13px;background:var(--panel);font-weight:400;color:var(--ink)}
.ge-card input:focus,.ge-card select:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}
.ge-card .ge-chk{flex-direction:row;align-items:center;font-weight:400;color:var(--ink)}
.ge-g3{display:grid;grid-template-columns:2fr 1fr 1fr;gap:10px}
.ge-g2{display:grid;grid-template-columns:1fr 1.4fr;gap:10px}
.ge-rule{display:flex;flex-direction:column;gap:10px}
.ge-chips{display:flex;flex-wrap:wrap;gap:5px;max-height:150px;overflow:auto}
.ge-madd{position:relative}
.ge-madd input{width:100%}
.ge-mtools{display:flex;gap:8px;align-items:center}
.ge-mtools input{flex:1;height:32px !important}
.ge-mhint{font-size:11px;color:var(--ink-faint);white-space:nowrap}
.ge-mlist{display:flex;flex-direction:column;border:1px solid var(--line-soft);border-radius:10px;max-height:340px;overflow:auto;min-height:60px}
.ge-mlist > .ug-muted{padding:14px;text-align:center}
.ge-m{display:flex;align-items:center;gap:9px;padding:6px 8px;border-bottom:1px solid var(--line-soft)}
.ge-m:last-child{border-bottom:0}
.ge-m.off .ge-mname b{color:var(--ink-faint)}
.ge-m .ug-av{flex-basis:26px;width:26px;height:26px;font-size:11px}
.ge-mname{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.25}
.ge-mname b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px}
.ge-mname small{color:var(--ink-faint);font-size:11px}
.ge-star{border:1px solid var(--line-soft);background:var(--panel);border-radius:999px;padding:2px 9px;font:inherit;font-size:11.5px;color:#cbd5e1;cursor:pointer;white-space:nowrap}
.ge-star span{color:var(--ink-faint)}
.ge-star.is-on{background:var(--warn-weak,#fff7ed);border-color:#fdba74;color:#ea580c}
.ge-cap{font:inherit;font-size:11.5px;padding:2px 4px;border:1px solid var(--line-soft);border-radius:6px;max-width:130px}
.ge-star.is-on span{color:#9a3412;font-weight:600}
.ge-x{border:0;background:none;width:28px;height:28px;border-radius:50%;font-size:18px;line-height:1;color:var(--ink-faint);cursor:pointer}
.ge-x:hover{background:var(--danger-weak,#fce8e6);color:var(--danger)}
.ge-foot{flex:0 0 auto;display:flex;justify-content:flex-end;gap:8px;padding:10px 0 12px;border-top:1px solid var(--line-soft)}
/* ô tìm có gợi ý */
.ge-ac{position:absolute;left:0;right:0;top:100%;margin-top:3px;z-index:20;background:var(--panel);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shadow-3);max-height:280px;overflow:auto;padding:4px}
.ge-ac[hidden]{display:none}
.ge-ac-it{display:flex;flex-direction:column;align-items:flex-start;width:100%;border:0;background:none;text-align:left;padding:7px 10px;
  border-radius:7px;font:inherit;font-size:12.5px;cursor:pointer;color:var(--ink)}
.ge-ac-it small{color:var(--ink-faint);font-size:11px;font-weight:400}
.ge-ac-it:hover,.ge-ac-it.is-hi{background:var(--brand-weak)}
.ge-ac-none{padding:10px;color:var(--ink-faint);font-size:12px;font-weight:400}
/* bộ chọn nhóm (200+ nhóm) */
.modal-box.ugp-box{width:min(580px,96vw);height:min(80vh,760px);max-height:none;display:flex;flex-direction:column;overflow:hidden}
.ugp-tools{display:flex;gap:8px;padding:12px 16px 8px}
.ugp-tools select{flex:0 1 auto;min-width:0}
.ugp-tools input{flex:1 1 0;min-width:0;height:36px;border:1px solid var(--line);border-radius:10px;padding:0 12px;font:inherit;font-size:13px}
.ugp-tools select{height:36px;border:1px solid var(--line);border-radius:10px;font:inherit;font-size:12.5px;max-width:45%}
.ugp-sel{display:flex;flex-wrap:wrap;gap:5px;padding:0 16px 8px;max-height:92px;overflow:auto}
.ugp-list{flex:1 1 auto;min-height:0;overflow:auto;padding:0 10px;overscroll-behavior:contain}
.ugp-row{display:flex;align-items:center;gap:10px;padding:8px;border-radius:9px;cursor:pointer;border-bottom:1px solid var(--line-soft)}
.ugp-row:hover{background:var(--surface)}
.ugp-row.is-on{background:var(--brand-weak)}
.ugp-row input{width:17px;height:17px;accent-color:var(--brand);flex:0 0 auto}
.ugp-name{flex:1;min-width:0;display:flex;flex-direction:column;font-size:13px}
.ugp-name b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.ugp-name small{color:var(--ink-faint);font-size:11px}
.ugp-count{margin-right:auto;font-size:12px}

@media (max-width:1000px){
  .ug-users{grid-template-columns:36px minmax(140px,1fr) 118px minmax(170px,1.6fr) 118px 0 72px}
  .ug-users .ug-date,.ug-users .ug-hd > :nth-child(6){overflow:hidden;padding:0;font-size:0}
  .ge-body{grid-template-columns:1fr}
}
@media (max-width:768px){
  .ug-box .ug-pane{padding:10px 12px 0;gap:8px}
  .ug-foot-hint{display:none}
  .ug-box .modal-foot{padding-top:8px}
  .modal-box.ug-box{width:100vw;height:100dvh}
  .ug-tools{gap:6px}
  .ug-search{flex:1 1 calc(100% - 56px);min-width:0;order:0}
  .ug-new{flex:0 0 auto;order:1;width:44px;height:40px;padding:0;justify-content:center}
  .ug-new span{display:none}
  .ug-sel{order:2;flex:1 1 28%;min-width:0;max-width:none;height:40px;padding:0 4px}
  .ug-stats{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;margin:0 -12px;padding:0 12px}
  .ug-stat{white-space:nowrap;flex:0 0 auto}
  .ug-add-grid{grid-template-columns:1fr}
  .ug-add-act .btn{flex:1;justify-content:center}
  .ug-list{border:0;border-radius:0;background:transparent;margin:0 -12px;padding:0 12px 8px}
  /* bảng -> thẻ */
  .ug-grid{display:flex;flex-direction:column;gap:8px}
  .ug-hd{display:none}
  .ug-row{background:var(--panel);border:1px solid var(--line-soft);border-radius:14px;box-shadow:0 1px 2px rgba(0,0,0,.04);min-height:0;padding:4px 2px}
  .ug-row > *{padding:4px 8px}
  .ug-users .ug-row{grid-template-columns:34px minmax(0,1fr) auto;
    grid-template-areas:"ck user act" ". role status" ". groups groups"}
  .ug-users .ug-ck{grid-area:ck}.ug-users .ug-user{grid-area:user}.ug-users .ug-act{grid-area:act}
  .ug-users .ug-role{grid-area:role}.ug-users .ug-status{grid-area:status;justify-self:end}
  .ug-users .ug-ugrp{grid-area:groups}
  .ug-users .ug-date{display:none}
  .ug-role select{height:36px;font-size:14px}
  .ug-groups .ug-row{grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"name act" "tags tags" "scope scope" "mem mem"}
  .gg-name{grid-area:name}.ug-groups .ug-act{grid-area:act}
  .gg-kind{grid-area:tags;display:flex;gap:6px;align-items:center}
  .gg-perm{grid-area:tags;justify-self:end}
  .gg-scope{grid-area:scope}.gg-mem{grid-area:mem}
  .acct-btn{width:36px;height:36px}
  .ug-pager{padding:8px 0;gap:6px;justify-content:space-between}
  .ug-pages{margin:0;order:3;flex-basis:100%;justify-content:center}
  .ug-pg{min-width:38px;height:38px}
  .ug-bulk{position:sticky;bottom:0;box-shadow:0 -4px 12px rgba(0,0,0,.08)}
  .ug-bulk .chip{padding:6px 11px}
  .ge-g3,.ge-g2{grid-template-columns:1fr}
  .ge-card{padding:12px}
  .ge-card input:not([type=checkbox]),.ge-card select,.ugp-tools input,.ugp-tools select,.ug-search input,.ug-add input,.ug-add select{font-size:16px;height:40px}
  .ge-mlist{max-height:none}
  .ge-star span{display:none}
  .ge-foot .btn{flex:1;justify-content:center}
  .modal-box.ugp-box{width:100vw;height:100dvh}
  .ugp-row{padding:11px 8px}
}

/* Nút thu/mở sidebar nổi */
#sb-toggle{border:0;border-radius:12px;box-shadow:var(--shadow-2);width:40px;height:40px;
  left:16px;top:16px;color:var(--ink-soft)}
#sb-toggle:hover{background:#f1f3f4;color:var(--ink)}

/* ---------- Readouts ---------- */
.coord-readout{
  background:var(--glass);color:var(--ink-soft);border:1px solid var(--line-soft);
  box-shadow:var(--shadow-1);backdrop-filter:blur(8px);font-weight:600;
  left:14px;bottom:14px;font-size:11px;padding:4px 9px;border-radius:8px;
}
/* mức zoom: chip nhỏ tinh tế, xếp chồng góc dưới-trái (trên dòng toạ độ) */
.zoom-readout{
  left:14px;right:auto;bottom:46px;
  background:var(--glass);color:var(--ink-soft);border:1px solid var(--line-soft);
  box-shadow:var(--shadow-1);backdrop-filter:blur(8px);
  font-size:11px;font-weight:700;letter-spacing:.2px;padding:3px 8px;border-radius:8px;
}
.scalebar{background:var(--glass);border-color:var(--line-soft);box-shadow:var(--shadow-1);
  border-radius:8px;color:var(--ink-soft)}
.sb-bar{border-color:var(--ink-soft)}
/* nút +/- của MapLibre: đồng bộ phong cách */
.maplibregl-ctrl-group{border-radius:11px!important;box-shadow:var(--shadow-2)!important;
  border:0!important;overflow:hidden}
.maplibregl-ctrl-group button{width:36px!important;height:36px!important}
.maplibregl-ctrl-group button+button{border-top:1px solid var(--line-soft)!important}

/* ---------- Panels / cards ---------- */
.project-item{border:1px solid var(--line-soft);border-radius:11px;padding:9px 11px;
  transition:border-color .15s,background .15s,box-shadow .15s}
.project-item:hover{border-color:transparent;background:var(--panel);box-shadow:var(--shadow-2)}
.project-item.active{border-color:var(--brand);background:var(--brand-weak);box-shadow:none}

/* Danh mục đồ án: mẫu chữ & màu thống nhất, gọn — tên tối đa 2 dòng */
.project-list{gap:5px}
.pi-name{
  font-weight:600;font-size:12.5px;line-height:1.32;color:var(--ink);
  letter-spacing:-.005em;margin-bottom:3px;
  white-space:normal;word-break:normal;overflow-wrap:anywhere;
}
.pi-loc{
  display:flex;align-items:center;gap:4px;margin-bottom:4px;
  font-size:11px;line-height:1.3;color:var(--ink-soft);
}
.pi-loc .ic{width:12px;height:12px;flex:0 0 12px;color:var(--ink-faint)}
.pi-loc span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.pi-sub{gap:4px 5px;font-size:10.5px}
.pi-badge{
  background:var(--surface);border:1px solid var(--line-soft);border-radius:999px;
  padding:1px 7px;font-size:10px;font-weight:600;color:var(--ink-faint);
}
.pi-badge.doc{background:var(--brand-weak);border-color:transparent;color:var(--brand-ink)}
.pi-badge.pi-tag{
  background:var(--brand);border-color:transparent;color:#fff;
  font-weight:700;letter-spacing:.02em;padding:1px 8px;
}
.pi-badge.warn{background:var(--warn-weak,#fef3c7);border-color:transparent;color:var(--warn-ink,#92400e)}
.pi-badge.err{background:var(--danger-weak,#fee2e2);border-color:transparent;color:var(--danger-ink,#b91c1c)}
.project-item mark{
  background:var(--brand-weak);color:var(--brand-ink);
  border-radius:3px;padding:0 1.5px;font-weight:700;
}
@supports (background:color-mix(in srgb,red,blue)){
  .project-item mark{background:color-mix(in srgb,var(--brand) 20%,transparent);color:inherit}
}
.lt-nhom{border-color:var(--line-soft);border-radius:12px}
.lt-nhom>summary{background:var(--brand-weak);font-weight:650}
.lt-group>summary{background:var(--surface);border-color:var(--line-soft);border-radius:9px}
.lt-item{border-radius:8px;transition:background .12s}
.lt-item:hover{background:var(--surface)}
.lt-item input[type=checkbox],.lt-showall-lbl input,.lt-grp{accent-color:var(--brand)}
.lt-tbl,.lt-sty,.lt-del,.lt-ren{border:0;background:transparent;color:var(--ink-faint);border-radius:8px;
  width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;
  transition:background .13s,color .13s;cursor:pointer}
.lt-tbl:hover,.lt-sty:hover,.lt-ren:hover{background:var(--hover);color:var(--brand);transform:none;opacity:1}
.lt-del:hover{background:var(--danger-weak,#fce8e6);color:var(--danger);transform:none;opacity:1}

/* ô đang sửa nhập sai kiểu */
.cell-inp.cell-bad{outline:2px solid var(--danger)!important;background:var(--danger-weak,#fef2f2)}

/* panel cột: cột ngoài chuẩn + nút xoá cột */
.cp-list label.cp-extra .cp-lbl{color:var(--warn)}
.cp-badge{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  color:var(--warn);background:var(--warn-weak,#fff7ed);border:1px solid #fed7aa;border-radius:5px;padding:0 4px;margin-left:4px}
.cp-list label{display:flex;align-items:center;gap:6px}
.cp-lbl{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cp-del{flex:0 0 auto;border:0;background:transparent;color:var(--ink-faint);cursor:pointer;
  font-size:12px;width:20px;height:20px;border-radius:5px;line-height:1}
.cp-del:hover{background:var(--danger-weak,#fce8e6);color:var(--danger)}
.lt-opacity{accent-color:var(--brand)}

/* ---------- Modal ---------- */
.modal{background:rgba(32,33,36,.55);backdrop-filter:blur(2px)}
.modal-box{border-radius:16px;box-shadow:var(--shadow-3);border:1px solid var(--line-soft)}
.modal-head{padding:18px 22px}
.modal-head h3{font-weight:700;letter-spacing:-.01em}
.modal-foot{padding:16px 22px;gap:8px}

/* ---------- Popup bản đồ ---------- */
.maplibregl-popup-content{border-radius:14px;box-shadow:var(--shadow-3);border:1px solid var(--line-soft)}
.popup-head{background:linear-gradient(135deg,var(--brand),var(--brand-2));font-weight:650}
.popup-toggle{color:var(--brand)}

/* ---------- Thanh chọn nổi (sel-bar) ---------- */
.sel-bar,.tbl-sel-bar{border-radius:14px;background:rgba(32,33,36,.94);box-shadow:var(--shadow-3)}
.sel-bar .btn{border-radius:999px}

/* ---------- Dock bảng dữ liệu ---------- */
.dock-bar{background:var(--surface)}
.dock-modes button{border:0;background:transparent;color:var(--ink-soft);border-radius:8px;
  width:30px;height:28px;transition:background .12s,color .12s}
.dock-modes button:hover{background:var(--hover);color:var(--ink)}
#main-col[data-dock="half"]   .dock-modes [data-mode="half"],
#main-col[data-dock="custom"] .dock-modes [data-mode="half"],
#main-col[data-dock="full"]   .dock-modes [data-mode="full"]{
  background:var(--brand);color:#fff;box-shadow:0 2px 6px var(--brand-a35)}
table.grid thead th{background:var(--surface);border-color:var(--line-soft);color:var(--ink-soft);
  font-weight:650;letter-spacing:.02em}
table.grid td{border-color:var(--line-soft)}
table.grid tbody tr:hover{background:var(--brand-weak)}

/* ---------- Toast ---------- */
.toast{border-radius:12px;box-shadow:var(--shadow-3);font-weight:600;background:#202124}
.toast.ok{background:var(--ok)} .toast.err{background:var(--danger)}

/* ---------- Empty state ---------- */
.empty-state{background:var(--surface)}
.es-card{border:0;border-radius:20px;box-shadow:var(--shadow-2);padding:32px 38px}

/* ---------- Style editor ---------- */
.sty-sec{border-color:var(--line-soft);border-radius:12px}
.sty-sec h4{color:var(--brand);letter-spacing:.6px}
.sty-row input[type=range],.sty-row-z input[type=range]{accent-color:var(--brand)}
.sty-tools{background:var(--brand-weak);border-color:transparent;border-radius:10px}

/* ---------- Chi tiết nhỏ ---------- */
.flt-chip{background:var(--brand-weak);color:var(--brand-ink);border-radius:999px}
.pi-ic{border:1px solid var(--line-soft);border-radius:8px;color:var(--ink-soft);
  transition:border-color .13s,color .13s,background .13s}
.pi-ic:hover{background:var(--brand-weak);border-color:transparent;color:var(--brand)}
.pi-ic.pi-del:hover{background:var(--danger-weak,#fce8e6);color:var(--danger)}
.dropzone{border-radius:14px;border-color:var(--line)}
.dropzone.drag{border-color:var(--brand);background:var(--brand-weak)}
.progress-bar span{background:linear-gradient(90deg,var(--brand),var(--brand-2))}
a{color:var(--brand)}
code{background:var(--brand-weak);color:var(--brand-ink)}

/* ---------- Cây lớp: MẬT ĐỘ CAO, nhãn đọc rõ, công cụ ẩn/hiện khi rê chuột ---------- */
.layer-tree{gap:4px}
.lt-items{gap:0;padding:1px 2px 2px 6px}
.lt-item{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:start;column-gap:8px;row-gap:0;
  padding:4px 8px;border-radius:8px;position:relative;
  transition:background .12s;
}
.lt-item>input[type=checkbox]{grid-column:1;grid-row:1;margin-top:1px;width:14px;height:14px}
.lt-name{
  grid-column:2;grid-row:1;
  white-space:normal;word-break:break-word;overflow:visible;text-overflow:clip;
  line-height:1.3;font-size:12px;font-weight:500;color:var(--ink);
  letter-spacing:-.005em;padding:0;cursor:pointer;min-width:0;
}
.lt-name:hover{color:var(--brand)}
.lt-fc{
  grid-column:3;grid-row:1;align-self:center;
  font-variant-numeric:tabular-nums;font-size:9.5px;font-weight:700;letter-spacing:.01em;
  color:var(--ink-faint);background:var(--surface);
  border:1px solid var(--line-soft);border-radius:999px;
  padding:0 6px;min-width:18px;line-height:1.55;text-align:center;transition:opacity .12s;
}
/* công cụ: phủ mép phải hàng 1, hiện mượt khi hover / focus (không đẩy layout) */
.lt-tools{
  position:absolute;right:6px;top:2px;
  display:flex;align-items:center;gap:1px;
  padding-left:30px;border-radius:8px;
  background:linear-gradient(to right,transparent,var(--surface) 38%);
  opacity:0;pointer-events:none;transition:opacity .12s ease;
}
.lt-item:hover .lt-tools,
.lt-item:focus-within .lt-tools{opacity:1;pointer-events:auto}
.lt-item:hover .lt-fc,
.lt-item:focus-within .lt-fc{opacity:0}
.lt-tools .lt-opacity{width:54px;height:14px;margin:0 4px 0 2px;accent-color:var(--brand)}
.lt-tools .lt-sty,.lt-tools .lt-tbl,.lt-tools .lt-ren,.lt-tools .lt-del{width:24px;height:24px}
.lt-item.disabled{opacity:.4}
.lt-item.disabled .lt-tools{display:none}

/* nhóm / tập dữ liệu: nhãn khoa học, gọn */
.lt-nhom{
  border-color:var(--line-soft);border-radius:10px;margin-bottom:5px;overflow:hidden;
  content-visibility:auto;contain-intrinsic-size:auto 96px;
}
.lt-nhom>summary{
  align-items:center;line-height:1.3;padding:6px 10px;gap:8px;
  background:var(--brand-weak);font-weight:650;font-size:11.5px;
}
.lt-nhom>div{padding:3px 6px 5px}
.lt-nhom>summary>b,.lt-group>summary>b{white-space:normal;word-break:break-word;font-weight:inherit}
.lt-group{border:0;margin:1px 0 1px 2px}
.lt-group>summary{
  align-items:center;line-height:1.3;padding:4px 7px;gap:6px;
  background:transparent;border:0;font-size:10.5px;font-weight:700;
  letter-spacing:.005em;text-transform:none;color:var(--ink-faint);
}
.lt-group>summary::before{font-size:9px}
.lt-group>summary:hover{background:var(--surface)}
.lt-group[open]>summary{color:var(--ink-soft)}
/* cụm lớp "đơn" (1 lớp / tập dữ liệu) — nằm thẳng dưới nhóm, không tiêu đề con */
.lt-solo{padding-left:4px;margin:1px 0}
.lt-count{margin-left:auto;font-size:9.5px;font-weight:600;color:var(--ink-faint);background:transparent;border:0}

/* đóng/mở nhóm con mượt (Chrome 131+, tự bỏ qua nơi chưa hỗ trợ) */
@supports selector(::details-content){
  .lt-group::details-content{opacity:0;transition:opacity .15s ease}
  .lt-group[open]::details-content{opacity:1}
}
@media (prefers-reduced-motion:reduce){
  .lt-group::details-content{transition:none}
}

.sp-name{white-space:normal;line-height:1.32;word-break:break-word}
.lt-proj .lp-name{max-width:170px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3;text-align:left}

/* dải "đồ án trên bản đồ" — gọn, hàng chip nhỏ */
.lt-projs{gap:5px;margin-bottom:8px}
.lt-projs .lp-hint{flex-basis:100%;font-size:10.5px;font-weight:600;letter-spacing:0;
  text-transform:none;color:var(--ink-faint);margin-bottom:1px}
.lt-proj{font-size:11.5px;border-color:var(--line-soft);background:var(--surface)}
.lt-proj .lp-name{padding:3px 3px 3px 9px}
.lt-proj .lp-x{padding:3px 7px 3px 3px;font-size:13px}
.lt-proj.is-active{background:var(--brand-weak)}

/* ảnh bay đang xử lý nền / lỗi (nhóm "Ảnh nền đồ án") */
.lt-ortho-pending .lt-name{white-space:normal;font-style:italic;color:var(--ink-soft);cursor:default}
.lt-ortho-pending.is-error .lt-name{color:var(--danger);font-style:normal}
.ortho-hint{font-size:11.5px;line-height:1.45;margin-top:4px}
.dock-title{max-width:none;white-space:normal}

/* thiết bị chạm: không có hover -> công cụ hiện sẵn ở hàng 2 */
@media (hover:none){
  .lt-tools{
    position:static;grid-column:1 / -1;grid-row:2;
    opacity:1;pointer-events:auto;justify-content:flex-end;
    padding-left:0;background:none;margin-top:3px;
  }
  .lt-item:hover .lt-fc,.lt-item:focus-within .lt-fc{opacity:1}
}

/* ---------- Toolbar: cụm công cụ ---------- */
.tool-cluster{display:inline-flex;align-items:center;gap:2px}
.toolbar .tool-sep{height:26px;margin:0 4px;background:var(--line-soft)}

/* ---------- Chấm định vị GPS ---------- */
.geo-dot{position:relative;width:16px;height:16px;border-radius:50%;background:#1a73e8;
  border:3px solid #fff;box-shadow:0 0 0 2px rgba(26,115,232,.35),0 1px 4px rgba(0,0,0,.3)}
.geo-dot::after{content:"";position:absolute;left:50%;top:50%;width:16px;height:16px;
  margin:-8px 0 0 -8px;border-radius:50%;background:rgba(26,115,232,.35);
  animation:geopulse 1.8s ease-out infinite}
@keyframes geopulse{0%{transform:scale(1);opacity:.6}100%{transform:scale(4);opacity:0}}

/* ---------- Bảng vẽ / nhập toạ độ ---------- */
#modal-draw textarea{font-family:ui-monospace,Consolas,"SF Mono",monospace;font-size:12.5px;
  line-height:1.5;white-space:pre;overflow-wrap:normal}
.draw-list{display:flex;flex-direction:column;gap:5px;max-height:34vh;overflow:auto}
.draw-row{display:flex;align-items:center;gap:8px;padding:6px 10px;border:1px solid var(--line-soft);
  border-radius:10px;font-size:12.5px}
.draw-tag{font-weight:700;color:var(--brand-ink);background:var(--brand-weak);
  border-radius:999px;padding:1px 9px;font-size:11.5px}
.draw-meta{color:var(--ink-soft);flex:1}
.draw-row .chip.del{color:var(--danger);border-color:#f2b8b5}

/* ==========================================================================
   ĐIỆN THOẠI / MÀN HÌNH NHỎ  (iOS Safari + Android Chrome)
   Nạp sau cùng - chỉ tinh chỉnh thị giác & vùng chạm, không đổi DOM.
   ========================================================================== */

/* Bỏ ô sáng xanh khi chạm; cuộn mượt trong panel */
*{-webkit-tap-highlight-color:transparent}

/* Màn che sidebar - chỉ dùng trên điện thoại (mặc định ẩn hẳn) */
.sb-scrim{display:none}

/* ---------- Sidebar chrome gọn — nhường tối đa diện tích cho nội dung ----------
   Header 1 hàng: [logo] tiêu đề … [avatar ▾] [«]. Tài khoản/quản trị nằm trong
   popover mở từ avatar; công cụ ký hiệu nằm trong menu "⋯" của panel Lớp. */
.side-head{padding:9px 12px;position:relative}
.brand{gap:9px;align-items:center}
.brand-mark{width:30px;height:30px;flex:0 0 30px;border-radius:9px;font-size:11.5px}
.brand-tt{min-width:0;flex:1 1 auto}
.brand-title{font-size:13.5px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brand-sub{display:none}
.side-head .sb-hide{position:static;margin:0 0 0 2px;flex:0 0 auto}

.side-auth{display:flex;align-items:center;gap:4px;width:auto;flex:0 0 auto}
.acct{
  position:relative;
  width:32px;height:32px;flex:0 0 32px;padding:0;border:0;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;color:#fff;
  background:linear-gradient(140deg,var(--brand),var(--brand-2));
  box-shadow:var(--shadow-1);transition:box-shadow .15s;
}
.acct[hidden]{display:none}
.acct .acct-av{width:32px;height:32px;display:grid;place-items:center;background:none;box-shadow:none}
.acct .acct-av .ic{width:17px;height:17px}
/* dấu tam giác nhỏ -> báo hiệu đây là MENU (đổi mật khẩu / đăng xuất) */
.acct::after{
  content:"";position:absolute;right:-2px;bottom:-2px;width:13px;height:13px;border-radius:50%;
  background:var(--panel) center/7px 7px no-repeat;box-shadow:0 0 0 2px var(--panel),var(--shadow-1);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6368' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  transition:transform .15s;
}
.acct[aria-expanded="true"]::after{transform:rotate(180deg)}
.acct:hover,.acct[aria-expanded="true"]{box-shadow:0 0 0 3px var(--brand-weak),var(--shadow-1)}
.acct-login{width:auto;padding:6px 12px;border-radius:999px;font-weight:700;white-space:nowrap}

.acct-pop{
  position:absolute;top:calc(100% - 4px);right:10px;z-index:60;min-width:216px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  box-shadow:var(--shadow-2);padding:6px;animation:cIn .12s ease;
}
.acct-pop-hd{display:flex;flex-direction:column;gap:1px;
  padding:7px 10px 8px;margin-bottom:4px;border-bottom:1px solid var(--line-soft)}
.acct-pop-hd .acct-name{font-weight:700;font-size:13px;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct-pop-hd .acct-role{font-size:10.5px;font-weight:600;letter-spacing:0;
  text-transform:none;color:var(--ink-faint)}
.acct-pop-hd .acct-role[data-role="admin"]{color:var(--brand-ink)}
.acct-pop-hd .acct-role[data-role="editor"]{color:var(--ok)}
.acct-item{
  display:flex;align-items:center;gap:10px;width:100%;
  padding:8px 10px;border:0;border-radius:9px;background:transparent;
  font:inherit;font-size:12.5px;font-weight:600;color:var(--ink-soft);
  text-align:left;cursor:pointer;transition:background .12s,color .12s;
}
.acct-item .ic{width:16px;height:16px;flex:0 0 16px}
a.acct-item{text-decoration:none;box-sizing:border-box}
.acct-item:hover{background:var(--surface);color:var(--ink)}
.acct-item.acct-out{color:var(--danger)}
.acct-item.acct-out:hover{background:var(--danger-weak,#fce8e6)}
.acct-item[hidden]{display:none}

/* nút hành động trong bảng Quản lý người dùng (vẫn dùng class .acct-btn) */
.acct-btn{
  width:28px;height:28px;border:0;border-radius:8px;background:transparent;
  color:var(--ink-faint);display:grid;place-items:center;cursor:pointer;
  transition:background .12s,color .12s;
}
.acct-btn .ic{width:16px;height:16px}
.acct-btn:hover{background:var(--hover);color:var(--brand)}
.acct-btn.acct-out:hover{background:var(--danger-weak,#fce8e6);color:var(--danger)}
.acct-btn[hidden]{display:none!important}

/* Tabs: icon + nhãn TRÊN 1 HÀNG, gọn; cụm icon lớp nằm cuối hàng (chỉ hiện ở tab Lớp) */
.side-tabs{padding:0 4px;align-items:stretch}
.side-tabs .stab{
  flex:1 1 0;min-width:0;
  display:inline-flex;flex-direction:row;align-items:center;justify-content:center;
  gap:5px;padding:8px 3px;font-size:11.5px;line-height:1;
  white-space:nowrap;overflow:hidden;text-overflow:clip;
}
.side-tabs .stab .ic{width:15px;height:15px;flex:0 0 15px}
.side-tabs .stab.is-active .ic{color:var(--brand)}
.side-tabs .stab-actions{
  display:flex;align-items:center;gap:1px;flex:0 0 auto;
  padding-left:4px;margin-left:2px;border-left:1px solid var(--line-soft);
}
.side-tabs .stab-actions .icon-btn{width:28px;height:28px}
.side-tabs .stab-actions .icon-btn .ic{width:16px;height:16px}
#side-tabs:not([data-tab="layers"]) .stab-actions{display:none}
@media (pointer:coarse){.side-tabs .stab-actions .icon-btn{width:32px;height:32px}}

/* Dải đồ án đang chọn — 1 hàng gọn: [tên] [số liệu mờ] … (i) */
.side-proj{padding:5px 12px;gap:6px}
.side-proj .sp-txt{display:flex;align-items:baseline;gap:8px;min-width:0;flex:1}
.side-proj .sp-name{
  flex:0 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:12.5px;font-weight:700;line-height:1.3;word-break:normal;
}
.side-proj .sp-meta{
  flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:10.5px;font-variant-numeric:tabular-nums;color:var(--ink-faint);
}
.side-proj .icon-btn{width:26px;height:26px;flex:0 0 26px}
.side-proj .icon-btn .ic{width:15px;height:15px}
@media (pointer:coarse){.side-proj{padding:7px 12px}.side-proj .icon-btn{width:34px;height:34px;flex-basis:34px}}

/* Panel Lớp: menu "⋯" gom công cụ ký hiệu + "hiện đầy đủ cây" */
.lt-more-btn{width:28px;height:28px;flex:0 0 28px}
.lt-more-btn.is-on{background:var(--brand-weak);color:var(--brand-ink)}
.lt-more{
  margin:2px 0 9px;padding:9px 10px;border:1px solid var(--line-soft);
  border-radius:12px;background:var(--surface);
  display:flex;flex-direction:column;gap:9px;animation:cIn .12s ease;
}
.lt-more .sty-tools{margin:0;padding:0;background:transparent;border:0}
.lt-more .sty-tools-lbl{width:100%}
.lt-more .lt-showall-lbl{margin:0}

/* ---------- Việt hoá tên trường ---------- */
.fl-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fl-tools #fl-search{flex:1 1 200px;min-width:150px}
.fl-tools #fl-add-name{flex:0 1 180px;min-width:130px}
.fl-tools #fl-search,.fl-tools #fl-add-name{border:1px solid var(--line);
  border-radius:9px;padding:8px 11px;font-size:13px;font-family:inherit}
.fl-spacer{flex:1 1 0}
.fl-list{max-height:56vh;overflow:auto;border:1px solid var(--line-soft);
  border-radius:12px;padding:4px}
.fl-row{display:grid;grid-template-columns:minmax(160px,38%) 1fr;gap:10px;
  align-items:center;padding:6px 8px;border-radius:8px}
.fl-row+.fl-row{border-top:1px solid var(--line-soft)}
.fl-row:hover{background:var(--surface)}
.fl-row.is-ov{background:var(--brand-weak)}
.fl-key{display:flex;flex-direction:column;gap:2px;min-width:0}
.fl-key code{background:transparent;color:var(--ink);font-size:12.5px;padding:0;
  word-break:break-all;font-family:ui-monospace,Consolas,monospace}
.fl-meta{font-size:10.5px;color:var(--ink-faint)}
.fl-inp{border:1px solid var(--line);border-radius:8px;padding:7px 10px;
  font-size:13px;font-family:inherit;width:100%;background:var(--panel)}
.fl-inp:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}
.fl-row.is-ov .fl-inp{border-color:var(--brand)}
.login-ok{background:var(--ok-weak,#e6f4ea);color:var(--ok)}

/* ---------- Kiểm tra / dọn CSDL ---------- */
.cov-sch{font-size:12px;padding:7px 10px;border-radius:9px;margin-bottom:8px;font-weight:600}
.cov-sch.ok{background:var(--ok-weak,#e6f4ea);color:var(--ok)}
.cov-sch.warn{background:#fef3e0;color:var(--warn)}
.cov-sch .chip{margin-left:6px}
.cov-act{padding:6px 2px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cov-extra{margin:8px 2px 4px;padding:8px 10px;background:var(--warn-weak,#fff7ed);border:1px solid #fed7aa;border-radius:9px;font-size:12px}
.cov-xrow{display:flex;align-items:center;gap:8px;padding:4px 0}
.cov-xrow code{background:transparent;color:var(--ink);font-size:12px}
.cov-xrow .chip.del{margin-left:auto;color:var(--danger);border-color:#f2b8b5}

/* Widget toạ độ/zoom: trên desktop trong suốt (con giữ vị trí cũ), nút ẩn */
#mapctl{display:contents}
.mapctl-toggle{display:none}

/* ---------- Chọn bản đồ nền: popup hiện LÊN TRÊN nút ---------- */
.basemap-ctrl{position:absolute;overflow:visible}
.bm-popup{
  position:absolute;left:0;bottom:calc(100% + 8px);
  min-width:210px;max-width:min(74vw,300px);
  background:var(--panel);border:1px solid var(--line-soft);
  border-radius:12px;box-shadow:var(--shadow-3);
  padding:5px;z-index:20;max-height:52vh;overflow:auto;
}
.bm-popup[hidden]{display:none}
.bm-opt{
  display:block;width:100%;text-align:left;
  padding:9px 11px;border:0;background:transparent;border-radius:8px;
  font-size:12.5px;color:var(--ink);white-space:nowrap;cursor:pointer;
}
.bm-opt:hover{background:var(--surface)}
.bm-opt.sel{background:var(--brand-weak);color:var(--brand-ink);font-weight:700}

/* ---------- Cụm điều khiển góc dưới-phải: (i) trên · +/- giữa · thước dưới ---------- */
.maplibregl-ctrl-bottom-right{
  display:flex;flex-direction:column;align-items:flex-end;gap:7px;
  bottom:0;right:0;
}
.maplibregl-ctrl-bottom-right .maplibregl-ctrl{margin:0 10px 0 0!important;float:none!important}
.maplibregl-ctrl-bottom-right .maplibregl-ctrl-attrib{order:1;margin-top:10px!important}
.maplibregl-ctrl-bottom-right .maplibregl-ctrl-group{order:2}
.maplibregl-ctrl-bottom-right .maplibregl-ctrl-scale{order:3;margin-bottom:10px!important}

/* nút (i) attribution: gọn, cùng phong cách */
.maplibregl-ctrl-attrib.maplibregl-compact{min-height:26px;border-radius:999px!important;
  box-shadow:var(--shadow-1)!important}
.maplibregl-ctrl-attrib-button{width:26px!important;height:26px!important}

/* ---------- Thanh tỉ lệ MapLibre: nhỏ gọn ---------- */
.maplibregl-ctrl-scale{
  font-size:9.5px!important;line-height:1.35!important;
  padding:0 4px 1px!important;border-width:1.6px!important;
  border-color:var(--ink-soft)!important;color:var(--ink-soft)!important;
  background:var(--glass)!important;border-radius:0 0 4px 4px!important;
}
.spane,.modal-box,.users-list,.sty-body,.info-body,.imp-layers,.draw-list,
.tbl-grid{-webkit-overflow-scrolling:touch}

/* Chiều cao thật khi thanh địa chỉ co/giãn (dvh) + vùng an toàn tai thỏ */
@supports (height:100dvh){
  #app{height:100dvh}
}

@media (max-width:768px){

  /* ---------- Bố cục chung ---------- */
  #app{height:100vh;height:100dvh;position:relative}
  body{font-size:14px}

  /* ---------- Sidebar = ngăn trượt phủ, có màn che ---------- */
  :root{--side-w:88vw}
  /* dùng translateX để ẩn/hiện (KHÔNG co width=0 như bản desktop) */
  #app #sidebar{
    position:fixed;top:0;bottom:0;left:0;z-index:26;
    width:var(--side-w);max-width:390px;flex:0 0 auto;
    padding-top:env(safe-area-inset-top);
    border-right:1px solid var(--line-soft);
    box-shadow:var(--shadow-3);overflow:hidden;
    transform:translateX(0);
    transition:transform .26s cubic-bezier(.4,0,.2,1);
  }
  #app.sb-collapsed #sidebar{
    transform:translateX(-103%);
    width:var(--side-w);flex-basis:auto;      /* ghi đè app.css: giữ nguyên bề rộng */
  }
  #main-col{width:100%;flex:1 1 100%}

  /* nút hamburger nổi: to, luôn hiện khi sidebar đang thu */
  #sb-toggle{
    display:none;position:fixed;z-index:22;
    top:calc(10px + env(safe-area-inset-top));left:10px;
    width:44px;height:44px;border-radius:13px;
    background:var(--panel);box-shadow:var(--shadow-2);color:var(--ink-soft);
  }
  #app.sb-collapsed #sb-toggle{display:grid}
  #app:not(.sb-collapsed) #sb-toggle{display:none}
  #sb-toggle .ic{width:23px;height:23px}
  .side-head .sb-hide{width:38px;height:38px}
  .side-head .sb-hide .ic{width:20px;height:20px}

  /* màn che sau sidebar */
  .sb-scrim{
    display:block;position:fixed;inset:0;z-index:25;background:rgba(0,0,0,.44);
    opacity:0;pointer-events:none;transition:opacity .24s;
  }
  #app.sb-collapsed .sb-scrim{opacity:0;pointer-events:none}
  #app:not(.sb-collapsed) .sb-scrim{opacity:1;pointer-events:auto}

  /* nội dung panel: chạm rộng hơn */
  .side-tabs .stab{padding:13px 4px;font-size:12.5px}
  .project-item{padding:13px 13px}
  .lt-item{padding:9px 8px;column-gap:8px}
  .lt-tools .lt-opacity{width:64px;height:18px}
  .lt-tools .lt-sty,.lt-tools .lt-tbl,.lt-tools .lt-ren,.lt-tools .lt-del{width:30px;height:30px}
  .lt-item input[type=checkbox]{width:18px;height:18px}
  .chip{padding:7px 13px;font-size:12px}
  .btn{padding:9px 15px}
  .btn-sm{padding:8px 12px;font-size:12px}
  .icon-btn{width:36px;height:36px}
  .panel{padding:13px 14px}
  .side-head{padding:14px 14px 12px}

  /* ---------- Banner đồ án + thanh công cụ trên bản đồ ---------- */
  .proj-banner{
    left:62px;right:66px;top:calc(8px + env(safe-area-inset-top));
    max-width:none;padding:6px 11px;
  }
  .pb-name{font-size:12.5px}
  .pb-meta{display:none}

  /* thanh công cụ: góc trên-phải (dưới banner), LUÔN thấy dù bảng dữ liệu mở.
     Thu lại = 1 nút tròn nổi (FAB); mở ra = lưới 2 cột cho gọn chiều cao. */
  #toolbar.toolbar{
    top:calc(8px + env(safe-area-inset-top));bottom:auto;right:10px;left:auto;
    transform:none;
    background:var(--glass);padding:5px;gap:4px;
    max-height:calc(100dvh - 200px);overflow:auto;
  }
  #toolbar .tool-body{display:grid;grid-template-columns:44px 44px;gap:5px;padding:0}
  #toolbar .tool-cluster{display:contents}
  #toolbar .tool{width:44px;height:44px;border-radius:12px}
  #toolbar .tool .ic{width:22px;height:22px}
  #toolbar .tool-sep{grid-column:1 / -1;height:1px;width:auto;margin:3px 2px;background:var(--line-soft)}
  #toolbar .tool-toggle{width:auto;height:40px;border-radius:10px;background:var(--surface)}
  #toolbar.toolbar.collapsed{background:transparent;box-shadow:none;border:0;padding:0;overflow:visible}
  #toolbar.toolbar.collapsed .tool-toggle{
    width:48px;height:48px;border-radius:50%;
    background:var(--panel);box-shadow:var(--shadow-2);
  }
  #toolbar.toolbar.collapsed .tool-toggle .ic{width:24px;height:24px}

  /* ---------- Góc dưới-trái: nút bản đồ nền + widget toạ độ/zoom ---------- */
  /* Bản đồ nền: SÁT góc dưới-trái */
  .basemap-ctrl{
    left:10px;bottom:calc(10px + env(safe-area-inset-bottom));
    width:44px;height:44px;
  }
  .basemap-ctrl .ic{width:22px;height:22px}

  /* Widget "toạ độ + zoom": 1 nút thu/mở, đặt cạnh nút bản đồ nền */
  #mapctl{
    display:flex;flex-direction:column-reverse;align-items:flex-start;gap:6px;
    position:absolute;left:64px;bottom:calc(10px + env(safe-area-inset-bottom));
    right:12px;z-index:4;pointer-events:none;
  }
  #mapctl>*{pointer-events:auto}
  .mapctl-toggle{
    display:inline-flex;align-items:center;gap:6px;height:44px;padding:0 12px;
    border:1px solid var(--line-soft);border-radius:999px;
    background:var(--glass);box-shadow:var(--shadow-1);backdrop-filter:blur(8px);
    color:var(--ink-soft);font-weight:700;font-size:12px;
  }
  .mapctl-toggle .ic{width:17px;height:17px}
  /* THU: chỉ hiện nút; ẩn toạ độ + zoom rời */
  #mapctl .coord-readout,#mapctl .zoom-readout,#mapctl .scalebar{display:none}
  /* MỞ: hiện thẻ toạ độ (xuống dòng, đọc đủ) */
  #mapctl.open .coord-readout{
    display:block;position:static;left:auto;right:auto;bottom:auto;
    max-width:calc(100vw - 88px);white-space:normal;line-height:1.55;
    font-size:11.5px;padding:8px 11px;
  }
  #mapctl.open .mapctl-toggle{background:var(--brand-weak);color:var(--brand-ink)}

  .scalebar{display:none}   /* thước tỉ lệ: thừa trên điện thoại (đã có mức zoom) */
  .maplibregl-ctrl-bottom-right{margin-bottom:env(safe-area-inset-bottom)}
  .maplibregl-ctrl-group button{width:42px!important;height:42px!important}

  .measure-readout{bottom:calc(72px + env(safe-area-inset-bottom));font-size:12.5px}

  /* thanh chọn nhiều đối tượng / xem trước nạp: full ngang, cho xuống dòng */
  .sel-bar,#imp-preview-bar,.tbl-sel-bar{
    left:8px;right:8px;transform:none;max-width:none;
    bottom:calc(64px + env(safe-area-inset-bottom));
    flex-wrap:wrap;justify-content:center;row-gap:6px;
  }
  .sel-bar .btn,#imp-preview-bar .btn{padding:6px 12px}

  /* ---------- Modal: gần như toàn màn hình ---------- */
  .modal{padding:0;place-items:stretch}
  .modal-box{
    width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;
    border-radius:0;border:0;display:flex;flex-direction:column;
  }
  .modal-box.wide{width:100vw}
  .modal-head{
    padding:14px 16px;padding-top:calc(14px + env(safe-area-inset-top));
    position:sticky;top:0;background:var(--panel);z-index:2;
  }
  .modal-foot{
    padding:12px 16px;padding-bottom:calc(12px + env(safe-area-inset-bottom));
    position:sticky;bottom:0;background:var(--panel);flex-wrap:wrap;
  }
  .modal-foot .btn{flex:1 1 auto;justify-content:center}
  .form,.info-body{padding:14px 16px}
  .grid2,.grid3{grid-template-columns:1fr}

  /* ---------- Cổng đăng nhập ---------- */
  .login-gate{padding:16px;align-items:flex-start}
  .lg-card{width:100%;max-width:none;margin-top:7vh;padding:26px 22px 20px;border-radius:18px}

  /* ---------- Màn hình "chưa chọn đồ án" ---------- */
  .empty-state{padding:0 14px}
  .es-card{padding:24px 22px;margin-right:56px}   /* chừa chỗ cho thanh công cụ bên phải */
  .es-card h2{font-size:16px}

  /* ---------- Bảng dữ liệu = "bottom sheet" nổi trên bản đồ ---------- */
  /* KHÔNG ép nhỏ bản đồ: dock ra khỏi luồng, trượt lên phủ nửa dưới. */
  #table-dock{
    position:fixed;left:0;right:0;bottom:0;z-index:23;
    border-radius:18px 18px 0 0;
    box-shadow:0 -10px 30px rgba(0,0,0,.24);
    max-height:92dvh;
    transition:transform .26s cubic-bezier(.4,0,.2,1);
    padding-bottom:env(safe-area-inset-bottom);
  }
  #main-col[data-dock="closed"] #table-dock{transform:translateY(101%)}
  #main-col[data-dock="half"]   #table-dock,
  #main-col[data-dock="custom"] #table-dock{height:min(var(--dock-h,54vh),90dvh);transform:none}
  #main-col[data-dock="full"]   #table-dock{height:90dvh;flex:none;transform:none}
  #main-col[data-dock="full"]   #map-wrap{display:block}   /* bản đồ vẫn là nền */

  /* tay kéo to, dễ chạm */
  .dock-drag{top:0;height:24px;z-index:3}
  .dock-drag::before{width:46px;height:5px;top:8px;margin-left:-23px;background:#c4c7c5;border-radius:999px}

  .dock-bar{flex-wrap:wrap;gap:7px;padding:18px 12px 9px;align-items:center}
  .dock-title{font-size:13px;flex:1 1 auto;order:1;white-space:nowrap;overflow:hidden;
    text-overflow:ellipsis;max-width:calc(100% - 140px)}
  .dock-bar #tbl-search{flex:1 1 100%;order:2;font-size:16px}
  .dock-bar #tbl-count{order:3}
  .dock-bar #tbl-prev,.dock-bar #tbl-next,.dock-bar #tbl-reload,
  .dock-bar #tbl-size,.dock-bar #tbl-cols-btn,
  .dock-bar #tbl-export,.dock-bar #tbl-import-btn{order:4;min-height:36px}
  /* nút có chữ -> chỉ còn icon cho gọn (svg giữ kích thước px) */
  .dock-bar #tbl-cols-btn,.dock-bar #tbl-export,.dock-bar #tbl-import-btn{
    font-size:0;padding:8px;width:38px;justify-content:center;
  }
  .tbl-spacer{display:none}
  /* GIỮ đủ 3 nút: Nửa · Toàn · Đóng — ghim góc trên-phải của sheet */
  .dock-modes{position:absolute;top:11px;right:10px;order:0;gap:4px;z-index:4;display:flex}
  .dock-modes button{width:38px;height:38px;border-radius:10px;background:var(--surface)}
  .dock-modes button .ic{width:19px;height:19px}
  #main-col[data-dock="full"] .dock-modes [data-mode="full"],
  #main-col[data-dock="half"] .dock-modes [data-mode="half"],
  #main-col[data-dock="custom"] .dock-modes [data-mode="half"]{
    background:var(--brand);color:#fff}

  .tbl-import{gap:6px 8px}
  .tbl-grid{-webkit-overflow-scrolling:touch}
  table.grid th,table.grid td{padding:7px 9px;font-size:12px;max-width:60vw}

  /* ---------- Trình sửa ký hiệu / nạp dữ liệu: bảng cuộn ngang ---------- */
  table.imp-tbl select{max-width:56vw}
  .sty-row>label{flex-basis:44%}
  .sty-cats,.sty-body{max-height:none}

  /* ---------- Khu tài khoản: nút chạm to hơn một chút ---------- */
  .acct{width:34px;height:34px;flex:0 0 34px;padding:0}
  .acct .acct-av{width:34px;height:34px}
  .acct .acct-av .ic{width:18px;height:18px}
  .acct-item{padding:11px 12px;font-size:13px}
  .acct-btn{width:32px;height:32px}

  /* ---------- Việt hoá tên trường: xếp dọc ---------- */
  .fl-row{grid-template-columns:1fr;gap:4px;padding:8px}
  .fl-list{max-height:none;flex:1 1 auto}
  .fl-tools #fl-add-name,.fl-tools #fl-search{flex:1 1 100%}
  .fl-tools .btn-sm{flex:1 1 auto;justify-content:center}

  /* ---------- Vẽ / nhập toạ độ: hợp điện thoại ---------- */
  #modal-draw .grid3{grid-template-columns:1fr}
  #modal-draw .form{gap:12px}
  #modal-draw textarea{min-height:34vh;font-size:15px;line-height:1.6}
  #modal-draw .form-row[style*="row"]{flex-direction:column!important;align-items:stretch!important}
  #modal-draw .form-row[style*="row"] .btn{width:100%;justify-content:center}
  #modal-draw #draw-count{text-align:center}
  #modal-draw .draw-list{max-height:26vh}
  /* chân trang xuất: nhãn 1 dòng, các nút lưới 2 cột */
  #modal-draw .modal-foot{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:12px}
  #modal-draw .modal-foot>span{grid-column:1 / -1;text-align:center;margin:0}
  #modal-draw .modal-foot .btn{width:100%;justify-content:center}
  #modal-draw #draw-done{grid-column:1 / -1}

  /* ---------- iOS: KHÔNG tự phóng khi focus (font input phải ≥ 16px) ---------- */
  input,select,textarea,
  .form input,.form select,.form textarea,
  #project-search,#tbl-search,.dock-bar #tbl-search,
  .lg-field input,.mini-select,.filters select,
  .users-tbl select,.doc-add input,.doc-add select,
  table.imp-tbl select,#imp-crs,.cell-inp{font-size:16px}
}

/* Thiết bị cảm ứng nói chung (kể cả máy tính bảng): nút bản đồ to hơn */
@media (hover:none) and (pointer:coarse){
  .maplibregl-ctrl-group button{width:40px!important;height:40px!important}
  .tool{min-width:40px;min-height:40px}
  .lt-tbl,.lt-sty{width:32px;height:32px}
}

/* Điện thoại nằm ngang, màn rất thấp: thu gọn thêm */
@media (max-width:900px) and (max-height:460px){
  #toolbar.toolbar{top:8px;transform:none}
  .basemap-ctrl{bottom:calc(60px + env(safe-area-inset-bottom))}
  .proj-banner{display:none}
}
.draw-row .chip.del:hover{background:var(--danger-weak,#fce8e6);color:var(--danger)}

/* ============================================================
   v134 — TINH CHỈNH HIỆN ĐẠI  (nâng cấp tiến bộ, tự thoái lui an toàn)
   ============================================================ */

/* --- Cuộn: mượt, không "kéo lây" ra trang, không nhảy khi hiện thanh cuộn --- */
html{scroll-behavior:smooth}
.spane,.side-panes,.tbl-grid,.modal-box,.users-list,.sty-body,.info-body,
.imp-layers,.draw-list,.fl-list,.cp-list,.colpanel,#cov-body,.bm-popup{
  overscroll-behavior:contain;
  scrollbar-gutter:stable;
}

/* --- Hiệu năng: chỉ dựng phần đang thấy của danh sách dài --- */
.project-item{content-visibility:auto;contain-intrinsic-size:auto 104px}
.fl-row{content-visibility:auto;contain-intrinsic-size:auto 46px}
/* cô lập reflow của từng dòng lặp -> lướt danh sách dài không giật */
.project-item,.lt-item,.doc-item,.fl-row,.cov-xrow{contain:layout style}

/* --- Chữ: ngắt dòng đẹp hơn (Baseline 2024, trình cũ bỏ qua) --- */
p,li,.lt-name,.pi-name,.pi-sub,.sp-name,.es-card p,.note p,.standfirst{text-wrap:pretty}
h1,h2,h3,.modal-head h3,.brand-title,.lg-card h2{text-wrap:balance}

/* --- Con trỏ nhập & bôi chọn theo màu nhấn --- */
:root{caret-color:var(--brand)}
::selection{background:var(--brand-a12)}

/* --- Tiêu đề panel dính khi cuộn (giữ ngữ cảnh) --- */
.spane .panel-head{
  position:sticky;top:0;z-index:4;
  background:var(--panel);
  margin:-14px -16px 10px;padding:14px 16px 8px;
  border-bottom:1px solid var(--line-soft);
}
#panel-context .panel-head,#panel-legend .panel-head{border-bottom:0}

/* Panel Lớp không còn hàng tiêu đề riêng -> cây lớp bắt đầu ngay từ trên */
#panel-layers{padding-top:9px}

/* Panel Thông tin: bỏ tiêu đề thừa "Thông tin đồ án"; nút × gọn ở góc phải trên.
   Khi xem 1 đối tượng -> vẫn hiện tên đối tượng làm tiêu đề (nhỏ, chữ thường). */
#panel-context{padding-top:10px;position:relative}
#ctx-title{
  font-size:12.5px;font-weight:600;letter-spacing:0;line-height:1.35;
  color:var(--ink);text-transform:none;word-break:break-word;
}
#ctx-title:empty{display:none}
#panel-context .panel-head{
  margin:-10px -16px 8px;padding:8px 12px 6px;gap:8px;
}
#panel-context .panel-head #ctx-close{flex:0 0 auto;width:28px;height:28px}
/* Không có tiêu đề (xem thông tin đồ án) -> × nổi ở góc phải trên, không chiếm hàng */
#panel-context.ctx-notitle .panel-head{
  position:absolute;top:6px;right:6px;left:auto;z-index:6;
  margin:0;padding:0;background:none;border:0;min-height:0;
}
#panel-context.ctx-notitle .ctx-body{padding-top:2px}
@media (pointer:coarse){#panel-context .panel-head #ctx-close{width:34px;height:34px}}

/* Hàng thao tác đồ án = nút ICON gọn (bỏ nút chữ dài + đoạn mô tả) */
.ctx-actions{display:flex;flex-wrap:wrap;gap:5px;margin:0 34px 12px 0}
.ctx-act{
  width:32px;height:32px;flex:0 0 32px;
  border:1px solid var(--line);border-radius:9px;background:var(--panel);color:var(--ink-soft);
  display:grid;place-items:center;cursor:pointer;
  transition:background .12s,border-color .12s,color .12s;
}
.ctx-act .ic{width:16px;height:16px}
.ctx-act:hover{background:var(--surface);color:var(--ink);border-color:#c0c4c9}
.ctx-act:focus-visible{outline:none;box-shadow:var(--ring)}
.ctx-act-pri{background:var(--brand);border-color:var(--brand);color:#fff}
.ctx-act-pri:hover{background:var(--brand-ink);border-color:var(--brand-ink);color:#fff}
.ctx-act-del:hover{background:var(--danger-weak,#fce8e6);border-color:#f2b8b5;color:var(--danger)}
@media (pointer:coarse){.ctx-act{width:38px;height:38px;flex-basis:38px}}

/* bảng thông tin: cột nhãn cố định, không bẻ chữ theo từng từ */
.ctx-body table.kv td{font-size:12px;line-height:1.4}
.ctx-body table.kv td:first-child{color:var(--ink-faint);font-size:11.5px}

/* --- Phản hồi khi bấm: nhấn nhẹ (transform, chạy trên compositor) --- */
@media (prefers-reduced-motion:no-preference){
  .btn,.chip,.tool,.icon-btn,.acct-btn,.lt-tbl,.lt-sty,.lt-ren,.lt-del,
  .dock-modes button,.basemap-ctrl,.mapctl-toggle,.bm-opt{
    transition:transform .09s ease, background .13s ease, color .13s ease,
               border-color .13s ease, box-shadow .16s ease, opacity .12s ease;
  }
  .btn:active,.chip:active,.tool:active,.icon-btn:active,.acct-btn:active,
  .dock-modes button:active,.bm-opt:active{transform:scale(.965)}
  .project-item:active{transform:scale(.995)}

  /* --- Xuất hiện có chủ đích: modal, toast, bảng thông tin --- */
  .modal:not([hidden]) .modal-box{animation:mIn .22s cubic-bezier(.2,.7,.3,1)}
  .toast:not([hidden]){animation:tIn .26s cubic-bezier(.2,.7,.3,1)}
  #panel-context:not([hidden]) .ctx-body{animation:cIn .2s ease}
}
@keyframes mIn{from{opacity:0;transform:translateY(8px) scale(.985)}to{opacity:1;transform:none}}
@keyframes tIn{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}
@keyframes cIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* --- Cụm điều khiển bản đồ: nền kính thống nhất --- */
.toolbar,.basemap-ctrl,.mapctl-toggle,.maplibregl-ctrl-group{
  backdrop-filter:saturate(1.35) blur(10px);
  -webkit-backdrop-filter:saturate(1.35) blur(10px);
}
@media (prefers-reduced-motion:no-preference){
  .tool:hover,.basemap-ctrl:hover,.mapctl-toggle:hover{box-shadow:var(--shadow-2)}
}

/* --- Màu suy ra từ --brand (color-mix, có giá trị dự phòng phía trên) --- */
@supports (background:color-mix(in srgb,red,blue)){
  .btn:hover{border-color:color-mix(in srgb,var(--brand) 45%,var(--line))}
  .project-item:hover{border-color:color-mix(in srgb,var(--brand) 25%,transparent)}
  .chip:hover{background:color-mix(in srgb,var(--brand) 8%,var(--panel))}
}

/* --- :has() — phản hồi trạng thái thông minh (trình cũ bỏ qua) --- */
@supports selector(:has(*)){
  .form-row:has(input:user-invalid) > label{color:var(--danger)}
  .form-row:has(input:user-invalid) input{border-color:var(--danger)}
  .lt-item:has(> input:checked) .lt-name{color:var(--brand-ink);font-weight:600}
  .lt-group:has(.lt-item > input:checked) > summary{color:var(--brand-ink)}
}

/* --- Ảnh trong popup / tài liệu: hiện dần mượt --- */
img{background:var(--surface)}

/* ============ Thanh vẽ nổi (điểm / đường / vùng + nhãn) ============ */
.draw-bar{position:absolute;left:50%;bottom:18px;transform:translateX(-50%);z-index:31;
  display:flex;flex-direction:column;gap:4px;padding:6px 8px;border-radius:14px;
  background:var(--glass);box-shadow:var(--shadow-3);backdrop-filter:blur(8px);
  max-width:calc(100% - 24px)}
.draw-bar[hidden]{display:none}
.db-row{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.db-btn{display:inline-flex;align-items:center;gap:5px;border:1px solid transparent;background:none;
  border-radius:9px;padding:6px 10px;font:inherit;font-size:12.5px;font-weight:600;color:var(--ink-soft);
  cursor:pointer;white-space:nowrap}
.db-btn:hover{background:var(--surface);color:var(--ink)}
.db-btn.active{background:#ffedd5;color:#9a3412;border-color:#fdba74}
.db-btn:disabled{opacity:.45;cursor:default}
.db-ok{background:#ea580c;color:#fff}
.db-ok:hover{background:#c2410c;color:#fff}
.db-x{padding:6px 7px;margin-left:2px}
.db-sep{width:1px;align-self:stretch;background:var(--line-soft);margin:2px 4px}
.db-chk{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;font-weight:600;color:var(--ink-soft);
  padding:0 6px;cursor:pointer;user-select:none}
.db-chk input{accent-color:#ea580c;margin:0}
.db-foot{display:flex;gap:10px;align-items:center;justify-content:space-between;padding:0 4px;font-size:11.5px;min-height:0}
.db-foot:has(.db-hint[hidden]):has(.db-status:empty){display:none}
.db-hint{color:#9a3412}
.db-status{color:var(--ink-faint);margin-left:auto}
.db-status.ok{color:var(--ok)} .db-status.warn{color:var(--warn)} .db-status.err{color:var(--danger)}

/* popup nhãn của hình vẽ */
.draw-popup .maplibregl-popup-content{padding:10px 12px;border-radius:12px;box-shadow:var(--shadow-2)}
.draw-pop{display:flex;flex-direction:column;gap:8px;min-width:230px;font-size:12.5px}
.dp-head{display:flex;align-items:center;gap:8px;padding-right:14px}
.dp-meta{color:var(--ink-soft);font-size:11.5px;line-height:1.35}
.dp-lbl{display:flex;flex-direction:column;gap:4px;font-weight:600;color:var(--ink-soft);font-size:11.5px}
.dp-lbl input{font:inherit;font-size:13px;font-weight:500;color:var(--ink);padding:6px 9px;
  border:1px solid var(--line);border-radius:8px}
.dp-lbl input:focus{outline:none;border-color:#ea580c;box-shadow:0 0 0 3px rgba(234,88,12,.18)}
.dp-btns{display:flex;gap:6px;justify-content:flex-end}
.dp-btns .chip.del{color:var(--danger);border-color:#f2b8b5;margin-right:auto}
.dp-btns .dp-ok{background:#ea580c;border-color:#ea580c;color:#fff}

/* ô sửa nhãn trong danh sách hình vẽ */
.draw-lbl-in{flex:1 1 140px;min-width:0;font:inherit;font-size:12.5px;padding:4px 8px;
  border:1px solid var(--line-soft);border-radius:7px;background:var(--panel)}
.draw-lbl-in:focus{outline:none;border-color:var(--brand)}
.draw-row .draw-meta{flex:0 0 auto}

@media (max-width:768px){
  .draw-bar{left:10px;right:10px;transform:none;bottom:calc(64px + env(safe-area-inset-bottom));max-width:none}
  .db-btn{padding:8px 10px}
}

/* ============ Tài liệu / bản vẽ / ảnh của đồ án (docs.js) ============ */
.dm{display:flex;flex-direction:column;gap:8px}
.dm-head{display:flex;align-items:center;gap:8px;justify-content:space-between;flex-wrap:wrap}
.dm-head b{font-size:13px}
.dm-count{color:var(--ink-faint);font-weight:500}
.dm-q{flex:0 1 220px;min-width:0;font:inherit;font-size:12.5px;padding:5px 9px;border:1px solid var(--line);border-radius:8px}
.dm-add{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px dashed var(--line);border-radius:10px;background:var(--surface)}
.dm-drop{display:flex;flex-direction:column;gap:2px;align-items:center;text-align:center;padding:12px 10px;
  border-radius:8px;cursor:pointer;font-size:12.5px;color:var(--ink-soft);background:var(--panel);border:1px solid var(--line-soft)}
.dm-drop:hover,.dm-drop:focus,.dm-drop.drag{border-color:var(--brand);background:var(--brand-weak);outline:none}
.dm-hint{font-size:11px;color:var(--ink-faint);line-height:1.4}
/* bộ chọn tài liệu chưa gửi (docPicker): mỗi file 1 dòng - loại + ghi chú riêng */
.dpk{display:flex;flex-direction:column;gap:6px}
.dpk-list{display:flex;flex-direction:column;gap:5px}
.dpk-list:empty{display:none}
.dpk-sum{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ink-soft);font-weight:600}
.dpk-clear{margin-left:auto;border:0;background:none;color:var(--danger);font:inherit;font-size:11.5px;cursor:pointer}
.dpk-row{display:grid;grid-template-columns:34px minmax(0,1.3fr) minmax(0,1.2fr) minmax(0,1fr) 26px;gap:7px;
  align-items:center;padding:5px 6px;background:var(--panel);border:1px solid var(--line-soft);border-radius:9px}
.dpk-main{display:flex;flex-direction:column;min-width:0}
.dpk-name{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dpk-type,.dpk-note{min-width:0;font:inherit;font-size:12px;padding:5px 7px;border:1px solid var(--line);border-radius:7px;background:var(--panel)}
.dpk-x{border:0;background:none;color:var(--ink-faint);font-size:17px;line-height:1;cursor:pointer;border-radius:6px;padding:2px}
.dpk-x:hover{color:var(--danger);background:var(--danger-weak,#fce8e6)}
@media (max-width:768px){
  .dpk-row{grid-template-columns:34px minmax(0,1fr) 26px}
  .dpk-type,.dpk-note{grid-column:2 / 3}
}
.dm-row{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.dm-send-row{justify-content:flex-end}
.dm-row select,.dm-row input:not([type=file]){flex:1 1 160px;min-width:0;font:inherit;font-size:12.5px;padding:6px 8px;
  border:1px solid var(--line);border-radius:8px;background:var(--panel)}
.dm-prog .progress-bar{height:6px;border-radius:999px;background:var(--line-soft);overflow:hidden}
.dm-prog .progress-bar span{display:block;height:100%;width:0;background:var(--brand);transition:width .2s}
.dm-prog-t{font-size:11.5px;color:var(--ink-soft);margin-top:3px}
.dm-list{display:flex;flex-direction:column;gap:10px}
.dm-empty{padding:4px 2px}
.dm-grp-h{font-size:11px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;color:var(--ink-faint);margin:0 2px 4px}
.dm-grp-h span{font-weight:500}
.dm-item{display:flex;align-items:center;gap:9px;padding:7px 8px;border:1px solid var(--line-soft);border-radius:10px;background:var(--panel)}
.dm-item + .dm-item{margin-top:5px}
.dm-ic{flex:0 0 auto;width:34px;height:34px;border-radius:8px;display:grid;place-items:center;font-size:10px;font-weight:800;
  letter-spacing:.02em;color:var(--c);background:color-mix(in srgb,var(--c) 12%,#fff);border:1px solid color-mix(in srgb,var(--c) 30%,#fff)}
.dm-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:1px}
.dm-name{font-size:12.8px;font-weight:600;color:var(--ink);text-decoration:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dm-name:hover{color:var(--brand);text-decoration:underline}
.dm-note{font-size:11.5px;color:var(--ink-soft)}
.dm-meta{font-size:11px;color:var(--ink-faint)}
.dm-s3{color:var(--warn-ink,#b45309);font-weight:600}
.dm-act{flex:0 0 auto;display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}
.dm-act .chip{padding:3px 9px;font-size:11.5px}
.dm-act .chip.del{color:var(--danger);border-color:#f2b8b5}
.dm-edit{flex:1;display:flex;gap:6px;flex-wrap:wrap}
.dm-edit input,.dm-edit select{flex:1 1 150px;min-width:0;font:inherit;font-size:12.5px;padding:5px 8px;border:1px solid var(--line);border-radius:7px}
.dm-e-btns{display:flex;gap:5px}
.dm-ok{background:var(--brand);border-color:var(--brand);color:#fff}
/* ảnh nền (ortho) trong form sửa */
.om{display:flex;flex-direction:column;gap:7px;font-size:12.5px}
.om-ok{color:var(--ok);font-weight:600}
.om-run{color:var(--warn);font-weight:600}
.om-err{color:var(--danger);margin-top:4px}
.om-row input[type=file]{flex:1 1 220px;min-width:0;font-size:12px}
.om-list,.om-jobs{display:flex;flex-direction:column;gap:5px}
.om-jobs:empty{display:none}
.om-add-h{font-size:12.5px}
.om-rep{margin:-2px 0 4px 43px;padding:8px;border:1px dashed var(--line);border-radius:10px;background:var(--surface);
  display:flex;flex-direction:column;gap:6px}
.om-act .chip[disabled],.dm-act .chip[disabled]{opacity:.4;cursor:default}
/* bộ chọn ảnh bay nhiều lớp (orthoPicker) */
.opk{display:flex;flex-direction:column;gap:6px}
.opk-mode{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center;font-size:12.5px}
.opk-mode label{display:inline-flex;align-items:center;gap:5px;cursor:pointer;font-weight:600;width:auto;margin:0}
.opk input[type=radio],.opk input[type=checkbox]{width:auto;margin:0;flex:0 0 auto}
.opk-mode .dm-hint{flex-basis:100%}
.opk-list{display:flex;flex-direction:column;gap:5px}
.opk-list:empty{display:none}
.opk-row{display:grid;grid-template-columns:30px 34px minmax(0,1.4fr) minmax(0,1.2fr) 132px 26px;gap:7px;
  align-items:center;padding:5px 6px;background:var(--panel);border:1px solid var(--line-soft);border-radius:9px}
.opk-row.opk-joined{margin-top:-6px;border-top-left-radius:0;border-top-right-radius:0;border-top-style:dashed;
  background:color-mix(in srgb,#0891b2 4%,#fff)}
.opk-badge{font-size:11px;font-weight:800;color:#0891b2;text-align:center}
.opk-joined .opk-badge{opacity:.45}
.opk-name{min-width:0;font:inherit;font-size:12px;padding:5px 7px;border:1px solid var(--line);border-radius:7px;background:var(--panel)}
.opk-jtxt{font-size:11.5px;color:var(--ink-faint);font-style:italic}
.opk-join{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--ink-soft);white-space:nowrap;cursor:pointer;
  width:auto;margin:0;font-weight:500}
.opk-warn{color:var(--danger)}
.opk-orph{font-size:11.5px;color:var(--warn)}
@media (max-width:768px){
  .opk-row{grid-template-columns:30px minmax(0,1fr) 26px}
  .opk-row .dm-ic{display:none}
  .opk-row .opk-name,.opk-row .opk-jtxt,.opk-row .opk-join{grid-column:2 / 3}
}
@media (max-width:768px){
  .dm-item{flex-wrap:wrap}
  .dm-act{width:100%;justify-content:flex-start;padding-left:43px}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}

/* ============ Công khai đồ án (publish) + trang chính công khai ============ */
.brand-pub{font-size:11px;line-height:1.2;color:var(--ok);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pi-badge.pub{background:var(--ok-weak,#dcfce7);color:var(--ok-ink,#166534);border-color:#86efac}
.ctx-act.is-on{background:var(--ok-weak,#dcfce7);border-color:#22c55e;color:var(--ok-ink,#166534)}
.lg-back{width:100%;justify-content:center;margin-top:8px;padding:10px;border-radius:11px}
/* khách chỉ xem: ẩn các nút tạo / nạp dữ liệu */
body.public-mode #btn-add,body.public-mode #es-add{display:none}
.es-pub{display:none}
body.public-mode .es-pub{display:block}
body.public-mode .es-int{display:none}
/* công khai tài liệu */
.dm-ncbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 8px;border-radius:9px;background:#eff6ff;border:1px solid #bfdbfe}
.dm-ncbar .chip{padding:3px 10px;font-size:12px;font-weight:600}
.dm-ncbar .dm-hint{font-size:11px;flex:1;min-width:140px}
.dm-qrthumb{width:56px;height:56px;cursor:zoom-in;border:1px solid #bfdbfe;border-radius:6px;background:#fff;padding:2px;order:9}
.dm-qrthumb svg{width:100%;height:100%;display:block}
.dm-pubbar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:12px;padding:6px 8px;border-radius:9px;background:var(--ok-weak,#f0fdf4);border:1px solid #bbf7d0}
.dm-pubinfo{flex:1 1 200px;color:var(--ink-soft)}
.dm-pubbar .chip{padding:3px 9px;font-size:11.5px}
.dm-pub{color:var(--ok-ink,#166534);font-weight:700}
.dm-act .chip.dm-pub-on{background:var(--ok-weak,#dcfce7);border-color:#22c55e;color:var(--ok-ink,#166534)}
/* HIỆU NĂNG: bỏ làm mờ nền (backdrop-filter) trên các nút/nhãn nổi trên bản đồ — trình duyệt
   phải làm mờ lại vùng đó MỖI KHUNG HÌNH khi kéo/zoom; nền đã gần đục (.94–.97) nên gần như không khác. */
*:not(.modal){backdrop-filter:none!important;-webkit-backdrop-filter:none!important}
/* ============ Nguồn dữ liệu ngoài (extsrc.js) ============ */
.tool.has-on{color:var(--brand);background:var(--brand-weak)}
.ext-panel{position:absolute;top:12px;right:64px;z-index:30;width:min(420px,calc(100vw - 96px));max-height:calc(100% - 90px);
  display:flex;flex-direction:column;gap:6px;padding:10px 12px;background:var(--panel);border:1px solid var(--line-soft);
  border-radius:14px;box-shadow:var(--shadow-3);font-size:12.5px}
.ext-panel[hidden]{display:none}
.ext-head{display:flex;align-items:center;gap:6px}
.ext-head b{flex:1;font-size:13.5px}
.ext-hint{font-size:11px;line-height:1.35}
.ext-list{overflow:auto;display:flex;flex-direction:column;gap:8px;min-height:40px}
.ext-empty{padding:10px 2px}
.ext-grp{display:flex;flex-direction:column;gap:4px}
.ext-row{display:grid;grid-template-columns:18px minmax(0,1fr) 70px auto;gap:6px;align-items:center;padding:5px 6px;
  border:1px solid var(--line-soft);border-radius:9px}
.ext-row.is-err{background:#fff5f5;border-color:#f2b8b5}
.ext-cb{margin:0}
.ext-main{display:flex;flex-direction:column;min-width:0}
.ext-name{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ext-meta{font-size:11px;color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ext-pub{color:var(--ok-ink,#166534)}.ext-errt{color:var(--danger)}
.ext-op{width:70px}
.ext-act{display:flex;gap:3px}
.ext-act .chip{padding:2px 7px;font-size:11px}
.ext-act .chip.del{color:var(--danger);border-color:#f2b8b5}
.ext-url-line{display:flex;gap:6px}
.ext-url-line input{flex:1;min-width:0}
.ext-probe-msg{font-size:11.5px;margin-top:4px;line-height:1.45}
.ext-checks{display:flex;flex-direction:column;gap:4px;justify-content:flex-end}
.ext-checks label,.ext-chk label{display:flex;align-items:center;gap:6px;font-weight:500}
.ext-checks input,.ext-chk input{width:auto;margin:0}
.ext-3dnote{grid-column:1 / -1;font-size:11.5px}
.ext-adv{margin:4px 0 8px}
.ext-adv summary{cursor:pointer;font-weight:600;font-size:12.5px;margin-bottom:6px}
.ext-pop .maplibregl-popup-content{padding:8px 10px;border-radius:10px;max-height:320px;overflow:auto;font-size:12px}
.ext-pop-h{font-weight:700;margin:0 16px 6px 0}
.ext-pop .kv td{padding:2px 6px;border-bottom:1px solid var(--line-soft);vertical-align:top}
.ext-pop .kv td:first-child{color:var(--ink-soft);white-space:nowrap}
#cesium-box{position:absolute;inset:0;z-index:40;background:#000}
#cesium-box[hidden]{display:none}
#cesium-view{position:absolute;inset:0}
#cesium-box .cz-top{position:absolute;top:12px;left:12px;z-index:6;display:flex;gap:8px}
#cesium-box .cz-open-ifc{font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,.35)}
#cesium-box .cz-note{position:absolute;bottom:34px;left:12px;z-index:2;background:rgba(15,23,42,.8);color:#fff;
  font-size:11.5px;padding:5px 9px;border-radius:8px}
@media (max-width:768px){
  .ext-panel{right:8px;left:8px;width:auto;top:60px}
  .ext-row{grid-template-columns:18px minmax(0,1fr) auto}
  .ext-op{grid-column:2 / 3;width:100%}
}
/* ============ QLDA-QN BIM (qlda.js) ============ */
.qd{display:flex;flex-direction:column;gap:7px;font-size:12.5px}
.qd h4{margin:10px 0 2px;font-size:12.5px;text-transform:uppercase;letter-spacing:.02em;color:var(--ink-soft)}
.qd-h{display:flex;align-items:flex-start;gap:8px;justify-content:space-between}
.qd-h b{font-size:14px;line-height:1.3}
.qd-st{flex:0 0 auto;font-size:11px;font-weight:700;color:var(--c);background:color-mix(in srgb,var(--c) 12%,#fff);
  border:1px solid color-mix(in srgb,var(--c) 35%,#fff);border-radius:999px;padding:1px 8px;white-space:nowrap}
.qd-mut{font-size:11.5px;color:var(--ink-faint)}
.qd-note{background:var(--warn-weak,#fffbeb);border:1px solid #fde68a;border-radius:8px;padding:6px 8px}
.qd-desc{color:var(--ink-soft);line-height:1.45}
.qd-acts{display:flex;gap:6px;flex-wrap:wrap}
.qd-q{font:inherit;padding:6px 9px;border:1px solid var(--line);border-radius:8px}
.qd-plist{display:flex;flex-direction:column;gap:4px}
.qd-prow{display:flex;align-items:center;gap:7px;padding:6px 7px;border:1px solid var(--line-soft);border-radius:9px}
.qd-prow[hidden]{display:none}
.qd-dot{flex:0 0 10px;height:10px;border-radius:50%;background:var(--c)}
.qd-pm{flex:1;min-width:0;display:flex;flex-direction:column}
.qd-pm span{font-size:11px;color:var(--ink-faint)}
.qd-sub{font-size:11.5px;color:var(--ink-soft)}
.qd-bcf{display:flex;gap:8px;padding:6px;border:1px solid var(--line-soft);border-radius:9px}
.qd-bcf.is-focus{border-color:var(--brand);box-shadow:0 0 0 2px var(--brand-weak)}
.qd-snap{flex:0 0 86px;height:64px;border-radius:7px;background:#e5e7eb center/cover no-repeat;cursor:zoom-in}
.qd-nosnap{display:grid;place-items:center;font-size:11px;font-weight:700;color:var(--ink-soft,#6b7280);cursor:default}
.qd-bm{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;align-items:flex-start}
.qd-bm span{font-size:11.5px;color:var(--ink-soft)}
.qd-bm .chip{padding:2px 8px;font-size:11px;margin-top:3px}
.qd-mdl{display:flex;flex-wrap:wrap;align-items:center;gap:5px;padding:6px;border:1px solid var(--line-soft);border-radius:9px}
.qd-mdl b{flex:1 1 100%}
.qd-mdl .chip{padding:2px 8px;font-size:11px}
.qd-mdl .chip.del{color:var(--danger);border-color:#f2b8b5}
.qd-add{border:1px dashed var(--line);border-radius:9px;padding:6px 8px}
.qd-add summary{cursor:pointer;font-weight:600}
.qd-add input{font:inherit;font-size:12px;padding:5px 7px;border:1px solid var(--line);border-radius:7px;margin:3px 0;min-width:0;width:100%}
.qd-add .grid2,.qd-add .grid3{gap:5px}
.qd-wp{width:100%;border-collapse:collapse;font-size:11.5px}
.qd-wp th{text-align:left;color:var(--ink-faint);font-weight:600;border-bottom:1px solid var(--line)}
.qd-wp td{padding:4px 3px;border-bottom:1px solid var(--line-soft);vertical-align:top}
.qd-fld{border:1px solid var(--line-soft);border-radius:8px;padding:5px 8px}
.qd-fld summary{cursor:pointer;font-weight:600;font-size:12px;color:var(--ink-soft)}
.qd-fv{white-space:pre-wrap;line-height:1.5;margin-top:4px;font-size:12px}
/* nhập danh mục lớp (GSI Maps) */
.ei{display:flex;flex-direction:column;gap:8px}
.ei-bar{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center}
.ei-bar .ei-q{flex:1 1 240px;min-width:0}
.ei-bar label{display:inline-flex;align-items:center;gap:5px;width:auto;margin:0;font-weight:500}
.ei-bar input[type=checkbox],.ei-tree input{width:auto;margin:0}
.ei-cnt{font-weight:600;color:var(--brand)}
.ei-tree{max-height:52vh;overflow:auto;display:flex;flex-direction:column;gap:8px;border:1px solid var(--line-soft);border-radius:10px;padding:8px}
.ei-grp{display:flex;flex-direction:column;gap:2px}
.ei-gh{display:flex;align-items:center;gap:6px;font-size:12.5px;width:auto;margin:0}
.ei-gh span{color:var(--ink-faint);font-weight:500}
.ei-it{display:flex;align-items:center;gap:6px;padding:2px 0 2px 22px;font-size:12.5px;font-weight:500;width:auto;margin:0;cursor:pointer}
.ei-it.is-off{opacity:.5;cursor:default}
.ei-k{margin-left:auto;font-size:11px;color:var(--ink-faint);white-space:nowrap}
body.has-ext #empty-state{display:none}
/* ============ Bảng nguồn dữ liệu v2: thẻ Đang hiển thị / Danh mục, cây thư mục, kéo thả, di động ============ */
.ext-panel{gap:6px;padding:8px 10px 10px;width:min(440px,calc(100vw - 96px))}
.ext-grab{display:none}
.ext-head{gap:8px}
.ext-head b{flex:0 0 auto}
.ext-sum{flex:1;font-size:11.5px;color:var(--ink-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ext-tools{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.ext-tools .btn{margin-left:auto}
.ext-tabs{display:flex;border-bottom:1px solid var(--line-soft)}
.ext-tabs button{flex:1;border:0;background:none;font:inherit;font-size:12.5px;font-weight:600;color:var(--ink-soft);
  padding:7px 4px;border-bottom:2px solid transparent;cursor:pointer}
.ext-tabs button.is-active{color:var(--brand);border-bottom-color:var(--brand)}
.ext-tabs span{font-weight:500;color:var(--ink-faint);margin-left:3px}
.ext-filter{display:flex;gap:6px}
.ext-filter .ext-q{flex:1;min-width:0;font:inherit;font-size:12.5px;padding:6px 9px;border:1px solid var(--line);border-radius:8px}
.ext-filter .ext-sort{flex:0 0 auto;font:inherit;font-size:12px;padding:5px 6px;border:1px solid var(--line);border-radius:8px;background:var(--panel)}
.ext-filter .ext-sort[hidden]{display:none}
.ext-list{gap:2px;overscroll-behavior:contain;padding-right:2px}
.ext-row{display:flex;align-items:center;gap:6px;padding:5px 6px;border:1px solid transparent;border-radius:8px;min-height:36px}
.ext-row:hover{background:var(--surface,#f8fafc)}
.ext-row.is-on{background:color-mix(in srgb,var(--brand) 5%,#fff);border-color:color-mix(in srgb,var(--brand) 18%,#fff)}
.ext-row.is-err{background:#fff5f5;border-color:#f2b8b5}
.ext-row.is-drag{opacity:.85;box-shadow:var(--shadow-2);background:var(--panel);z-index:2;position:relative}
.ext-row .ext-cb{flex:0 0 auto;margin:0;width:16px;height:16px}
.ext-main{flex:1;min-width:0}
.ext-name{font-size:12.5px}
.ext-meta{font-size:10.5px}
.ext-tag{font-weight:700;color:var(--ink-soft)}
/* chu giai lop (options.legend): hang rieng duoi ten lop; dong KHONG bi co trong danh sach cuon */
.ext-list>.ext-row,.ext-list>.ext-dir,.ext-dbody>.ext-row{flex-shrink:0}
.ext-row{flex-wrap:wrap}
.ext-row>.ext-leg{flex:1 0 100%;margin:1px 0 1px 24px}
.ext-leg{display:flex;flex-wrap:wrap;gap:2px 10px;font-size:10.5px;color:var(--ink-soft);line-height:1.35;min-width:0}
.ext-leg .lg-it{display:inline-flex;align-items:center;gap:4px;min-width:0}
.ext-leg .lg-sw{flex:0 0 auto;display:inline-block;width:14px;height:10px;border:1px solid;border-radius:2px}
.ext-leg .lg-l{height:3px;border:0;border-radius:2px}
.ext-leg .lg-d{height:0;background:none;border:0;border-top:3px dashed;border-radius:0}
.ext-leg .lg-p{width:9px;height:9px;border-radius:50%;border-width:1.5px}
.ext-row .ext-op{flex:0 0 64px;width:64px}
.ext-drag{flex:0 0 auto;cursor:grab;color:var(--ink-faint);font-size:15px;line-height:1;padding:4px 2px;touch-action:none;user-select:none}
.ext-ic{flex:0 0 auto;border:0;background:none;color:var(--ink-soft);font-size:11px;width:24px;height:24px;border-radius:6px;cursor:pointer;padding:0}
.ext-ic:hover{background:var(--line-soft);color:var(--ink)}
.ext-more{font-size:16px;font-weight:700}
.ext-onbar{display:flex;align-items:center;gap:6px;justify-content:space-between;font-size:11px;padding:2px 2px 6px}
.ext-onbar .chip{padding:2px 8px;font-size:11px}
/* cây thư mục */
.ext-dir{display:flex;flex-direction:column}
.ext-dh{display:flex;align-items:center;gap:5px;padding:4px 4px 4px calc(4px + var(--d,0) * 14px);border-radius:7px;min-height:32px}
.ext-dh:hover{background:var(--surface,#f8fafc)}
/* keo tha sap xep (the Dang hien thi: ca dong; Theo thu muc: quan tri) */
.ext-ddrag{flex:0 0 auto;cursor:grab;color:var(--ink-faint);font-size:15px;line-height:1;padding:4px 2px;touch-action:none;user-select:none}
.ext-dh.can-drag,.ext-list .ext-row.is-on{cursor:grab}
.ext-rdir{opacity:0;margin-left:auto}
.ext-dh:hover .ext-rdir,.ext-rdir:focus-visible{opacity:1}
.ext-dir.is-drag>.ext-dh,.ext-row.is-drag{opacity:.45}
.ext-list .drop-before{box-shadow:inset 0 3px 0 var(--brand,#2563eb)}
.ext-list .drop-after{box-shadow:inset 0 -3px 0 var(--brand,#2563eb)}
.ext-list .drop-in{background:rgba(37,99,235,.12)!important;outline:2px dashed var(--brand,#2563eb);outline-offset:-2px}
.ext-ghost{position:fixed;z-index:10000;pointer-events:none;background:var(--brand,#2563eb);color:#fff;font-size:12.5px;font-weight:600;
  padding:5px 10px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.25);max-width:280px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.ext-dragging,body.ext-dragging *{cursor:grabbing!important;user-select:none!important}
.ext-arrbar{font-size:11.5px}
.ext-caret{border:0;background:none;width:18px;height:18px;padding:0;cursor:pointer;color:var(--ink-faint);font-size:11px;transition:transform .15s}
.ext-dir.is-open>.ext-dh .ext-caret{transform:rotate(90deg)}
.ext-dcb{margin:0;width:15px;height:15px;flex:0 0 auto}
.ext-dn{flex:1;min-width:0;font-weight:650;font-size:12.5px;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ext-dc{font-size:11px;color:var(--ink-faint);flex:0 0 auto}
.ext-dbody{display:flex;flex-direction:column;gap:1px;padding-left:calc(10px + var(--d,0) * 14px);border-left:1px dashed var(--line-soft);margin-left:calc(12px + var(--d,0) * 14px)}
.ext-dbody>.ext-dir>.ext-dh{padding-left:4px}
.ext-dbody .ext-dbody{margin-left:12px;padding-left:10px}
/* menu ⋯ */
.ext-menu{position:fixed;z-index:9000;width:220px;background:var(--panel);border:1px solid var(--line-soft);border-radius:12px;
  box-shadow:var(--shadow-3);padding:5px;display:flex;flex-direction:column}
.ext-menu[hidden]{display:none}
.ext-mh{font-size:11.5px;font-weight:700;color:var(--ink-soft);padding:5px 8px 6px;border-bottom:1px solid var(--line-soft);margin-bottom:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ext-menu button{border:0;background:none;text-align:left;font:inherit;font-size:12.5px;padding:8px 9px;border-radius:7px;cursor:pointer}
.ext-menu button:hover{background:var(--brand-weak)}
.ext-menu button.del{color:var(--danger)}
.ext-merr{font-size:11px;color:var(--danger);padding:4px 8px}
/* muc zoom hien thi (ca nhan hoa) */
.ext-mz{border:1px solid var(--line-soft);background:none;border-radius:6px;padding:0 4px;font:inherit;font-size:10.5px;line-height:15px;color:var(--ink-faint);cursor:pointer}
.ext-mz:hover{border-color:var(--brand);color:var(--brand)}
.ext-mz.is-own{border-color:var(--brand);color:var(--brand);font-weight:600}
.ext-mzp{display:flex;flex-direction:column;gap:6px;padding:4px 6px 2px}
.ext-mzh{font-size:12px}
.ext-mzg{display:grid;grid-template-columns:repeat(6,1fr);gap:4px}
.ext-menu .ext-mzg button{padding:5px 0;text-align:center;border:1px solid var(--line-soft);border-radius:6px;font-size:12px}
.ext-menu .ext-mzg button.def{border-style:dashed;border-color:var(--ink-faint)}
.ext-menu .ext-mzg button.on{background:var(--brand);border-color:var(--brand);color:#fff}
.ext-mzn{font-size:10.5px;color:var(--ink-faint);line-height:1.35}
.ext-mzf{font-size:11.5px;display:flex;gap:6px;align-items:flex-start}
.ext-leg .lg-ic{flex:0 0 auto;width:16px;height:16px;object-fit:contain}
/* popup đối tượng */
.ext-pop-t{font-weight:600;margin:-2px 0 6px}
.ext-pop-a{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:6px}
.ext-pop-a .chip{padding:3px 9px;font-size:11.5px}
/* ---- điện thoại: bảng trượt từ dưới (bottom sheet) ---- */
@media (max-width:768px){
  .ext-panel{position:fixed;left:0;right:0;bottom:0;top:auto;width:auto;max-height:72vh;border-radius:16px 16px 0 0;
    padding:4px 12px calc(10px + env(safe-area-inset-bottom));z-index:60}
  .ext-panel.is-min{max-height:none}
  .ext-panel.is-min>:not(.ext-grab):not(.ext-head){display:none}
  .ext-grab{display:block;width:44px;height:5px;border-radius:9px;background:var(--line);margin:4px auto 2px;cursor:pointer}
  .ext-row{min-height:44px;gap:8px}
  .ext-row .ext-cb,.ext-dcb{width:20px;height:20px}
  .ext-ic{width:34px;height:34px;font-size:13px}
  .ext-dh{min-height:42px}
  .ext-caret{width:28px;height:28px;font-size:13px}
  .ext-row .ext-op{flex-basis:56px;width:56px}
  .ext-drag{font-size:20px;padding:6px 4px}
  .ext-menu{left:8px!important;right:8px;width:auto;top:auto!important;bottom:calc(8px + env(safe-area-inset-bottom));border-radius:14px}
  .ext-menu button{padding:12px}
  .ext-pop .maplibregl-popup-content{max-height:45vh}
}
/* cá nhân hoá / kịch bản hiển thị */
.ext-onbar{flex-wrap:wrap}
.ext-onbtns{display:flex;gap:4px;flex-wrap:wrap}
.ext-setdef{border-color:var(--brand);color:var(--brand)}
.lv-tools .lv-note{font-size:11px}
.scn-panel{right:64px}
.scn-hint{font-size:11.5px;line-height:1.4}
.scn-form{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center;padding:6px;border:1px dashed var(--line);border-radius:10px}
.scn-form .scn-name{flex:1 1 220px;min-width:0;font:inherit;font-size:12.5px;padding:6px 9px;border:1px solid var(--line);border-radius:8px}
.scn-form label{display:inline-flex;align-items:center;gap:4px;font-size:12px;width:auto;margin:0}
.scn-form input[type=checkbox]{width:auto;margin:0}
.scn-row .chip{padding:3px 10px;font-size:11.5px}
.scn-login{font-size:12px;padding:4px}

/* ============ Trợ lý AI (ai.js) ============ */
.tool.ai-off{display:none}
.ai-panel{right:64px;width:min(460px,calc(100vw - 96px));height:min(640px,calc(100% - 90px));max-height:none}
.ai-panel .ext-head{gap:6px}
.ai-panel .ext-head b{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ai-logo{display:inline-flex;color:#7c3aed}
.ai-logo .ic{width:18px;height:18px}
.ai-model{max-width:150px;font:inherit;font-size:11.5px;padding:3px 6px;border:1px solid var(--line);border-radius:8px;background:var(--panel)}
.ai-log{flex:1 1 auto;min-height:120px;overflow:auto;display:flex;flex-direction:column;gap:8px;padding:2px 2px 6px}
.ai-empty{padding:18px 8px;text-align:center;color:var(--ink-soft);line-height:1.6}
.ai-hello{background:linear-gradient(135deg,#f5f3ff,#eff6ff);border:1px solid #e0e7ff;border-radius:12px;padding:10px 12px;line-height:1.5}
.ai-sugg{display:flex;flex-wrap:wrap;gap:6px}
.ai-sugg .chip{font-size:12px;padding:5px 10px}
.ai-msg{max-width:92%;padding:8px 11px;border-radius:14px;line-height:1.5;word-wrap:break-word;overflow-wrap:anywhere}
.ai-u{align-self:flex-end;background:var(--brand);color:#fff;border-bottom-right-radius:4px}
.ai-a{align-self:flex-start;background:var(--surface);border:1px solid var(--line-soft);border-bottom-left-radius:4px}
.ai-a p{margin:0 0 6px}.ai-a p:last-child{margin-bottom:0}
.ai-a h5{margin:8px 0 4px;font-size:13px}
.ai-a ul,.ai-a ol{margin:2px 0 6px;padding-left:20px}
.ai-a li{margin:1px 0}
.ai-a code{background:#eef2ff;border-radius:4px;padding:0 4px;font-size:11.5px}
.ai-a a{color:var(--brand)}
.ai-err{background:#fff5f5;border-color:#f2b8b5;color:#9f1239}
.ai-meta{margin-top:5px;font-size:10.5px;color:var(--ink-faint)}
.ai-steps{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px}
.ai-step{font-size:10.5px;padding:1px 7px;border-radius:999px;background:#ede9fe;color:#5b21b6}
.ai-step::before{content:"⚙ "}
.ai-step.is-err{background:var(--danger-weak,#fee2e2);color:var(--danger-ink,#991b1b)}
.ai-tblw{overflow:auto;margin:4px 0 6px}
.ai-tbl{border-collapse:collapse;font-size:11.5px;min-width:100%}
.ai-tbl th,.ai-tbl td{border:1px solid var(--line-soft);padding:3px 7px;text-align:left;vertical-align:top}
.ai-tbl th{background:var(--surface,#f1f5f9);font-weight:600}
.ai-typing em{font-size:11.5px;color:var(--ink-soft)}
.ai-typing span{display:inline-block;width:6px;height:6px;margin-right:3px;border-radius:50%;background:#7c3aed;animation:aiDot 1s infinite}
.ai-typing span:nth-child(2){animation-delay:.15s}.ai-typing span:nth-child(3){animation-delay:.3s}
@keyframes aiDot{0%,80%,100%{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}
.ai-ctx{display:flex;flex-wrap:wrap;gap:4px}
.ai-chip{font-size:11px;padding:2px 8px;border-radius:999px;background:var(--brand-weak);color:var(--brand-ink);max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ai-chip button{border:0;background:none;color:inherit;cursor:pointer;padding:0 0 0 2px;font-size:13px;line-height:1}
.ai-form{display:flex;align-items:flex-end;gap:6px}
.ai-in{flex:1;min-width:0;resize:none;font:inherit;font-size:13px;line-height:1.4;padding:8px 10px;border:1px solid var(--line);
  border-radius:12px;max-height:140px}
.ai-in:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}
.ai-send{padding:8px 12px;border-radius:12px}
.ai-foot{font-size:10.5px;text-align:center}
.popup-toggle.ai-ask{margin-top:6px;color:#6d28d9;border-color:#ddd6fe}
/* cấu hình AI */
.ai-cfg-box{display:flex;flex-direction:column;max-height:92vh}
.ai-cfg-body{overflow:auto;padding:12px 22px;display:flex;flex-direction:column;gap:14px;font-size:13px}
.ai-sec h4{margin:0 0 8px;font-size:13.5px}
.ai-sec textarea{width:100%;font:inherit;font-size:12.5px;padding:7px 9px;border:1px solid var(--line);border-radius:8px}
.ai-hint{font-size:11.5px;line-height:1.45;margin:2px 0 8px}
.ai-hint code{background:var(--surface,#f1f5f9);border-radius:4px;padding:0 4px}
.ai-inl{display:inline-flex!important;flex-direction:row!important;align-items:center;gap:6px;width:auto;margin:0;font-size:12.5px}
.ai-inl input{width:auto;margin:0}
.ai-prov{border:1px solid var(--line-soft);border-radius:10px;padding:8px 10px;margin-bottom:8px;display:flex;flex-direction:column;gap:6px}
.ai-prov.is-env{background:var(--ok-weak,#f0fdf4);border-color:#bbf7d0}
.ai-prov-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ai-prov-h b{font-size:13px}
.ai-prov-h .muted{font-size:11px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ai-prov-h .ai-pn{flex:1;min-width:140px;font-weight:600}
.ai-prov-m{font-size:11.5px}
.ai-prov .grid2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.ai-cfg-body .grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;align-items:end}
.ai-cfg-body .chip.del{color:var(--danger);border-color:#f2b8b5}
.linkbtn{border:0;background:none;color:var(--brand);cursor:pointer;font-size:11px;padding:0 0 0 6px}
.ai-test-out{font-size:11.5px}
.ai-ok{color:var(--ok)}.ai-bad{color:var(--danger)}
.ai-add{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.ai-add select{font:inherit;font-size:12.5px;padding:5px 8px;border:1px solid var(--line);border-radius:8px}
.ai-modes{display:flex;flex-direction:column;gap:4px;margin-bottom:6px}
.ai-pool{display:flex;flex-direction:column;gap:4px;margin-bottom:8px}
.ai-pool-r{display:flex;align-items:center;gap:6px;padding:4px 8px;border:1px solid var(--line-soft);border-radius:8px}
.ai-pool-n{width:20px;height:20px;border-radius:50%;background:var(--brand-weak);color:var(--brand-ink);font-size:11px;
  display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}
.ai-pool-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ai-pool-r .chip{padding:1px 8px}
.ai-cfg-msg{margin-right:auto;font-size:12px}
@media (max-width:768px){
  .ai-panel{height:78vh;width:auto}
  .ai-panel.is-min{height:auto}
  .ai-model{max-width:110px}
  .ai-in{font-size:16px}
  .ai-msg{max-width:96%}
  .ai-prov .grid2,.ai-cfg-body .grid3{grid-template-columns:1fr}
  .ai-cfg-body{padding:10px 12px}
}

.ai-alias{flex:0 1 190px;min-width:110px;font:inherit;font-size:12px;padding:4px 8px;border:1px solid var(--line);border-radius:7px}
.ai-pool-l{font-size:11.5px;color:var(--ink-soft)}
@media (max-width:768px){.ai-pool-r{flex-wrap:wrap}.ai-alias{flex:1 1 100%;order:5}}

/* ============ Cảnh 3D + thư viện nguồn thế giới (scene3d.js) ============ */
.tool.is-open{background:var(--brand-weak)}
.s3d-panel{right:64px;width:min(380px,calc(100vw - 96px));overflow:auto}
.s3d-logo{display:inline-flex;color:var(--brand)}
/* kiem tra tuan thu quy hoach (tuan-thu.js) */
.tt-panel .ext-head .chip{margin-left:auto}
.tt-sum{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.tt-card{border:1px solid var(--line-soft);border-left:4px solid var(--c);border-radius:9px;padding:5px 7px;display:flex;flex-direction:column;background:var(--panel)}
.tt-card b{font-size:16px;color:var(--c)}.tt-card span{font-size:10.5px;color:var(--ink-soft)}
.tt-ma{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:11.5px}
.tt-list{max-height:240px;overflow:auto;border:1px solid var(--line-soft);border-radius:9px}
.tt-it{display:flex;gap:7px;align-items:flex-start;width:100%;text-align:left;padding:5px 8px;border:0;border-bottom:1px solid var(--line-soft);
  background:var(--panel);font:inherit;font-size:11.5px;cursor:pointer;color:var(--ink)}
.tt-it:hover{background:var(--brand-weak)}
.tt-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;margin-top:4px}
.tt-lo{border:1px solid var(--line-soft);border-radius:10px;padding:7px 8px;background:#fafbff;display:flex;flex-direction:column;gap:4px;font-size:12px}
.tt-kq{width:100%;border-collapse:collapse;font-size:11.5px}
.tt-kq th{text-align:left;font-weight:600;color:var(--ink-soft);border-bottom:1px solid var(--line);padding:3px 4px}
.tt-kq td{border-bottom:1px solid var(--line-soft);padding:3px 4px;vertical-align:top}
.tt-kq .muted{font-size:10.5px}
.tt-kq tr.tt-vi_pham td:first-child{color:#c62828;font-weight:600}
.tt-badge{color:#fff;border-radius:999px;padding:1px 7px;font-size:10.5px;white-space:nowrap}
.tt-ket{color:#fff;font-weight:700;border-radius:8px;padding:5px 8px;text-align:center;letter-spacing:.3px}
.tt-cc{border-top:1px solid var(--line-soft);padding-top:6px}
.ss3-tang{color:var(--ok-ink,#15803d);font-weight:600}.ss3-giam{color:#c62828;font-weight:600}
/* sua tung cong trinh 3D (scene3d.js suaBox) + muc mo hinh do an */
.s3d-sua{position:absolute;left:12px;bottom:58px;z-index:31;width:min(330px,calc(100vw - 24px));background:var(--panel,#fff);
  border:1px solid var(--line);border-radius:14px;box-shadow:0 10px 30px rgba(15,23,42,.18);padding:8px 10px;display:flex;flex-direction:column;gap:6px;font-size:12.5px}
.s3d-sua-h{display:flex;align-items:center;gap:6px}.s3d-sua-h .icon-btn{margin-left:auto}
.s3d-sua-luu{border-top:1px solid var(--line-soft);padding-top:6px}
.s3d-tt{font-size:11.5px;font-weight:600}.s3d-tt.dang{color:var(--warn-ink,#b45309)}.s3d-tt.xong{color:var(--ok-ink,#15803d)}.s3d-tt.loi{color:#c62828}
.s3d-tt-o{font-size:11.5px;margin:4px 0}
.s3d-mau{display:inline-block;width:14px;height:8px;border-radius:3px;flex:0 0 auto}
/* quan ly quy chuan doi chieu (quy-chuan.js) */
.qc-hop{position:fixed;inset:0;z-index:2000;background:rgba(15,23,42,.45);display:flex;align-items:center;justify-content:center;padding:16px}
.qc-hop[hidden]{display:none}
.qc-khung{background:var(--panel,#fff);border-radius:14px;box-shadow:0 20px 60px rgba(0,0,0,.3);width:min(1100px,100%);max-height:92vh;display:flex;flex-direction:column}
.qc-dau{display:flex;align-items:center;padding:10px 14px;border-bottom:1px solid var(--line)}.qc-dau .icon-btn{margin-left:auto}
.qc-than{display:flex;gap:12px;padding:10px 14px;overflow:auto;min-height:0;flex:1}
.qc-ds{flex:0 0 230px;display:flex;flex-direction:column;gap:6px}
.qc-pb{text-align:left;border:1px solid var(--line);border-radius:10px;padding:6px 8px;background:var(--panel);cursor:pointer;display:flex;flex-direction:column;font:inherit;font-size:12.5px}
.qc-pb span{font-size:11px;color:var(--ink-soft)}.qc-pb.on{border-color:var(--brand);background:var(--brand-weak)}
.qc-form{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;font-size:12.5px}
.qc-hang{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center}
.qc-hang input,.qc-luoi input{font:inherit;font-size:12px;padding:3px 6px;border:1px solid var(--line);border-radius:6px}
.qc-muc{border:1px solid var(--line-soft);border-radius:10px;padding:6px 10px;display:flex;flex-direction:column;gap:6px}
.qc-muc legend{font-weight:600;padding:0 4px}
.qc-luoi{border-collapse:collapse}.qc-luoi th,.qc-luoi td{border:1px solid var(--line-soft);padding:2px 4px;font-size:11.5px;text-align:center}
.qc-luoi input{width:56px;text-align:right}
.qc-chan{display:flex;gap:8px;align-items:center;padding:10px 14px;border-top:1px solid var(--line)}
@media (max-width:768px){.qc-than{flex-direction:column}.qc-ds{flex:none}}
.s3d-mh{border:1px solid var(--line-soft);border-radius:10px;padding:6px 8px;margin-top:6px;background:#fafbff;font-size:12px}
.tt-card input{margin:0 3px 0 0;vertical-align:-1px}
.s3d-switch{display:flex;align-items:center;gap:10px;width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:12px;
  background:var(--panel);font:inherit;font-weight:600;cursor:pointer;color:var(--ink)}
.s3d-switch span{width:34px;height:20px;border-radius:999px;background:#cbd5e1;position:relative;flex:0 0 auto;transition:background .2s}
.s3d-switch span::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;transition:left .2s;box-shadow:0 1px 2px rgba(0,0,0,.25)}
.s3d-switch.is-on{border-color:var(--brand);background:var(--brand-weak);color:var(--brand-ink)}
.s3d-switch.is-on span{background:var(--brand)}
.s3d-switch.is-on span::after{left:16px}
.s3d-hint{font-size:11px;line-height:1.35}
.s3d-sec{border-top:1px solid var(--line-soft);padding-top:8px;display:flex;flex-direction:column;gap:5px}
.s3d-sec h5{margin:0 0 2px;font-size:12.5px}
.s3d-r{display:flex!important;flex-direction:row!important;align-items:center;gap:7px;font-size:12.5px;margin:0;width:auto}
.s3d-r input{width:auto;margin:0}
.s3d-row{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center;font-size:12px}
.s3d-row label{display:inline-flex!important;flex-direction:row!important;align-items:center;gap:6px;margin:0;width:auto}
.s3d-row input[type=number]{width:62px;padding:3px 6px;font:inherit;font-size:12px;border:1px solid var(--line);border-radius:6px}
.s3d-row input[type=range]{width:110px}
.s3d-row select{font:inherit;font-size:12px;padding:2px 4px;border:1px solid var(--line);border-radius:6px}
.s3d-minfo,.s3d-ifc-st{font-size:11px}
.s3d-ifc{border:1px solid var(--line-soft);border-radius:10px;padding:6px 8px;display:flex;flex-direction:column;gap:5px;background:#fafbff}
.s3d-ifc-h{display:flex;flex-direction:column}
.s3d-ifc-h b{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.s3d-ifc-h .muted{font-size:10.5px}
.s3d-acts{display:flex;flex-wrap:wrap;gap:5px}
.s3d-acts .chip{font-size:11.5px;padding:3px 9px}
.s3d-acts .chip .ic{width:14px;height:14px}
.s3d-acts .chip.del{color:var(--danger);border-color:#f2b8b5}
/* thư viện */
.lib-box{display:flex;flex-direction:column;max-height:92vh;width:min(1100px,97vw)}
.lib-bar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:10px 22px 4px}
.lib-cats{display:flex;flex-wrap:wrap;gap:5px;flex:1}
.lib-cats .chip.is-on{background:var(--brand);color:#fff;border-color:var(--brand)}
.lib-q{flex:0 1 280px;font:inherit;font-size:13px;padding:6px 10px;border:1px solid var(--line);border-radius:9px}
.lib-grid{overflow:auto;padding:10px 22px;display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:10px;align-content:start}
.lib-card{border:1px solid var(--line-soft);border-radius:12px;padding:10px 12px;display:flex;flex-direction:column;gap:4px;background:var(--panel)}
.lib-card:hover{box-shadow:var(--shadow-1)}
.lib-h{display:flex;align-items:flex-start;gap:6px}
.lib-h b{flex:1;font-size:13px;line-height:1.3}
.lib-k{font-size:10px;padding:1px 6px;border-radius:999px;background:var(--surface,#f1f5f9);color:var(--ink-soft);white-space:nowrap}
.lib-p{font-size:11.5px;color:var(--ink-soft)}
.lib-need{color:var(--warn);font-weight:600}
.lib-d{font-size:12px;line-height:1.4}
.lib-lic{font-size:10.5px}
.lib-in{font:inherit;font-size:12px;padding:5px 8px;border:1px solid var(--line);border-radius:7px}
.lib-acts{display:flex;align-items:center;gap:8px;margin-top:auto;padding-top:4px;font-size:11.5px}
.lib-ok{color:var(--ok);font-weight:600;flex:1}
.lib-note{font-size:11px;margin-right:auto}
@media (max-width:768px){
  .s3d-panel{width:auto}
  .lib-bar,.lib-grid{padding-left:12px;padding-right:12px}
  .lib-q{flex:1 1 100%}
  .lib-grid{grid-template-columns:1fr}
}

/* mẫu khối 3D */
.s3d-tpl{display:flex;flex-direction:column;gap:6px;padding:6px 8px;border:1px dashed var(--line);border-radius:10px;margin:2px 0 4px}
.s3d-ctbl{width:100%;border-collapse:collapse;font-size:11.5px}
.s3d-ctbl th{text-align:left;font-weight:600;color:var(--ink-soft);padding:2px 4px}
.s3d-ctbl td{padding:2px 4px;border-top:1px solid var(--line-soft)}
.s3d-ctbl select{width:100%;max-width:170px;font:inherit;font-size:11.5px;padding:2px 4px;border:1px solid var(--line);border-radius:6px}
.tpl-body{overflow:auto;padding:10px 22px;display:flex;flex-direction:column;gap:10px}
.tpl-add{border:1px dashed var(--brand);border-radius:12px;padding:10px 12px;display:flex;flex-direction:column;gap:6px;background:#f8fbff}
.tpl-add input[type=text],.tpl-add .tpl-name,.tpl-add .tpl-url{flex:1 1 240px;font:inherit;font-size:12.5px;padding:6px 9px;border:1px solid var(--line);border-radius:8px}
.tpl-st{font-size:11.5px;line-height:1.5}
.tpl-grid{padding:0}
@media (max-width:768px){.tpl-body{padding:10px 12px}}

/* hạ tầng 3D */
.s3d-legend{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:11px;margin:2px 0}
.s3d-legend span{display:inline-flex;align-items:center;gap:4px}
.s3d-legend i{width:18px;height:6px;border-radius:3px;display:inline-block}

/* đi bộ trong đô thị */
#walk-hud{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:70;background:var(--glass);border:1px solid var(--line-soft);
  border-radius:14px;box-shadow:var(--shadow-3);padding:8px 12px;display:flex;flex-direction:column;gap:6px;max-width:calc(100vw - 24px);font-size:12.5px}
#walk-hud[hidden]{display:none}
#walk-hud .wk-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
#walk-hud .wk-info{flex:1;color:var(--ink-soft);font-size:12px;min-width:160px}
#walk-hud .wk-help{font-size:11px}
#walk-hud .wk-pad{display:grid;grid-template-columns:repeat(3,44px) 44px;gap:4px;justify-content:center}
#walk-hud .wk-pad button{height:40px;border:1px solid var(--line);border-radius:10px;background:var(--panel);font-size:17px;cursor:pointer;touch-action:none;user-select:none}
#walk-hud .wk-pad button:active{background:var(--brand-weak)}
#walk-hud .wk-pad [data-k=shift]{grid-column:4;grid-row:1 / span 2;height:auto}
@media (hover:hover) and (pointer:fine){#walk-hud .wk-pad{display:none}}
body.walking .toolbar,body.walking .ext-panel{display:none!important}
body.walking #map canvas{cursor:grab}
.lib-k-new{background:var(--ok-weak,#dcfce7)!important;color:var(--ok-ink,#166534)!important}
.tpl-build .s3d-row input[type=color]{width:34px;height:24px;padding:0;border:1px solid var(--line);border-radius:6px;vertical-align:middle}
.tpl-build .s3d-row input[type=number]{width:62px}
.tpl-bname{flex:1 1 220px;font:inherit;font-size:12.5px;padding:6px 9px;border:1px solid var(--line);border-radius:8px}

/* Kieu MapLibre tu khai (nguon Martin) */
.ext-json { width: 100%; font: 12px/1.45 ui-monospace, Consolas, monospace; resize: vertical; white-space: pre; }


/* nut bang du lieu cua lop anh / 3D (khong co bang) */
.ext-ic.ext-tb.is-off { opacity: .32; cursor: help; }


/* thong tin doi tuong NGUON NGOAI tren thanh ben */
.ext-ctx-t { font-weight: 600; margin: 4px 0 6px; }
.ext-ctx-a { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 8px; }


/* nut bat / tat nhan: dang TAT -> do + gach cheo */
.tool#t-labels { position: relative; }
.tool#t-labels.is-off { color:var(--danger-ink,#b91c1c); background:var(--danger-weak,#fef2f2); }
.tool#t-labels.is-off::after { content: ""; position: absolute; left: 22%; right: 22%; top: 50%; height: 2px;
  background: #b91c1c; transform: rotate(-45deg); border-radius: 2px; }

/* nut bat / tat nhanh ca nhom nguon du lieu */
.ext-grps { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 6px; }
.ext-grp { font-weight: 600; }
.ext-grp.is-on { background: var(--brand-weak); border-color: var(--brand); color: var(--brand-ink); }
.ext-grp .ext-grp-n { font-weight: 400; opacity: .7; font-size: .9em; }

.tool[hidden] { display: none !important; }


/* Canh 3D CesiumJS: bang "Du lieu 3D" + keo tha IFC */
#cesium-box .cz-panel { position: absolute; top: 52px; left: 10px; z-index: 5; width: min(320px, calc(100% - 20px));
  max-height: calc(100% - 120px); overflow: auto; background: var(--glass); border-radius: 12px;
  box-shadow: 0 6px 24px rgba(0,0,0,.25); padding: 8px 10px; font-size: 13px; color:var(--ink,#1f2937); }
#cesium-box .cz-panel.is-min .cz-body { display: none; }
#cesium-box .cz-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
#cesium-box .cz-sub { margin: 10px 0 4px; font-weight: 600; font-size: 12px; color:var(--ink-soft,#475569); text-transform: uppercase; letter-spacing: .03em; }
#cesium-box .cz-row { display: flex; align-items: center; gap: 6px; padding: 3px 0; }
#cesium-box .cz-row .cz-chk, #cesium-box .cz-row .cz-ifcn { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#cesium-box .cz-chk { display: flex; align-items: center; gap: 6px; cursor: pointer; }
#cesium-box .cz-tag { font-size: 11px; color:var(--ink-soft,#64748b); background:var(--surface,#f1f5f9); border-radius: 6px; padding: 0 5px; }
#cesium-box .cz-tag.cz-warn { color:var(--warn-ink,#b45309); background:var(--warn-weak,#fef3c7); }
#cesium-box .cz-hint { font-size: 11.5px; }
#cesium-box .cz-st { margin-top: 4px; font-size: 12px; }
#cesium-box.cz-drop::after { content: "Thả tệp .ifc để mở trong cảnh 3D"; position: absolute; inset: 0; z-index: 9;
  display: grid; place-items: center; font-size: 20px; font-weight: 600; color: #fff; background: rgba(26,115,232,.45);
  border: 3px dashed #fff; pointer-events: none; }

/* Thiết kế tuyến đường: CSS đã chuyển về gói plugins_store/road_design/web/road.css (gỡ gói không sót CSS trong lõi) */
.linkbtn{border:0;background:none;color:var(--brand,#2563eb);text-decoration:underline;cursor:pointer;font:inherit;padding:0}

/* nhat ky he thong (audit.js) */
.au-tools{flex-wrap:wrap;gap:6px}
.au-tools input,.au-tools select{font:inherit;padding:5px 8px;border:1px solid var(--line-soft);border-radius:8px;background:var(--panel)}
.au-sys{font-size:12px;margin:6px 0}
.au-list{overflow:auto;max-height:52vh}
.au-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.au-tbl th{position:sticky;top:0;background:var(--surface,#f8fafc);text-align:left;padding:5px 6px;border-bottom:1px solid var(--line-soft);font-weight:600;color:var(--ink-soft,#475569)}
.au-tbl td{padding:4px 6px;border-bottom:1px solid #f1f5f9;white-space:nowrap}
.au-tbl tr.au-bad td{color:var(--danger-ink,#b91c1c);background:var(--danger-weak,#fef2f2)}

/* plugin: nut dang tai + quan tri mo-dun */
.tool.is-loading{opacity:.55;cursor:progress}
.pl-hint{font-size:12px;margin-bottom:8px;line-height:1.5}
.pl-row{display:flex;gap:10px;align-items:flex-start;padding:10px;border:1px solid var(--line-soft);border-radius:10px;margin-bottom:8px;background:var(--panel)}
.pl-row.is-off{opacity:.6}
.pl-main{flex:1;min-width:0}
.pl-desc{font-size:12px;margin-top:3px;line-height:1.45}
.pl-err{color:var(--danger-ink,#b91c1c);font-size:12px}
.pl-sw{position:relative;width:38px;height:22px;flex:0 0 auto;margin-top:2px}
.pl-sw input{opacity:0;width:0;height:0}
.pl-sw span{position:absolute;inset:0;background:#cbd5e1;border-radius:22px;transition:.2s;cursor:pointer}
.pl-sw span::before{content:"";position:absolute;width:16px;height:16px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.2s}
.pl-sw input:checked+span{background:var(--brand,#2563eb)}
.pl-sw input:checked+span::before{transform:translateX(16px)}

/* ============================================================
   THANH CÔNG CỤ GỌN (js/toolgroups.js): rail ngắn + menu nhóm có nhãn
   ============================================================ */
#toolbar .tool-sep{width:22px;height:1px;margin:3px auto;background:var(--line-soft)}
.tg-btn{position:relative}
.tg-btn::before{content:"";position:absolute;right:3px;bottom:3px;border:3px solid transparent;
  border-right-color:currentColor;border-bottom-color:currentColor;opacity:.45}
.tg-btn.tg-open{background:var(--brand);color:#fff}
.tg-btn.tg-on::after{content:"";position:absolute;top:5px;right:5px;width:7px;height:7px;border-radius:50%;
  background:#16a34a;box-shadow:0 0 0 2px #fff}
.tg-menu{position:fixed;z-index:60;width:272px;overflow:auto;padding:6px;background:var(--panel);
  border:1px solid var(--line-soft);border-radius:13px;box-shadow:var(--shadow-3,0 10px 30px rgba(0,0,0,.18));
  animation:tgIn .12s ease}
.tg-menu[hidden]{display:none}
@keyframes tgIn{from{opacity:0;transform:translateX(6px)}to{opacity:1;transform:none}}
.tg-head{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint);
  padding:4px 8px 6px}
.tg-items{display:flex;flex-direction:column;gap:1px}
.tg-menu .tool{width:100%!important;height:auto!important;min-height:44px;display:grid!important;
  grid-template-columns:30px 1fr;grid-template-rows:auto auto;align-items:center;column-gap:8px;
  padding:6px 8px;border-radius:9px;text-align:left;justify-items:start}
.tg-menu .tool[hidden]{display:none!important}
.tg-menu .tool .ic{grid-row:1 / span 2;justify-self:center;width:19px;height:19px}
.tg-menu .tool::after{content:attr(data-tg-label);grid-column:2;font-size:13px;font-weight:600;color:var(--ink);line-height:1.25}
.tg-menu .tool::before{content:attr(data-tg-hint);grid-column:2;grid-row:2;order:2;font-size:11px;color:var(--ink-faint);line-height:1.3}
.tg-menu .tool[data-tg-hint=""]::before{display:none}
.tg-menu .tool:hover{background:var(--hover)}
.tg-menu .tool.active,.tg-menu .tool[aria-pressed="true"],.tg-menu .tool.has-on{background:#eef4ff}
.tg-menu .tool.active::after,.tg-menu .tool.has-on::after{color:var(--brand)}
@media (max-width:768px){.tg-menu{width:min(272px,calc(100vw - 80px))}}
/* ===== Danh muc do an: cach trinh bay (danh sach / cay theo loai - dia ban - chu dau tu) ===== */
.proj-view{display:flex;gap:2px;padding:3px;margin:2px 0 6px;background:var(--surface);border:1px solid var(--line-soft);border-radius:10px}
.proj-view button{flex:1;min-width:0;border:0;background:none;font:inherit;font-size:11.5px;font-weight:600;color:var(--ink-soft);
  padding:6px 4px;border-radius:7px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.proj-view button:hover{color:var(--ink);background:var(--hover)}
.proj-view button.is-active{background:var(--panel);color:var(--brand);box-shadow:0 1px 2px rgba(60,64,67,.18)}
.project-list.is-tree{gap:2px}
.pt-grp{display:flex;flex-direction:column}
.pt-head{display:flex;align-items:center;gap:6px;width:100%;border:0;background:none;font:inherit;text-align:left;cursor:pointer;
  padding:7px 8px;border-radius:8px;color:var(--ink)}
.pt-head:hover{background:var(--surface)}
.pt-grp.d0>.pt-head{font-weight:700;font-size:12.5px}
.pt-grp.d1>.pt-head{font-weight:600;font-size:12px;padding-left:22px;color:var(--ink-soft)}
.pt-car{flex:0 0 auto;width:12px;color:var(--ink-faint);font-size:10px;transition:transform .15s}
.pt-grp.is-open>.pt-head .pt-car{transform:rotate(90deg)}
.pt-dot{flex:0 0 auto;width:8px;height:8px;border-radius:50%;background:var(--cap,#94a3b8)}
.pt-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pt-cnt{flex:0 0 auto;font-size:10.5px;font-weight:700;color:var(--ink-soft);background:var(--surface);border:1px solid var(--line-soft);
  border-radius:999px;padding:1px 7px}
.pt-items{list-style:none;margin:2px 0 6px;padding:0 0 0 14px;display:flex;flex-direction:column;gap:2px}
.pt-grp.d1 .pt-items{padding-left:30px}
.pt-item{position:relative;display:flex;align-items:center;gap:6px;padding:6px 6px 6px 10px;border-radius:8px;cursor:pointer;
  border:1px solid transparent}
.pt-item::before{content:"";position:absolute;left:0;top:7px;bottom:7px;width:3px;border-radius:2px;background:var(--cap,#94a3b8);opacity:.75}
.pt-item:hover{background:var(--surface);border-color:var(--line-soft)}
.pt-item.active{background:var(--brand-weak);border-color:color-mix(in srgb,var(--brand) 25%,#fff)}
.pt-item.on-map .pt-name{color:var(--brand-ink)}
.pt-item.pending{opacity:.6}
.pt-main{flex:1;min-width:0}
.pt-name{font-size:12.5px;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pt-meta{font-size:10.5px;color:var(--ink-faint);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pt-pub{flex:0 0 auto;color:#16a34a;font-size:9px}
.pt-item .pi-add{flex:0 0 auto;opacity:.55}
.pt-item:hover .pi-add,.pt-item.on-map .pi-add{opacity:1}
/* bo loc danh muc: xa/phuong + chu dau tu chiem ca dong (ten dai) */
.filters .f-wide{grid-column:1/-1}
/* cay danh muc: o tick nhom / do an (bat tat hien thi tren ban do) */
.pt-head{user-select:none}
.pt-head:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.pt-cb{flex:0 0 auto;margin:0;width:15px;height:15px;cursor:pointer;accent-color:var(--brand)}
.pt-item .pt-cb{margin-left:2px}
.pt-grp.has-on>.pt-head .pt-lbl{color:var(--brand-ink)}
.pt-item.on-map{background:color-mix(in srgb,var(--brand) 4%,#fff)}

/* ---- Trang HTML (js/trang.js): quan ly /trang/ ---- */
.modal-box.tr-box{width:min(980px,97vw);height:min(86vh,900px);max-height:none;display:flex;flex-direction:column;overflow:hidden}
.tr-body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:8px;padding:0 22px 18px}
.tr-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.tr-sp{flex:1 1 auto}
.tr-crumb{font-weight:600;font-size:14px}
.tr-box button.link{background:none;border:0;padding:0;color:var(--brand-ink);cursor:pointer;font:inherit;text-align:left}
.tr-box button.link:hover{text-decoration:underline}
.tr-url{font-size:12px;color:var(--ink-soft);word-break:break-all}
.tr-url a{color:var(--brand-ink)}
.tr-ok{color:var(--ok-ink,#188038);font-weight:600}
.tr-drop{flex:1 1 auto;min-height:120px;overflow:auto;border:1px dashed var(--line-soft);border-radius:12px;display:flex;flex-direction:column}
.tr-drop.is-over{border-color:var(--brand);background:var(--brand-weak)}
.tr-list{flex:1 1 auto}
.tr-row{display:flex;align-items:center;gap:8px;padding:6px 10px;border-bottom:1px solid var(--line-soft);font-size:13px}
.tr-row:hover{background:color-mix(in srgb,var(--brand) 5%,#fff)}
.tr-row.is-index .tr-name{font-weight:700}
.tr-ic{flex:0 0 auto;color:var(--ink-soft);display:flex}
.tr-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tr-tag{font-size:11px;padding:1px 7px;border-radius:999px;background:var(--ok-weak,#e6f4ea);color:var(--ok-ink,#188038)}
.tr-tag-nh{background:#fff4e5;color:var(--warn-ink,#b45309)}
.tr-nh{margin-top:4px}
.tr-nh-on{color:var(--warn-ink,#b45309);font-weight:600}
.modal-box.tr-sh{width:min(720px,96vw)}
.tr-sh-bd{display:grid;grid-template-columns:220px 1fr;gap:16px;padding:4px 22px 20px;align-items:start}
.tr-sh-qr{width:220px;height:220px;border:1px solid var(--line-soft);border-radius:12px;padding:8px;background:#fff;display:grid;place-items:center}
.tr-sh-qr svg{width:100%;height:100%;display:block}
.tr-sh-r{display:grid;gap:10px;min-width:0}
.tr-sh-url{font-size:12px;word-break:break-all;background:var(--brand-weak);border-radius:8px;padding:6px 9px}
.tr-sh-warn{font-size:12px;background:var(--warn-weak,#fff7ed);color:#9a3412;border:1px solid #fed7aa;border-radius:8px;padding:6px 9px}
.tr-sh-row{display:flex;flex-wrap:wrap;gap:6px}
.tr-sh-lbl{font-size:12px;font-weight:600;color:var(--ink-soft)}
.tr-sh-fb{background:#1877f2;color:#fff;border-color:#1877f2}
.tr-sh-zl{background:#0068ff;color:#fff;border-color:#0068ff}
.tr-sh-note{font-size:11.5px;line-height:1.5}
.tr-cd{font-size:11px;padding:1px 7px;border-radius:999px;white-space:nowrap;background:#e8eaed;color:#3c4043}
.tr-cd-cong_khai{background:var(--ok-weak,#e6f4ea);color:var(--ok-ink,#137333)}.tr-cd-noi_bo{background:#e8f0fe;color:#1a56c4}.tr-cd-nhom{background:#f3e8fd;color:#7b1fa2}.tr-cd-nhap{background:var(--danger-weak,#fce8e6);color:#a50e0e}
.tr-nh .btn{margin-left:6px;vertical-align:middle}
.modal-box.tq-box{width:min(560px,96vw)}
.tq-bd{padding:4px 22px 18px;display:grid;gap:8px}
.tq-url{font-size:12px;word-break:break-all}
.tq-op{display:flex;gap:10px;align-items:flex-start;border:1px solid var(--line-soft);border-radius:10px;padding:8px 10px;cursor:pointer}
.tq-op:has(input:checked){border-color:var(--brand);background:var(--brand-weak)}
.tq-op span{display:grid;gap:2px}.tq-op small{color:var(--ink-soft);font-size:12px}
.tq-chon{display:grid;gap:6px;border-top:1px solid var(--line-soft);padding-top:8px}
.tq-lbl{font-size:12px;font-weight:600;color:var(--ink-soft)}
.tq-nhom{max-height:180px;overflow:auto;display:grid;gap:2px;border:1px solid var(--line-soft);border-radius:8px;padding:6px 8px;font-size:13px}
.tq-chon input[type=text],.tq-chon input[type=search],.tds-tim{width:100%;padding:6px 9px;border:1px solid var(--line-soft);border-radius:8px;font:inherit}
.tq-lich{font-size:11.5px}.tq-foot{display:flex;justify-content:flex-end;gap:6px;margin-top:4px}
.modal-box.tds-box{width:min(720px,96vw);max-height:86vh;display:flex;flex-direction:column}
.tds-bd{padding:4px 22px 18px;display:flex;flex-direction:column;gap:8px;min-height:0;flex:1 1 auto}
.tds-bar{display:flex;gap:6px;align-items:center}.tds-bar .tds-tim{flex:1 1 auto}
.tds-list{overflow:auto;display:grid;gap:6px}
.tds-it{display:flex;align-items:center;gap:8px;border:1px solid var(--line-soft);border-radius:10px;padding:8px 10px}
.tds-it:hover{border-color:var(--brand)}
.tds-a{flex:1 1 auto;min-width:0;display:flex;gap:10px;align-items:center;color:inherit;text-decoration:none}
.tds-ic{color:var(--brand-ink);display:flex}
.tds-t{display:grid;min-width:0}.tds-t b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tds-t small{font-size:11.5px;color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tds-it .pi-ic{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;background:var(--panel);cursor:pointer}
.tds-rong{padding:24px;text-align:center}
@media (max-width:560px){.tr-sh-bd{grid-template-columns:1fr}.tr-sh-qr{margin:auto}}
.tr-size{flex:0 0 72px;text-align:right;color:var(--ink-soft);font-size:12px}
.tr-date{flex:0 0 110px;text-align:right;color:var(--ink-soft);font-size:12px}
.tr-act{flex:0 0 auto;display:flex;gap:4px}
.tr-act .pi-ic{width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;background:var(--panel);cursor:pointer}
.tr-act .pi-del:hover{color:var(--danger-ink,#d93025);border-color:#d93025}
.tr-empty{padding:24px;text-align:center}
.tr-hint{padding:8px 10px;font-size:12px;color:var(--ink-soft);text-align:center}
.tr-msg{font-size:13px;padding:6px 10px;border-radius:8px;background:var(--brand-weak)}
.tr-msg.ok{background:var(--ok-weak,#e6f4ea);color:var(--ok-ink,#137333)}
.tr-msg.warn{background:var(--warn-weak,#fef7e0);color:#8a5a00}
.tr-msg.err{background:var(--danger-weak,#fce8e6);color:var(--danger-ink,#c5221f)}
.tr-edit{flex:1.4 1 auto;min-height:240px;display:flex;flex-direction:column;gap:6px}
.tr-ehead{display:flex;align-items:center;gap:6px;font-size:13px}
.tr-code{flex:1 1 auto;width:100%;resize:none;font:12.5px/1.5 Consolas,"Cascadia Mono",monospace;padding:10px;border:1px solid var(--line-soft);border-radius:10px;tab-size:2;white-space:pre}
.tr-box:has(.tr-edit:not([hidden])) .tr-drop{flex:0 1 200px}
@media (max-width:640px){.modal-box.tr-box{width:100vw;height:100dvh}.tr-date{display:none}.tr-body{padding:0 12px 12px}}

/* Ten "Cong thong tin Khong gian So": 2 dong gon (moi cum 1 dong) */
.side-head .brand-title{white-space:normal;overflow:visible;font-size:13px;line-height:1.22}
.side-head .brand-title>span{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:900px){                 /* thanh ben hep 290px: nut dang nhap chi bieu tuong, nhuong cho cho ten */
  .side-head .acct-login{font-size:0;gap:0;padding:7px 9px}
}

/* ---- Mo-dun chuc nang (js/modun.js) ---- */
.modal-box.md-box{width:min(980px,96vw);height:min(86vh,860px);max-height:none;display:flex;flex-direction:column;overflow:hidden}
.md-box .modal-head{gap:12px}
.md-box .modal-head h3{display:flex;align-items:center;gap:8px;white-space:nowrap}
.md-q{margin-left:auto;width:min(260px,40vw);border:1px solid var(--line-soft);border-radius:8px;padding:6px 10px;font:inherit;font-size:13px}
.md-note{padding:8px 22px 0;font-size:12.5px}
.md-body{flex:1 1 auto;overflow:auto;padding:6px 22px 20px}
.md-grp h4{margin:14px 0 8px;font-size:13px;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.04em}
.md-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(400px,1fr));gap:10px}
.md-card{display:flex;gap:12px;align-items:flex-start;border:1px solid var(--line-soft);border-radius:12px;padding:12px;background:var(--panel);transition:border-color .15s,box-shadow .15s}
.md-card:hover{border-color:var(--brand-a35);box-shadow:0 2px 10px var(--brand-a12)}
.md-card.off{background:var(--surface,#f8f9fa)}
.md-card.off .md-ic{filter:grayscale(1);opacity:.6}
.md-ic{flex:0 0 42px;height:42px;border-radius:11px;background:var(--brand-weak);color:var(--brand-ink);display:flex;align-items:center;justify-content:center}
.md-main{flex:1 1 auto;min-width:0}
.md-main b{font-size:14px}
.md-desc{font-size:12.5px;color:var(--ink-soft);margin:3px 0 5px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.md-meta{font-size:11.5px;color:var(--ink-soft)}
.md-on{color:var(--ok-ink,#188038);font-weight:600}.md-offt{color:var(--ink-faint,#80868b);font-weight:600}.md-err{color:var(--danger-ink,#c5221f)}
.md-act{display:flex;flex-direction:column;align-items:flex-end;gap:8px}
.md-sw{position:relative;display:inline-block;width:38px;height:22px;cursor:pointer}
.md-sw input{display:none}
.md-sw span{position:absolute;inset:0;border-radius:999px;background:#cfd4dc;transition:.15s}
.md-sw span::after{content:"";position:absolute;left:3px;top:3px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:.15s}
.md-sw input:checked+span{background:var(--brand)}
.md-sw input:checked+span::after{left:19px}
.md-empty{padding:40px;text-align:center;color:var(--ink-soft)}
@media (max-width:700px){.md-grid{grid-template-columns:1fr}.modal-box.md-box{width:100vw;height:100dvh}}

/* mo-dun an khoi thanh cong cu (Mo-dun chuc nang) */
.tool.pl-off{display:none !important}
.md-swl{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--ink-soft);white-space:nowrap;cursor:pointer}
.md-swl.dis{opacity:.45;cursor:default}
.md-tabs{display:flex;gap:2px;background:var(--surface,#f1f3f4);border-radius:9px;padding:2px}
.md-tabs button{border:0;background:none;padding:5px 12px;border-radius:7px;font:inherit;font-size:13px;color:var(--ink-soft);cursor:pointer;white-space:nowrap}
.md-tabs button.is-on{background:var(--panel);color:var(--brand-ink);font-weight:600;box-shadow:0 1px 2px rgba(0,0,0,.12)}
.md-kho{color:#7c3aed;font-weight:600}.md-new{color:#b06000;font-weight:600}
.md-act .btn{white-space:nowrap}
.md-kho-cong{display:grid;grid-template-columns:repeat(auto-fit,minmax(380px,1fr));gap:12px;margin-top:10px}
.md-kho-o{border:1px solid var(--line-soft);border-radius:12px;padding:10px 12px;background:var(--panel);display:flex;flex-direction:column;gap:8px}
.md-kho-o h4{margin:0;font-size:13px;color:var(--ink)}
.md-kho-f{display:flex;flex-wrap:wrap;gap:6px}
.md-kho-f input{flex:1 1 150px;min-width:0;font:inherit;font-size:13px;padding:6px 8px;border:1px solid var(--line-soft);border-radius:8px}
.md-kho-f .md-kho-dai{flex-basis:100%}
.md-kho-b{display:flex;gap:6px;flex-wrap:wrap}
.md-kho-g{font-size:12px}
.md-kho-up{display:flex;gap:10px;align-items:center;padding:12px;border:2px dashed #c3cbd6;border-radius:10px;cursor:pointer;font-size:12.5px;color:var(--brand-ink)}
.md-kho-up:hover,.md-kho-up.on{border-color:var(--brand);background:var(--brand-weak)}
.md-kho-hd{font-size:12.5px}
.md-kho-hd summary{cursor:pointer;font-weight:600;color:var(--brand-ink)}
.md-kho-hd ol{margin:6px 0 0;padding-left:20px;display:flex;flex-direction:column;gap:4px}

/* QLDA-QN BIM: bat / tat mo hinh 3D (mac dinh chi hien diem vi tri cong trinh) */
.qd-3dbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 10px; margin: 6px 0 8px; border: 1px solid #fde68a; background:var(--warn-weak,#fffbeb); border-radius: 8px; font-size: 12.5px; }
.qd-3dbar .qd-mut { flex-basis: 100%; }
.qd .chip.qd-3d { font-weight: 600; }
.qd .chip.qd-3d.on { background: #f59e0b; border-color: #f59e0b; color: #fff; }
.qd-sw { position: relative; display: inline-flex; flex: none; margin-right: 6px; cursor: pointer; vertical-align: middle; }
.qd-sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.qd-sw i { position: relative; width: 30px; height: 17px; border-radius: 999px; background: #cbd5e1; transition: background .15s; }
.qd-sw i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: transform .15s; }
.qd-sw input:checked + i { background: #f59e0b; }
.qd-sw input:checked + i::after { transform: translateX(13px); }
.qd-sw input:focus-visible + i { outline: 2px solid #2563eb; outline-offset: 2px; }
.qd-mdl .qd-sw + b { flex: 1 1 calc(100% - 44px); }
.qd-prow { flex-wrap: wrap; } .qd-prow .qd-pm { flex: 1 1 calc(100% - 24px); } .qd-prow > .chip:first-of-type { margin-left: 17px; }

/* Street View (streetview.js): dau vi tri dung xem - nguoi vang + non huong nhin */
.wg-sv-mk { width: 40px; height: 40px; pointer-events: none; }
.wg-sv-mk .non { fill: rgba(255, 193, 7, .45); stroke: #e0a100; stroke-width: 1; }
.wg-sv-mk .nen { fill: #ffc107; stroke: #fff; stroke-width: 2; filter: drop-shadow(0 1px 2px rgba(0,0,0,.45)); }
.wg-sv-mk .ng { fill: #5d4300; }

/* Mo-dun chuc nang: phan quyen theo vai tro / nhom / nguoi dung (quan tri) */
.md-quyen{font-size:11.5px;color:var(--ink-soft);margin-top:3px;display:flex;align-items:center;gap:4px}
.md-quyen.gioi-han{color:#9a3412;font-weight:600}
.mq{display:flex;flex-direction:column;gap:12px;padding:4px 2px 8px}
.mq-h{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.mq-h h4{margin:0;font-size:15px}
.mq-note{font-size:12.5px;background:var(--warn-weak,#fff7ed);border:1px solid #fed7aa;color:#7c2d12;border-radius:10px;padding:8px 10px}
.mq-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:13px}.mq-row select{min-width:200px}.mq-row i{font-style:normal;color:var(--ink-soft);font-size:12px}
.mq-che{display:flex;flex-direction:column;gap:6px;font-size:13px}
.mq-chon{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media (max-width:720px){.mq-chon{grid-template-columns:1fr}}
.mq-col{border:1px solid var(--line,#e5e7eb);border-radius:10px;overflow:hidden;display:flex;flex-direction:column}
.mq-ct{display:flex;align-items:center;gap:8px;padding:6px 8px;background:var(--soft,#f6f7f9);border-bottom:1px solid var(--line,#e5e7eb)}.mq-ct input{flex:1;min-width:0}
.mq-ds{max-height:300px;overflow:auto;padding:4px 8px;display:flex;flex-direction:column}
.mq-ds label{display:flex;align-items:center;gap:6px;font-size:12.5px;padding:3px 0;cursor:pointer}.mq-ds label i{margin-left:auto;font-style:normal;color:var(--ink-soft);font-size:11.5px}
.mq-act{display:flex;gap:8px}

/* ==== BANG DIEU KHIEN NGUOI DUNG & PHAN QUYEN (30/10/2026): thanh trai chia nhom + Tong quan ==== */
.modal-box.ug-box{width:min(1440px,98vw);height:min(94vh,1020px)}
.ug-shell{flex:1 1 auto;min-height:0;display:flex}
.ug-nav{flex:0 0 228px;overflow-y:auto;border-right:1px solid var(--line-soft);padding:10px 8px 14px;display:flex;flex-direction:column;gap:1px;background:var(--surface)}
.ug-nav-h{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;font-weight:700;color:var(--ink-faint);padding:14px 10px 5px}
.ug-nav .ug-tab{border:0;border-radius:8px;margin:0;padding:7px 10px;width:100%;text-align:left;justify-content:flex-start;gap:9px;
  font-weight:500;font-size:13px;color:var(--ink);white-space:nowrap;border-bottom:0}
.ug-nav .ug-tab:hover{background:var(--panel)}
.ug-nav .ug-tab.is-active{background:var(--brand-weak);color:var(--brand);font-weight:600;border-bottom:0}
.ug-nav .ug-tab svg.ic{width:16px;height:16px;flex:0 0 auto;opacity:.75}
.ug-nav .ug-tab.is-active svg.ic{opacity:1}
.ug-nav .ug-tab > span:first-of-type{overflow:hidden;text-overflow:ellipsis}
.ug-nav .ug-n{margin-left:auto}
.ug-n.warn{background:#fef3c7;color:#92400e;border-color:#fcd34d}
.ug-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;overflow:hidden}
.ug-main .ug-pane:not([data-ug="users"]) > .ug-gbox{overflow-y:auto;padding-bottom:14px}
.ug-main .ug-pane > .ug-gbox > h4:first-child{margin-top:0}
.ug-foot-hint{font-size:12px}
@media (max-width:768px){
  .ug-shell{flex-direction:column}
  .ug-nav{flex:0 0 auto;flex-direction:row;overflow-x:auto;overflow-y:hidden;border-right:0;border-bottom:1px solid var(--line-soft);padding:6px;scrollbar-width:none}
  .ug-nav-h{display:none}
  .ug-nav .ug-tab{width:auto}
}
/* vai tro trong bang nguoi dung */
.ug-users{grid-template-columns:36px minmax(160px,1.1fr) 118px minmax(220px,2fr) 118px 112px 92px}
.ug-date{min-width:0;overflow:hidden}
.ug-date small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
.ug-vt{flex-basis:100%;display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}
.ug-vtchip{border:1px solid #c7d2fe;background:#eef2ff;color:#3730a3;border-radius:6px;font:inherit;font-size:11px;line-height:18px;padding:0 7px;cursor:pointer;
  max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ug-vtchip:hover{border-color:#6366f1}
.ug-vtchip.han{border-style:dashed}
.ug-vtchip.more{background:var(--surface);color:var(--ink-soft);border-color:var(--line-soft)}
/* Tong quan */
.ug-gbox > .iq,.iq > *{flex:0 0 auto}
.iq{display:flex;flex-direction:column;gap:18px}
.iq-nhom h4{margin:0 0 9px;font-size:11.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-soft);display:flex;gap:10px;align-items:center}
.iq-nhom h4 .ug-link{text-transform:none;letter-spacing:0;font-weight:600}
.iq-luoi{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px}
.iq-the{text-align:left;border:1px solid var(--line-soft);background:var(--panel);border-radius:12px;padding:12px 14px;display:flex;flex-direction:column;gap:3px;
  cursor:pointer;font:inherit;color:inherit;transition:border-color .15s,box-shadow .15s,transform .15s}
.iq-the:hover{border-color:var(--brand);box-shadow:0 4px 14px rgba(15,23,42,.08);transform:translateY(-1px)}
.iq-so{font-size:26px;font-weight:700;line-height:1.1;color:var(--ink);font-variant-numeric:tabular-nums}
.iq-nhan{font-size:13px;font-weight:600;color:var(--ink)}
.iq-phu{font-size:11.5px;color:var(--ink-faint);line-height:1.4}
.iq-the.warn{box-shadow:inset 4px 0 0 #f59e0b}.iq-the.err{box-shadow:inset 4px 0 0 var(--danger,#d93025)}.iq-the.info{box-shadow:inset 4px 0 0 #3b82f6}
.iq-the.warn .iq-so{color:#b45309}.iq-the.err .iq-so{color:var(--danger,#d93025)}
.iq-tien{cursor:default}.iq-tien:hover{transform:none;box-shadow:none;border-color:var(--line-soft)}
.iq-thanh{display:block;height:6px;border-radius:3px;background:var(--surface);overflow:hidden;margin:3px 0}
.iq-thanh b{display:block;height:100%;background:var(--ok,#16a34a);border-radius:3px}
.iq-hai{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media (max-width:900px){.iq-hai{grid-template-columns:1fr}}
@media (max-width:768px){.iq-luoi{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.iq-the{padding:10px}.iq-so{font-size:21px}}
.iq-viec{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.iq-viec button{width:100%;text-align:left;border:1px solid var(--line-soft);border-radius:10px;background:var(--panel);padding:8px 12px;font:inherit;font-size:13px;cursor:pointer;color:inherit}
.iq-viec button:hover{border-color:var(--brand)}
.iq-viec small{display:block;color:var(--ink-faint);font-size:11.5px;margin-top:1px}
.iq-viec .iq-err button{box-shadow:inset 4px 0 0 var(--danger,#d93025)}.iq-viec .iq-warn button{box-shadow:inset 4px 0 0 #f59e0b}.iq-viec .iq-info button{box-shadow:inset 4px 0 0 #3b82f6}
.iq-lop{margin:0 0 6px;padding-left:20px;font-size:12.5px;line-height:1.65}
/* khu vuc quan ly / du lieu ngoai pham vi */
.pv-tom{display:grid;grid-template-columns:1.5fr 1fr;gap:16px;background:var(--surface);border:1px solid var(--line-soft);border-radius:12px;padding:10px 14px;font-size:12.5px;line-height:1.55}
.pv-tom ul{margin:4px 0 0;padding-left:18px}
.pv-tom form{display:flex;flex-direction:column;gap:8px;justify-content:center}
@media (max-width:900px){.pv-tom{grid-template-columns:1fr}}
.td-tbl tr.is-tat{opacity:.5}
.td-nut{white-space:nowrap;text-align:right}
.pv-loc{display:flex;gap:6px;flex-wrap:wrap}
.pv-loc .chip.is-on{background:var(--brand-weak);color:var(--brand);border-color:var(--brand)}
/* lop nut rut gon (btn primary / danger / sm) dung trong cac mo-dun IAM, CDE... = btn-primary / btn-danger / btn-sm */
.btn.primary{background:var(--brand);border-color:var(--brand);color:var(--on-brand,#fff)}
.btn.primary:hover{background:var(--brand-ink);color:var(--on-brand,#fff)}
.btn.danger{background:var(--panel,#fff);border-color:var(--danger);color:var(--danger)}
.btn.danger:hover{background:var(--danger);color:#fff}
.btn.sm{padding:4px 10px;font-size:12px;min-height:28px}
