/* =============================================================================================
   ui-v4-modules.css — WorkSight v4 SPECIAL MODULES layer (SHIFT1 REVIEW ONLY). Owner: Agent 4.
   Loaded LAST. "100x visual, same structure": upgrades the EXECUTION of existing modules in place —
   same placement, same flows, same ids/handlers/semantics:
     1 Enrolment (GEN wizard capture area, stepper, status feedback, identity summary, image strip;
       queue / frames / gallery / crops modals; Employees enrol bar)
     2 Detection Log (toolbar, table density, crop framing, column menus, bulk bar, pager, mobile
       Load more / Back to live)
     3 Advanced Search (filter panel, quick ranges, action bar, results, export group)
     4 Maps (.planmap toolbar, controls, selected area, legend, overlays, heatmap)
   ONE DESIGN SYSTEM: consumes ui-v4.css tokens only (colour, radius, shadow, focus, easing, fonts).
   No hex colours, no custom shadows, no custom radii; custom properties: none defined.
   Movement Tracker (.mh-app / #mh* / .mh-* / .vx-replay*) is NOT styled here.
   ============================================================================================= */

/* ---------------------------------------------------------------------------------------------
   0. SHARED MODULE PRIMITIVES
   --------------------------------------------------------------------------------------------- */
@keyframes v4mIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@keyframes v4mSheen{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
@keyframes v4mPulse{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--v4-ok) 45%,transparent)}100%{box-shadow:0 0 0 6px transparent}}

/* ---------------------------------------------------------------------------------------------
   1. ENROLMENT
   --------------------------------------------------------------------------------------------- */
/* Employees page: enrol entry bar (injected next to "Enrol Employee"; same row, same flow). */
.v4m-enrbar{display:inline-flex;flex-wrap:wrap;gap:var(--v4-space-1);align-items:center;padding:var(--v4-space-1);border-radius:var(--v4-r-lg);
  background:var(--v4-surface-2);border:1px solid var(--v4-line)}
.v4m-enrbar .v4m-sep{display:none}
.v4m-enrbar .btn{white-space:nowrap;border:1px solid transparent!important;background:transparent!important;color:var(--v4-ink-2)!important;
  min-height:var(--v4-h);padding:var(--v4-space-1) var(--v4-space-3);border-radius:var(--v4-r);font-size:var(--v4-fs-ui);font-weight:var(--v4-fw-med);box-shadow:none!important}
.v4m-enrbar .btn:hover{background:var(--v4-surface)!important;color:var(--v4-accent)!important;border-color:var(--v4-line)!important;box-shadow:var(--v4-shadow-1)!important}
.v4m-enrbar .btn:focus-visible{outline:none;box-shadow:var(--v4-focus)!important}

/* Modals: lift above the mobile shell (z 500/540) exactly like the GEN wizard's .gen-modal (600). */
#enrollListModal,#galModal{z-index:610}
#elFramesModal,#galCropsModal{z-index:620}
.v4m-modal .modalbox{border-radius:var(--v4-r-lg);background:var(--v4-surface);border:1px solid var(--v4-line);box-shadow:var(--v4-shadow-3);
  overflow:hidden;display:flex;flex-direction:column}
.v4m-modal.open .modalbox{animation:v4mIn var(--v4-dur-slow) var(--v4-ease) both}
.v4m-modal .modalhead{flex:0 0 auto;padding:var(--v4-space-3) var(--v4-space-4);gap:var(--v4-space-3);border-bottom:1px solid var(--v4-line);
  background:linear-gradient(180deg,color-mix(in srgb,var(--v4-accent) 7%,var(--v4-surface)),var(--v4-surface))}
.v4m-modal .modalhead b{font:var(--v4-fw-semi) var(--v4-fs-lg)/1.3 var(--v4-font);color:var(--v4-ink);letter-spacing:-.01em}
.v4m-modal .modalhead .muted.sm{font-size:var(--v4-fs-sm);color:var(--v4-muted);max-width:72ch;margin-top:var(--v4-space-1)}
.v4m-modal .evicon{width:36px;height:36px;border-radius:var(--v4-r-lg);background:var(--v4-accent-soft);color:var(--v4-accent);display:grid;place-items:center}
.v4m-modal .modalhead .iconbtn,.v4m-modal .modalhead .btn{border-radius:var(--v4-r)}
.v4m-modal .modalbody{flex:1 1 auto;overflow:auto;padding:var(--v4-space-4) var(--v4-space-4);background:var(--v4-surface)}
.v4m-modal .modalbody > .muted.sm:first-child{font-size:var(--v4-fs-sm);color:var(--v4-muted);padding:0 var(--v4-space-1) var(--v4-space-2)}
.v4m-modal .modalbody > .muted.sm:only-child{padding:var(--v4-space-6);text-align:center}
.v4m-modal .tablewrap{border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);overflow:auto;max-width:100%;background:var(--v4-surface);box-shadow:var(--v4-shadow-1)}
.v4m-modal table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--v4-fs-base)}
/* queue / gallery tables carry inline inputs: keep a usable width and scroll inside their own box on phones */
.v4m-modal .tablewrap > table{min-width:780px}
.v4m-modal.v4m-ro .tablewrap > table{min-width:640px}
.v4m-modal thead th{position:sticky;top:0;z-index:1;text-align:left;font:var(--v4-fw-med) var(--v4-fs-sm)/1.3 var(--v4-font);color:var(--v4-muted);
  background:var(--v4-surface-2);padding:var(--v4-space-2) var(--v4-space-3);border-bottom:1px solid var(--v4-line);white-space:nowrap}
.v4m-modal tbody td{padding:var(--v4-space-2) var(--v4-space-3);border-bottom:1px solid var(--v4-line);vertical-align:middle;color:var(--v4-ink);
  transition:background-color var(--v4-dur-fast) ease}
.v4m-modal tbody tr:last-child td{border-bottom:0}
.v4m-modal tbody tr:hover td{background:var(--v4-hover)}
/* inherited log-table ellipsis clipped the Actions cell (Save / Repush / Delete) — let modal cells size to content */
.v4m-modal thead th,.v4m-modal tbody td{max-width:none;overflow:visible;text-overflow:clip}
.v4m-modal tbody td:last-child{white-space:nowrap}
.v4m-modal tbody td:last-child .btn + .btn{margin-left:var(--v4-space-1)}
.v4m-modal .galinp{border:1px solid var(--v4-line-strong);background:var(--v4-surface);color:var(--v4-ink);
  border-radius:var(--v4-r);padding:var(--v4-space-1) var(--v4-space-2);font:inherit;font-size:var(--v4-fs-base);min-height:var(--v4-h);transition:border-color var(--v4-dur-fast) ease,box-shadow var(--v4-dur-fast) ease}
.v4m-modal .galinp:hover{border-color:var(--v4-ink-3)}
.v4m-modal .galinp:focus{border-color:var(--v4-accent);box-shadow:var(--v4-focus);outline:none}
.v4m-modal .galinp.mono{font-family:var(--v4-mono);font-size:var(--v4-fs-ui)}
.v4m-modal .galinp[readonly]{background:transparent;border-color:transparent;padding-left:0;cursor:default;box-shadow:none}
.v4m-modal .tag{border-radius:var(--v4-r);font:var(--v4-fw-med) var(--v4-fs-meta)/1.35 var(--v4-font);padding:var(--v4-space-1) var(--v4-space-2)}
.v4m-modal .btn.sm{min-height:var(--v4-h);padding:var(--v4-space-1) var(--v4-space-2);font-size:var(--v4-fs-ui)}
.v4m-modal .btn svg{width:14px;height:14px}
.v4m-modal .btn.ghost.sm[data-elframes]{font-family:var(--v4-mono);gap:var(--v4-space-1)}
.v4m-modal .empty{color:var(--v4-muted);padding:var(--v4-space-8) var(--v4-space-4)!important;border:1px dashed var(--v4-line-strong);border-radius:var(--v4-r-lg);background:var(--v4-surface-2)}
.v4m-modal .callout{border:1px solid var(--v4-line);background:var(--v4-surface-2);border-radius:var(--v4-r-lg);padding:var(--v4-space-2) var(--v4-space-3);margin-bottom:var(--v4-space-3)!important}
/* frame / crop grids — image selection tiles (inline-styled grid; tile treatment only) */
.v4m-modal .modalbody div[style*="grid-template-columns"]{gap:var(--v4-space-3)!important}
.v4m-modal .modalbody div[style*="grid-template-columns"] > div{border:1px solid var(--v4-line)!important;border-radius:var(--v4-r-lg)!important;
  background:var(--v4-surface)!important;box-shadow:var(--v4-shadow-1);overflow:hidden;
  transition:transform var(--v4-dur) var(--v4-ease),box-shadow var(--v4-dur) var(--v4-ease),border-color var(--v4-dur) ease}
.v4m-modal .modalbody div[style*="grid-template-columns"] > div:hover{transform:translateY(-2px);box-shadow:var(--v4-shadow-2);border-color:var(--v4-line-strong)!important}
.v4m-modal .modalbody div[style*="grid-template-columns"] img{background:var(--v4-surface-3);transition:transform var(--v4-dur-slow) var(--v4-ease)}
.v4m-modal .modalbody div[style*="grid-template-columns"] > div:hover img{transform:scale(1.03)}
.v4m-modal .modalbody div[style*="grid-template-columns"] .sm{padding:var(--v4-space-2) var(--v4-space-2)!important;border-top:1px solid var(--v4-line)}
.v4m-modal .efdel,.v4m-modal [data-cropdel]{background:var(--v4-crit)!important;color:var(--v4-accent-ink)!important;border:2px solid var(--v4-surface)!important;
  box-shadow:var(--v4-shadow-2)!important;opacity:.92;transition:transform var(--v4-dur-fast) var(--v4-ease),opacity var(--v4-dur-fast) ease}
.v4m-modal .efdel:hover,.v4m-modal [data-cropdel]:hover{opacity:1;transform:scale(1.08)}
/* read-only (no enroll:manage): the Actions column carries nothing — drop it. */
.v4m-modal.v4m-ro .tablewrap th:last-child,.v4m-modal.v4m-ro .tablewrap td:last-child{display:none}

/* GEN wizard (.gen-v2) — capture logic untouched; presentation only. */
.gen-modal .gen-v2{border-radius:var(--v4-r-lg);background:var(--v4-surface);border:1px solid var(--v4-line);box-shadow:var(--v4-shadow-3);
  animation:v4mIn var(--v4-dur-slow) var(--v4-ease) both}
.gen-v2 .genv2-head{padding:var(--v4-space-3) var(--v4-space-4);background:linear-gradient(180deg,color-mix(in srgb,var(--v4-accent) 8%,var(--v4-surface)),var(--v4-surface));
  border-bottom:1px solid var(--v4-line)}
.gen-v2 .genv2-logo{width:40px;height:40px;border-radius:var(--v4-r-lg);background:var(--v4-accent);color:var(--v4-accent-ink);box-shadow:var(--v4-shadow-1)}
.gen-v2 .genv2-htxt b{font:var(--v4-fw-semi) var(--v4-fs-title)/1.3 var(--v4-font);letter-spacing:-.01em;color:var(--v4-ink)}
.gen-v2 .genv2-htxt span{color:var(--v4-muted);font-size:var(--v4-fs-ui)}
.gen-v2 .genv2-pill{border:1px solid var(--v4-line);background:var(--v4-surface);color:var(--v4-ink-2);font:var(--v4-fw-med) var(--v4-fs-sm)/1 var(--v4-font);border-radius:var(--v4-r-lg);padding:var(--v4-space-2) var(--v4-space-3)}
.gen-v2 .genv2-dot{background:var(--v4-ink-3)}
.gen-v2 .genv2-dot.on{background:var(--v4-ok);animation:v4mPulse 1.8s ease-out infinite}
.gen-v2 .genv2-x{border-radius:var(--v4-r);border:1px solid var(--v4-line);background:var(--v4-surface);color:var(--v4-ink-2);transition:background-color var(--v4-dur-fast) ease,color var(--v4-dur-fast) ease}
.gen-v2 .genv2-x:hover{color:var(--v4-ink);background:var(--v4-surface-2)}
.gen-v2 .genv2-main{padding:var(--v4-space-4) var(--v4-space-5)}
.gen-v2 .genv2-side{padding:var(--v4-space-4) var(--v4-space-5);background:var(--v4-surface-2);border-left:1px solid var(--v4-line)}
/* progress */
.gen-v2 .genv2-progressline b{font:var(--v4-fw-semi) var(--v4-fs-ui)/1.3 var(--v4-font);color:var(--v4-ink)}
.gen-v2 .genv2-progressline span{font-family:var(--v4-mono);font-size:var(--v4-fs-sm);color:var(--v4-muted)}
.gen-v2 .genv2-progressbar{height:8px;background:var(--v4-surface-3);border:1px solid var(--v4-line);position:relative}
.gen-v2 .genv2-progressbar i{background:var(--v4-accent);position:relative;overflow:hidden;transition:width var(--v4-dur-slow) var(--v4-ease)}
.gen-v2 .genv2-progressbar i::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--v4-accent-ink) 35%,transparent),transparent);animation:v4mSheen 1.8s ease-in-out infinite}
/* capture area */
.gen-v2 .genv2-stage{border-radius:var(--v4-r-lg);border:1px solid var(--v4-line-strong);box-shadow:var(--v4-shadow-2)}
.gen-v2 .genv2-stage::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;border-radius:inherit;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--v4-accent) 18%,transparent)}
.gen-v2 .genv2-faceguide{border-color:var(--v4-accent-2);box-shadow:0 0 0 999px color-mix(in srgb,var(--v4-scrim) 55%,transparent),0 0 32px color-mix(in srgb,var(--v4-accent) 35%,transparent);
  transition:border-color var(--v4-dur) ease}
.gen-v2 .genv2-faceguide.done{border-color:var(--v4-ok)}
.gen-v2 .genv2-corner{border-color:var(--v4-accent-2);opacity:.95}
.gen-v2 .genv2-scanline{background:linear-gradient(90deg,transparent,var(--v4-accent-2),transparent)}
.gen-v2 .genv2-badge{border-radius:var(--v4-r-lg);font:var(--v4-fw-med) var(--v4-fs-meta)/1.2 var(--v4-font)}
/* pose guidance card */
.gen-v2 .genv2-posecard{border-radius:var(--v4-r-lg);border:1px solid var(--v4-line);background:var(--v4-surface);box-shadow:var(--v4-shadow-1);
  border-left:3px solid var(--v4-accent)}
.gen-v2 .genv2-posecard h2{font:var(--v4-fw-semi) var(--v4-fs-title)/1.3 var(--v4-font);letter-spacing:-.01em;color:var(--v4-ink)}
.gen-v2 .genv2-posecard p{color:var(--v4-ink-2);font-size:var(--v4-fs-ui)}
.gen-v2 .genv2-count{border-radius:var(--v4-r-lg);background:var(--v4-accent-soft);border:1px solid color-mix(in srgb,var(--v4-accent) 25%,var(--v4-line))}
.gen-v2 .genv2-count strong{font:var(--v4-fw-semi) var(--v4-fs-kpi-sm)/1 var(--v4-mono);color:var(--v4-accent)}
.gen-v2 .genv2-count span{color:var(--v4-ink-2);font-size:var(--v4-fs-xs)}
/* live signal tiles */
.gen-v2 .genv2-metrics{gap:var(--v4-space-2)}
.gen-v2 .genv2-metric{border-radius:var(--v4-r-lg);background:var(--v4-surface);border:1px solid var(--v4-line);padding:var(--v4-space-2) var(--v4-space-3);position:relative;
  transition:background-color var(--v4-dur) ease,border-color var(--v4-dur) ease}
.gen-v2 .genv2-metric span{color:var(--v4-muted);letter-spacing:.06em;font:var(--v4-fw-med) var(--v4-fs-xs)/1.2 var(--v4-font);text-transform:uppercase}
.gen-v2 .genv2-metric b{color:var(--v4-ink);font:var(--v4-fw-semi) var(--v4-fs-nav)/1.3 var(--v4-font)}
.gen-v2 .genv2-metric.good{border-color:color-mix(in srgb,var(--v4-ok) 40%,var(--v4-line));background:var(--v4-ok-soft)}
.gen-v2 .genv2-metric.good b{color:var(--v4-ok-ink)}
.gen-v2 .genv2-metric.good::after{content:"";position:absolute;top:9px;right:10px;width:7px;height:7px;border-radius:50%;background:var(--v4-ok)}
/* actions */
.gen-v2 .genv2-actions{gap:var(--v4-space-2)}
.gen-v2 .genv2-btn{border-radius:var(--v4-r);font:var(--v4-fw-semi) var(--v4-fs-base)/1.2 var(--v4-font);min-height:var(--v4-h-lg);padding:var(--v4-space-2) var(--v4-space-4);
  transition:transform var(--v4-dur-fast) var(--v4-ease),box-shadow var(--v4-dur-fast) var(--v4-ease),background-color var(--v4-dur-fast) ease,border-color var(--v4-dur-fast) ease}
.gen-v2 .genv2-btn.primary{background:var(--v4-accent);color:var(--v4-accent-ink);box-shadow:var(--v4-shadow-1)}
.gen-v2 .genv2-btn.primary:hover{background:var(--v4-accent-2);transform:translateY(-1px);box-shadow:var(--v4-shadow-2)}
.gen-v2 .genv2-btn.primary:disabled{opacity:.5;transform:none;box-shadow:none;cursor:not-allowed}
.gen-v2 .genv2-btn.secondary{border:1px solid var(--v4-line-strong);background:var(--v4-surface);color:var(--v4-ink)}
.gen-v2 .genv2-btn.secondary:hover{background:var(--v4-surface-2);transform:translateY(-1px)}
.gen-v2 .genv2-btn.ghost{color:var(--v4-ink-2)}
.gen-v2 .genv2-btn.ghost:hover{color:var(--v4-crit-ink)}
.gen-v2 .genv2-btn:focus-visible{outline:none;box-shadow:var(--v4-focus)}
/* stepper (Capture coverage) — vertical, with connector */
.gen-v2 .genv2-sidehead h3{font:var(--v4-fw-semi) var(--v4-fs-md)/1.3 var(--v4-font);color:var(--v4-ink)}
.gen-v2 .genv2-sidehead p{color:var(--v4-muted);font-size:var(--v4-fs-sm)}
.gen-v2 .genv2-coverage{gap:var(--v4-space-1);position:relative}
.gen-v2 .genv2-step{position:relative;border-radius:var(--v4-r-lg);border:1px solid var(--v4-line);background:var(--v4-surface);padding:var(--v4-space-2) var(--v4-space-2);
  transition:border-color var(--v4-dur) ease,background-color var(--v4-dur) ease,box-shadow var(--v4-dur) ease}
.gen-v2 .genv2-step + .genv2-step::before{content:"";position:absolute;left:27px;top:-7px;width:2px;height:6px;background:var(--v4-line-strong)}
.gen-v2 .genv2-step.done + .genv2-step::before{background:var(--v4-ok)}
.gen-v2 .genv2-step.on{border-color:var(--v4-accent);background:var(--v4-accent-soft);box-shadow:var(--v4-shadow-1)}
.gen-v2 .genv2-step.done{border-color:color-mix(in srgb,var(--v4-ok) 45%,var(--v4-line))}
.gen-v2 .genv2-n{border-radius:var(--v4-r-lg);background:var(--v4-surface-3);color:var(--v4-ink-2);font:var(--v4-fw-semi) var(--v4-fs-base)/1 var(--v4-mono)}
.gen-v2 .genv2-step.on .genv2-n{background:var(--v4-accent);color:var(--v4-accent-ink)}
.gen-v2 .genv2-step.done .genv2-n{background:var(--v4-ok-soft);color:var(--v4-ok-ink)}
.gen-v2 .genv2-step b{color:var(--v4-ink);font:var(--v4-fw-semi) var(--v4-fs-base)/1.3 var(--v4-font)}
.gen-v2 .genv2-step small{color:var(--v4-muted);font-size:var(--v4-fs-meta)}
.gen-v2 .genv2-state{font:var(--v4-fw-semi) var(--v4-fs-xs)/1 var(--v4-font);letter-spacing:.04em;color:var(--v4-ink-3);padding:var(--v4-space-1) var(--v4-space-2);border-radius:var(--v4-r);background:var(--v4-surface-2)}
.gen-v2 .genv2-step.on .genv2-state{color:var(--v4-accent);background:var(--v4-surface)}
.gen-v2 .genv2-step.done .genv2-state{color:var(--v4-ok-ink);background:var(--v4-ok-soft)}
/* captured image strip (7:9 frames, numbered) */
.gen-v2 .genv2-strip{counter-reset:v4mpose;gap:var(--v4-space-2)}
.gen-v2 .genv2-strip .gen-dot{counter-increment:v4mpose;border-radius:var(--v4-r);background:var(--v4-surface-3);border:1px solid var(--v4-line);
  transition:border-color var(--v4-dur) ease,box-shadow var(--v4-dur) ease}
.gen-v2 .genv2-strip .gen-dot::before{content:counter(v4mpose);position:absolute;left:4px;bottom:4px;z-index:1;font:var(--v4-fw-semi) var(--v4-fs-xs)/1 var(--v4-mono);
  color:var(--v4-ink-2);background:var(--v4-surface);border-radius:var(--v4-r);padding:var(--v4-space-1) var(--v4-space-1);box-shadow:var(--v4-shadow-1)}
.gen-v2 .genv2-strip .gen-dot.cur{border-color:var(--v4-accent);box-shadow:var(--v4-focus)}
.gen-v2 .genv2-strip .gen-dot.done{border-color:var(--v4-ok)}
.gen-v2 .genv2-strip .gen-dot.done::before{color:var(--v4-ok-ink);background:var(--v4-ok-soft)}
/* identity summary */
.gen-v2 .genv2-identity{margin-top:var(--v4-space-4);padding:var(--v4-space-3);border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);background:var(--v4-surface);box-shadow:var(--v4-shadow-1)}
.gen-v2 .genv2-sectionTitle b{color:var(--v4-ink);font:var(--v4-fw-semi) var(--v4-fs-base)/1.3 var(--v4-font)}
.gen-v2 .genv2-sectionTitle span{color:var(--v4-muted);font-size:var(--v4-fs-meta);padding:var(--v4-space-1) var(--v4-space-2);border-radius:var(--v4-r);background:var(--v4-surface-2)}
.gen-v2 .genv2-identity label{color:var(--v4-ink-2);font:var(--v4-fw-med) var(--v4-fs-meta)/1.3 var(--v4-font);letter-spacing:.02em;text-transform:none}
.gen-v2 .genv2-input{border-radius:var(--v4-r);border:1px solid var(--v4-line-strong);background:var(--v4-surface);color:var(--v4-ink);min-height:var(--v4-h-lg);font-size:var(--v4-fs-nav);
  transition:border-color var(--v4-dur-fast) ease,box-shadow var(--v4-dur-fast) ease}
.gen-v2 .genv2-input:hover{border-color:var(--v4-ink-3)}
.gen-v2 .genv2-input:focus{border-color:var(--v4-accent);box-shadow:var(--v4-focus)}
.gen-v2 .genv2-helper{border-radius:var(--v4-r-lg);border:1px dashed var(--v4-line-strong);color:var(--v4-ink-2);background:var(--v4-surface-2);font-size:var(--v4-fs-sm)}
/* validation / success / failure */
.gen-v2 .gen-status:not(:empty){margin-top:var(--v4-space-2);padding:var(--v4-space-2) var(--v4-space-3);border-radius:var(--v4-r-lg);font:var(--v4-fw-med) var(--v4-fs-ui)/1.4 var(--v4-font);
  border:1px solid var(--v4-line);background:var(--v4-surface-2);color:var(--v4-ink-2);animation:v4mIn var(--v4-dur) var(--v4-ease) both}
.gen-v2 .gen-status.ok:not(:empty){background:var(--v4-ok-soft);color:var(--v4-ok-ink);border-color:color-mix(in srgb,var(--v4-ok) 40%,transparent)}
.gen-v2 .gen-status.err:not(:empty){background:var(--v4-crit-soft);color:var(--v4-crit-ink);border-color:color-mix(in srgb,var(--v4-crit) 40%,transparent)}

/* ---------------------------------------------------------------------------------------------
   2. DETECTION LOG (app.js detections()/hydrateDetections — semantics untouched)
   --------------------------------------------------------------------------------------------- */
/* toolbar: title block left, controls right in one grouped surface */
#view .card:has(#detRows) > .head{align-items:center;gap:var(--v4-space-3);flex-wrap:wrap;padding-bottom:var(--v4-space-3);margin-bottom:var(--v4-space-3);border-bottom:1px solid var(--v4-line)}
#view .card:has(#detRows) > .head h3{font:var(--v4-fw-semi) var(--v4-fs-lg)/1.3 var(--v4-font);letter-spacing:-.01em;text-transform:none;color:var(--v4-ink)}
#view .card:has(#detRows) > .head #detCount{display:inline-block;margin-top:var(--v4-space-1);font:var(--v4-fw-med) var(--v4-fs-sm)/1.3 var(--v4-font);color:var(--v4-muted)}
#view .card:has(#detRows) > .head .right{gap:var(--v4-space-1);padding:var(--v4-space-1);border-radius:var(--v4-r-lg);background:var(--v4-surface);border:1px solid var(--v4-line);box-shadow:var(--v4-shadow-1)}
#view .card:has(#detRows) > .head select{min-height:var(--v4-h);padding:var(--v4-space-1) var(--v4-space-6) var(--v4-space-1) var(--v4-space-2);font-size:var(--v4-fs-base);border-radius:var(--v4-r)}
#view .card:has(#detRows) > .head .btn{min-height:var(--v4-h);border-radius:var(--v4-r)}
#view .card:has(#detRows) .detshow{display:inline-flex;align-items:center;gap:var(--v4-space-1);font-size:var(--v4-fs-ui);color:var(--v4-ink-2);padding-left:var(--v4-space-1)}
/* table: sticky header in a bounded scroll box; reference density */
#view .tablewrap:has(> table > #detRows){max-height:min(72vh,820px);overflow:auto;overscroll-behavior:auto;box-shadow:var(--v4-shadow-1)}
#detHead th{position:sticky;top:0;z-index:2;background:var(--v4-surface-2);box-shadow:inset 0 -1px 0 var(--v4-line);
  padding:var(--v4-space-2) var(--v4-space-2);white-space:nowrap;font:var(--v4-fw-med) var(--v4-fs-sm)/1.3 var(--v4-font);letter-spacing:0;text-transform:none;color:var(--v4-muted)}
#detHead .thlbl{vertical-align:middle}
#detRows td{padding:var(--v4-space-2) var(--v4-space-2);vertical-align:middle;border-bottom:1px solid var(--v4-line);transition:background-color var(--v4-dur-fast) ease}
#detRows tr{position:relative}
#detRows tr:hover td{background:var(--v4-hover)}
#detRows tr:hover td:first-child{box-shadow:inset 3px 0 0 var(--v4-accent)}
#detRows tr:has(.detsel:checked) td{background:var(--v4-selected)}
#detRows td.mono,#detRows .mono{font-family:var(--v4-mono);font-size:var(--v4-fs-ui)}
#detRows td b{font-weight:var(--v4-fw-semi);color:var(--v4-ink)}
#detRows .asmatch{color:var(--v4-ok-ink);font-weight:var(--v4-fw-semi)}
#detRows td:last-child .tag.ok{border-radius:var(--v4-r)}
/* crop framing: 7:9 portrait with a hairline ring, depth and a hover lift */
#detRows td > div[style*="width:52px"]{border-radius:var(--v4-r-lg)!important;overflow:hidden;background:var(--v4-surface-3)!important;
  box-shadow:0 0 0 1px var(--v4-line),var(--v4-shadow-1);transition:transform var(--v4-dur) var(--v4-ease),box-shadow var(--v4-dur) var(--v4-ease)}
#detRows td > div[style*="width:52px"] img{border-radius:0!important}
#detRows tr:hover td > div[style*="width:52px"]{transform:translateY(-1px);box-shadow:0 0 0 1px var(--v4-accent),var(--v4-shadow-2)}
/* column filter funnels + popover */
#detHead .colf{margin-left:var(--v4-space-1);border:0;background:transparent;color:var(--v4-ink-3);border-radius:var(--v4-r);padding:var(--v4-space-1) var(--v4-space-1);cursor:pointer;vertical-align:middle;
  transition:color var(--v4-dur-fast) ease,background-color var(--v4-dur-fast) ease}
#detHead .colf:hover{color:var(--v4-ink);background:var(--v4-surface-3)}
#detHead .colf.on{color:var(--v4-accent-ink);background:var(--v4-accent)}
#detHead .colf:focus-visible{outline:none;box-shadow:var(--v4-focus)}
.colmenu{background:var(--v4-surface);border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);box-shadow:var(--v4-shadow-3);color:var(--v4-ink);padding:var(--v4-space-3);
  animation:v4mIn var(--v4-dur) var(--v4-ease) both}
.colmenu .colmh{color:var(--v4-muted);font:var(--v4-fw-semi) var(--v4-fs-xs)/1.3 var(--v4-font);letter-spacing:.05em}
.colmenu .colcb{border-radius:var(--v4-r);padding:var(--v4-space-1) var(--v4-space-2);transition:background-color var(--v4-dur-fast) ease}
.colmenu .colcb:hover{background:var(--v4-hover)}
.colmenu .colcb:has(input:checked){background:var(--v4-accent-soft);color:var(--v4-accent)}
.colmenu .colmq,.colmenu .colml input{border:1px solid var(--v4-line-strong);border-radius:var(--v4-r);background:var(--v4-surface);color:var(--v4-ink);min-height:var(--v4-h)}
.colmenu .colmq:focus,.colmenu .colml input:focus{border-color:var(--v4-accent);box-shadow:var(--v4-focus);outline:none}
.colmenu .colmft{padding-top:var(--v4-space-2);border-top:1px solid var(--v4-line)}
.colmenu .btn{border-radius:var(--v4-r);border:1px solid var(--v4-line-strong);background:var(--v4-surface);color:var(--v4-ink);min-height:var(--v4-h)}
.colmenu .btn.primary{background:var(--v4-accent);border-color:var(--v4-accent);color:var(--v4-accent-ink)}
.actmenu{background:var(--v4-surface);border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);box-shadow:var(--v4-shadow-3);color:var(--v4-ink)}
.actmenu button{border-radius:var(--v4-r);color:var(--v4-ink)}
.actmenu button:hover{background:var(--v4-hover)}
.actmenu button.danger{color:var(--v4-crit-ink)}
/* bulk-selection bar */
.detbulk{border:1px solid color-mix(in srgb,var(--v4-crit) 35%,var(--v4-line));background:var(--v4-crit-soft);border-radius:var(--v4-r-lg);padding:var(--v4-space-2) var(--v4-space-3);
  animation:v4mIn var(--v4-dur) var(--v4-ease) both}
.detbulk-n{color:var(--v4-crit-ink)}
/* pager (Detection Log, Search, Employees) */
.detfoot,.attfoot{border-top:1px solid var(--v4-line)}
.detfoot .aspg,.attfoot .aspg{min-width:var(--v4-h);height:var(--v4-h);border-radius:var(--v4-r);border:1px solid var(--v4-line);background:var(--v4-surface);color:var(--v4-ink);
  font:var(--v4-fw-med) var(--v4-fs-ui)/1 var(--v4-font);transition:background-color var(--v4-dur-fast) ease,border-color var(--v4-dur-fast) ease,transform var(--v4-dur-fast) var(--v4-ease)}
.detfoot .aspg:hover:not(:disabled),.attfoot .aspg:hover:not(:disabled){background:var(--v4-surface-2);border-color:var(--v4-line-strong);transform:translateY(-1px)}
.detfoot .aspg.on,.attfoot .aspg.on{background:var(--v4-accent);border-color:var(--v4-accent);color:var(--v4-accent-ink);font-weight:var(--v4-fw-semi);box-shadow:var(--v4-shadow-1)}
.detfoot .aspg:focus-visible,.attfoot .aspg:focus-visible{outline:none;box-shadow:var(--v4-focus)}
.detgo{color:var(--v4-muted)}
.detgo input{border-radius:var(--v4-r);border:1px solid var(--v4-line-strong);background:var(--v4-surface);color:var(--v4-ink);min-height:var(--v4-h)}
/* person history "Load more" row inside the log */
tr[data-phmore] td{background:var(--v4-surface-2)!important;color:var(--v4-muted);font-size:var(--v4-fs-sm);text-align:center}
/* mobile Detection Log (mScreenDetections): filter bar, cards, Load more / Back to live */
.mdet-filters{display:grid;grid-template-columns:1fr 1fr;gap:var(--v4-space-2);margin-bottom:var(--v4-space-2);padding:var(--v4-space-2);border:1px solid var(--v4-line);
  border-radius:var(--v4-r-lg);background:var(--v4-surface);box-shadow:var(--v4-shadow-1)}
.mdet-filters #mdetQ{grid-column:1/-1}
.mdet-filters input,.mdet-filters select{min-width:0;width:100%;min-height:var(--v4-h-lg);border:1px solid var(--v4-line-strong);border-radius:var(--v4-r);
  background:var(--v4-surface);color:var(--v4-ink);padding:var(--v4-space-1) var(--v4-space-2);font:inherit;font-size:var(--v4-fs-nav)}
.mdet-filters input:focus,.mdet-filters select:focus{border-color:var(--v4-accent);box-shadow:var(--v4-focus);outline:none}
.mdet-note{display:flex;align-items:center;justify-content:space-between;gap:var(--v4-space-2);flex-wrap:wrap;font-size:var(--v4-fs-ui);color:var(--v4-ink-2);background:var(--v4-surface-2);
  border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);padding:var(--v4-space-2) var(--v4-space-3);margin-bottom:var(--v4-space-2)}
.mdet-note.live{color:var(--v4-ok-ink);background:var(--v4-ok-soft);border-color:transparent;justify-content:flex-start}
.mdet-note.live::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--v4-ok);animation:v4mPulse 1.8s ease-out infinite}
.mdet-card{background:var(--v4-surface);border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);box-shadow:var(--v4-shadow-1);transition:border-color var(--v4-dur-fast) ease}
.mdet-card:active{border-color:var(--v4-accent)}
.mdet-img{border-radius:var(--v4-r);box-shadow:0 0 0 1px var(--v4-line)}
.mdet-name{color:var(--v4-ink);font-weight:var(--v4-fw-semi)}
.mdet-time,.mdet-meta{color:var(--v4-muted)}
#mdetMore,#mdetLive,.mdet-more,[data-phmore-btn]{display:inline-flex;align-items:center;justify-content:center;gap:var(--v4-space-1);border:1px solid var(--v4-line-strong);
  border-radius:var(--v4-r);background:var(--v4-surface);color:var(--v4-accent);font:var(--v4-fw-semi) var(--v4-fs-ui)/1.2 var(--v4-font);min-height:var(--v4-h);padding:var(--v4-space-1) var(--v4-space-3);cursor:pointer;
  box-shadow:var(--v4-shadow-1);transition:background-color var(--v4-dur-fast) ease,border-color var(--v4-dur-fast) ease,transform var(--v4-dur-fast) var(--v4-ease)}
#mdetMore:hover,#mdetLive:hover,[data-phmore-btn]:hover{background:var(--v4-accent-soft);border-color:var(--v4-accent);transform:translateY(-1px)}
#mdetLive::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--v4-ok)}
#mdetMore{width:100%;margin-top:var(--v4-space-2);min-height:var(--v4-h-lg)}

/* ---------------------------------------------------------------------------------------------
   3. ADVANCED SEARCH (ui-v3 searchV3 + app.js asCollect/asQS/runSearch — semantics untouched)
   --------------------------------------------------------------------------------------------- */
#srV3 .srcard > .head{padding-bottom:var(--v4-space-3);border-bottom:1px solid var(--v4-line)}
#srV3 .srcard > .head h3{font:var(--v4-fw-semi) var(--v4-fs-lg)/1.3 var(--v4-font);letter-spacing:-.01em}
#srV3 .srtop{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr);gap:var(--v4-space-3);padding-top:var(--v4-space-4)}
#srV3 .srchips{display:flex;flex-wrap:wrap;align-items:center;gap:var(--v4-space-1);padding-top:var(--v4-space-3)}
#srV3 .srsel{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:var(--v4-space-3);margin-top:var(--v4-space-4);padding:var(--v4-space-3);
  border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);background:var(--v4-surface-2)}
#srV3 .srf{display:flex;flex-direction:column;gap:var(--v4-space-1);min-width:0}
#srV3 .srf > span{font:var(--v4-fw-med) var(--v4-fs-sm)/1.3 var(--v4-font);color:var(--v4-ink-2)}
#srV3 .srf input,#srV3 .srf select{width:100%;min-width:0;min-height:var(--v4-h-lg);font-size:var(--v4-fs-base);border-radius:var(--v4-r);background-color:var(--v4-surface);
  transition:border-color var(--v4-dur-fast) ease,box-shadow var(--v4-dur-fast) ease}
#srV3 .srf input:hover,#srV3 .srf select:hover{border-color:var(--v4-ink-3)}
/* a filter that is set reads as "active" (accent hairline) */
#srV3 .srf select:has(option:checked:not([value=""])),#srV3 .srf input#asPerson:not(:placeholder-shown){border-color:var(--v4-accent);box-shadow:inset 3px 0 0 var(--v4-accent)}
#srV3 .srchips .srchl{font:var(--v4-fw-med) var(--v4-fs-sm)/1.3 var(--v4-font);color:var(--v4-muted);margin-right:var(--v4-space-1)}
#srV3 .srchips .chip{border:1px solid var(--v4-line);background:var(--v4-surface);border-radius:var(--v4-r-lg);padding:var(--v4-space-1) var(--v4-space-3);font-size:var(--v4-fs-ui);font-weight:var(--v4-fw-med);
  color:var(--v4-ink-2);cursor:pointer;transition:border-color var(--v4-dur-fast) ease,color var(--v4-dur-fast) ease,background-color var(--v4-dur-fast) ease,transform var(--v4-dur-fast) var(--v4-ease)}
#srV3 .srchips .chip:hover{border-color:var(--v4-accent);color:var(--v4-accent);transform:translateY(-1px)}
#srV3 .srchips .chip.on{background:var(--v4-accent-soft);border-color:var(--v4-accent);color:var(--v4-accent);font-weight:var(--v4-fw-semi)}
#srV3 .srchips .chip:focus-visible{outline:none;box-shadow:var(--v4-focus)}
/* action bar */
#srV3 .srbtns{display:flex;justify-content:flex-end;gap:var(--v4-space-2);margin-top:var(--v4-space-4);padding-top:var(--v4-space-3);flex-wrap:wrap;border-top:1px solid var(--v4-line)}
#srV3 .srbtns .btn{min-height:var(--v4-h-lg);padding:var(--v4-space-2) var(--v4-space-4)}
/* results */
#asResults > .head{display:flex;align-items:center;justify-content:space-between;gap:var(--v4-space-2);flex-wrap:wrap;padding-bottom:var(--v4-space-3);margin-bottom:var(--v4-space-3);border-bottom:1px solid var(--v4-line)}
#asResults > .head h3{font:var(--v4-fw-semi) var(--v4-fs-lg)/1.3 var(--v4-font);font-variant-numeric:tabular-nums}
/* export menu = one joined button group */
#asResults > .head .tools{display:inline-flex;gap:0;flex-wrap:wrap;border:1px solid var(--v4-line-strong);border-radius:var(--v4-r);background:var(--v4-surface);
  box-shadow:var(--v4-shadow-1);overflow:hidden}
#asResults > .head .tools .btn{border:0!important;border-radius:0!important;min-height:var(--v4-h);padding:var(--v4-space-1) var(--v4-space-3);background:transparent;box-shadow:none!important;transform:none!important;
  color:var(--v4-ink-2);font-size:var(--v4-fs-ui)}
#asResults > .head .tools .btn + .btn{border-left:1px solid var(--v4-line)!important}
#asResults > .head .tools .btn:hover{background:var(--v4-hover);color:var(--v4-accent)}
#asResults > .head .tools .btn[data-mh]{color:var(--v4-accent);font-weight:var(--v4-fw-semi)}
#asResults > .tablewrap{max-height:min(70vh,780px);overflow:auto;overscroll-behavior:auto;box-shadow:var(--v4-shadow-1)}
#asResults thead th{position:sticky;top:0;z-index:2;background:var(--v4-surface-2);box-shadow:inset 0 -1px 0 var(--v4-line);padding:var(--v4-space-2) var(--v4-space-2);white-space:nowrap}
#asResults tbody td{padding:var(--v4-space-2) var(--v4-space-2);vertical-align:middle;transition:background-color var(--v4-dur-fast) ease}
#asResults tbody tr[data-asrow]{cursor:pointer}
#asResults tbody tr[data-asrow]:hover td{background:var(--v4-hover)}
#asResults tbody tr[data-asrow]:hover td:first-child{box-shadow:inset 3px 0 0 var(--v4-accent)}
#asResults .wsav{box-shadow:0 0 0 1px var(--v4-line),var(--v4-shadow-1);border-radius:var(--v4-r-lg);transition:transform var(--v4-dur) var(--v4-ease)}
#asResults tr[data-asrow]:hover .wsav{transform:translateY(-1px)}
#asResults > .empty{padding:var(--v4-space-8) var(--v4-space-4);text-align:center;color:var(--v4-muted);border:1px dashed var(--v4-line-strong);border-radius:var(--v4-r-lg);background:var(--v4-surface-2)}
@media (max-width:760px){
  #srV3 .srtop{grid-template-columns:1fr 1fr}
  #srV3 .srtop .srf-w{grid-column:1/-1}
  #srV3 .srchips{flex-wrap:nowrap;overflow-x:auto}
  #srV3 .srsel{grid-template-columns:1fr 1fr;padding:var(--v4-space-2)}
  #srV3 .srbtns .btn{flex:1}
}
@media (max-width:420px){ #srV3 .srtop,#srV3 .srsel{grid-template-columns:1fr} }

/* ---------------------------------------------------------------------------------------------
   4. MAPS — office/floor plan (.planmap, officeMapV3) + hourly footfall heatmap (.heat, liveHeatmap)
   Engines untouched; toolbar, controls, selected area, legend, overlays and surfaces only.
   --------------------------------------------------------------------------------------------- */
/* Plan must fill its card exactly like production (web-v2 #command: svg 611x384 in a 633x437 frame).
   The card height is fixed by its grid row, so nothing may steal vertical space from the SVG: the toolbar
   stays flush (no extra padding/margin) and the legend OVERLAYS the plan's bottom edge instead of adding a row. */
.v3 .planmap{position:relative;background:var(--v4-surface-2);border:1px solid var(--v4-line);
  border-radius:var(--v4-r-lg);padding:var(--v4-space-2);max-width:100%;min-width:0;overflow:hidden}
.v3 .planmap svg{max-width:100%;height:auto}
/* toolbar: two segmented controls, flush (same footprint as production's .mapbar) */
.v3 .planmap .mapbar{margin:0 0 var(--v4-space-2);padding:0;background:none;border:0;box-shadow:none}
.v3 .planmap .mapbar .chips{background:var(--v4-surface-2);border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);padding:var(--v4-space-1);gap:var(--v4-space-1);width:auto;max-width:100%}
.v3 .planmap .mapbar .chip{border:0;border-radius:var(--v4-r);background:transparent;color:var(--v4-ink-2);font:var(--v4-fw-med) var(--v4-fs-sm)/1.4 var(--v4-font);padding:var(--v4-space-1) var(--v4-space-3);cursor:pointer;
  transition:color var(--v4-dur-fast) ease,background-color var(--v4-dur-fast) ease,box-shadow var(--v4-dur-fast) ease}
.v3 .planmap .mapbar .chip:hover{color:var(--v4-ink)}
.v3 .planmap .mapbar .chip.on{background:var(--v4-surface);color:var(--v4-accent);font-weight:var(--v4-fw-semi);box-shadow:var(--v4-shadow-1)}
.v3 .planmap .mapbar .chip:focus-visible{outline:none;box-shadow:var(--v4-focus)}
/* zones: full-contrast occupancy tint + labels (production parity, teal instead of blue) */
.v3 .planmap .zn.some{fill:color-mix(in srgb,var(--v4-accent) 34%,var(--v4-surface-2))}
.v3 .planmap .zn.near{fill:color-mix(in srgb,var(--v4-med) 42%,var(--v4-surface-2))}
.v3 .planmap .zn.full{fill:color-mix(in srgb,var(--v4-crit) 42%,var(--v4-surface-2))}
.v3 .planmap .zt{fill:var(--v4-ink)}
.v3 .planmap .zn-n{fill:var(--v4-ink-2)}
.v3 .planmap .lbl.dim{opacity:.7}
/* zones: hover + selected area */
.v3 .planmap .zn{transition:fill var(--v4-dur) ease,stroke var(--v4-dur) ease,stroke-width var(--v4-dur) ease}
.v3 .planmap .zn.sel{stroke:var(--v4-accent)!important;stroke-width:3!important;fill:color-mix(in srgb,var(--v4-accent) 26%,var(--v4-surface-2))}
.v3 .planmap .zn:focus-visible{outline:none}
/* zone-kind outline (data-v4kind set by ui-v4-modules.js from the live zone kind) — fill keeps the occupancy tint */
.v3 .planmap .zn[data-v4kind="work"]{stroke:var(--v4-z-work)}
.v3 .planmap .zn[data-v4kind="meet"]{stroke:var(--v4-z-meet)}
.v3 .planmap .zn[data-v4kind="cafe"]{stroke:var(--v4-z-cafe)}
.v3 .planmap .zn[data-v4kind="common"]{stroke:var(--v4-z-common)}
.v3 .planmap .zn[data-v4kind="lobby"]{stroke:var(--v4-z-lobby)}
.v3 .planmap .zn[data-v4kind="park"]{stroke:var(--v4-z-park)}
.v3 .planmap .zn[data-v4kind]:not(:hover):not(:focus-visible):not(.sel){stroke-width:1.6}
/* overlays: flows + labels on the plan */
.v3 .planmap .flow{stroke:var(--v4-accent);opacity:.8}
.v3 .planmap .flown{fill:var(--v4-accent);paint-order:stroke;stroke:var(--v4-surface);stroke-width:3px}
.v3 .planmap .noflow{fill:var(--v4-muted)}
/* areas not on the plan */
.v3 .planmap .offplan{display:flex;flex-wrap:wrap;gap:var(--v4-space-1);align-items:center;margin-top:var(--v4-space-2);padding-top:var(--v4-space-2);border-top:1px dashed var(--v4-line)}
.v3 .planmap .offplan .lab{font:var(--v4-fw-med) var(--v4-fs-sm)/1.3 var(--v4-font);color:var(--v4-muted);margin-right:var(--v4-space-1)}
.v3 .planmap .offplan .chip{display:inline-flex;align-items:center;border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);background:var(--v4-surface);font-size:var(--v4-fs-sm);
  padding:var(--v4-space-1) var(--v4-space-2);cursor:pointer;color:var(--v4-ink-2);transition:border-color var(--v4-dur-fast) ease,color var(--v4-dur-fast) ease}
.v3 .planmap .offplan .chip:hover{border-color:var(--v4-accent);color:var(--v4-accent)}
.v3 .planmap .offplan .chip.stale{opacity:.65}
.v3 .planmap .offplan .chip .n{margin-left:var(--v4-space-1);font:var(--v4-fw-semi) var(--v4-fs-sm)/1 var(--v4-mono);color:var(--v4-accent)}
/* legend (auto-built from what is actually on the plan) */
.v4m-maplegend{position:absolute;left:14px;bottom:14px;z-index:2;display:flex;flex-wrap:wrap;gap:var(--v4-space-1) var(--v4-space-3);max-width:calc(100% - 28px);
  padding:var(--v4-space-1) var(--v4-space-2);font-size:var(--v4-fs-meta);color:var(--v4-ink-2);align-items:center;pointer-events:none;
  border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);background:var(--v4-glass);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);box-shadow:var(--v4-shadow-1)}
.v3 .planmap:has(> .offplan) > .v4m-maplegend{position:static;margin-top:var(--v4-space-2);max-width:100%;pointer-events:auto}
.v4m-maplegend span{display:inline-flex;align-items:center;gap:var(--v4-space-1);white-space:nowrap}
.v4m-maplegend i{display:inline-block;width:12px;height:12px;border-radius:var(--v4-r);flex:0 0 auto}
.v4m-maplegend i.fill-some{background:color-mix(in srgb,var(--v4-accent) 30%,var(--v4-surface-2))}
.v4m-maplegend i.fill-near{background:color-mix(in srgb,var(--v4-med) 40%,var(--v4-surface-2))}
.v4m-maplegend i.fill-full{background:color-mix(in srgb,var(--v4-crit) 40%,var(--v4-surface-2))}
.v4m-maplegend i.fill-unmapped{border:1.5px dashed var(--v4-line-strong)}
.v4m-maplegend i.fill-stale{border:1.5px dotted var(--v4-ink-3)}
.v4m-maplegend i.k{background:transparent;border:2px solid currentColor}
.v4m-maplegend .k-work{color:var(--v4-z-work)} .v4m-maplegend .k-meet{color:var(--v4-z-meet)}
.v4m-maplegend .k-cafe{color:var(--v4-z-cafe)} .v4m-maplegend .k-common{color:var(--v4-z-common)}
.v4m-maplegend .k-lobby{color:var(--v4-z-lobby)} .v4m-maplegend .k-park{color:var(--v4-z-park)}
.v4m-maplegend .v4m-lg-sep{width:1px;height:14px;background:var(--v4-line)}
.v4m-maplegend .v4m-lg-t{color:var(--v4-muted)}
/* heatmap: contained, reference cell shape */
.heatwrap,:where(.v4q-heat){max-width:100%;overflow-x:auto}
.heat{gap:var(--v4-space-1)!important}
.heat .hc{border-radius:var(--v4-r);font-family:var(--v4-mono);transition:transform var(--v4-dur-fast) var(--v4-ease),box-shadow var(--v4-dur-fast) var(--v4-ease)}
.heat .hc.cell:hover{outline:none;transform:scale(1.06);box-shadow:0 0 0 2px var(--v4-accent),var(--v4-shadow-2);z-index:1;position:relative}
.heat .hc.lab{font-family:var(--v4-font);color:var(--v4-ink-2);font-size:var(--v4-fs-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.heat .hc.hd{color:var(--v4-ink-3);font-size:var(--v4-fs-xs)}

/* ---------------------------------------------------------------------------------------------
   4a. MAP CONTROLS (Review C — reference "Live site map"): zoom group bottom-left, calm label
       chips, clean frame. The engine's SVG, zones, tints and click handlers are untouched.
   --------------------------------------------------------------------------------------------- */
/* zoom in / zoom out / fit — one compact rounded group */
.v3 .planmap > .v4m-mapzoom{position:absolute;left:var(--v4-space-4);bottom:var(--v4-space-4);z-index:3;display:inline-flex;align-items:stretch;
  background:var(--v4-surface);border:1px solid var(--v4-line);border-radius:var(--v4-r-lg);box-shadow:var(--v4-shadow-1);overflow:hidden}
.v4m-mapzoom button{display:grid;place-items:center;width:var(--v4-h);height:var(--v4-h);padding:0;border:0;background:transparent;color:var(--v4-ink-2);
  cursor:pointer;transition:background-color var(--v4-dur-fast) ease,color var(--v4-dur-fast) ease}
.v4m-mapzoom button + button{border-left:1px solid var(--v4-line)}
.v4m-mapzoom button:hover:not(:disabled){background:var(--v4-hover);color:var(--v4-accent)}
.v4m-mapzoom button:focus-visible{outline:none;box-shadow:inset var(--v4-focus)}
.v4m-mapzoom button:disabled{color:var(--v4-ink-3);cursor:default}
/* ui-v3's `.v3 .planmap svg{width:100%}` targets the PLAN; the control glyphs must not inherit it */
.v3 .planmap .v4m-mapzoom svg{display:block;width:var(--v4-ic);height:var(--v4-ic);max-width:none;max-height:none;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* legend moves to the bottom-right so it never sits under the zoom group */
.v3 .planmap > .v4m-maplegend{left:auto;right:var(--v4-space-4);bottom:var(--v4-space-4);max-width:calc(100% - var(--v4-space-4) * 2 - var(--v4-h) * 3 - var(--v4-space-4))}
/* zoomed: the plan pans by drag (engine clicks still open an area when you don't drag) */
.v3 .planmap.v4m-zoomed > svg{cursor:grab;touch-action:none}
.v3 .planmap.v4m-panning > svg{cursor:grabbing}
.v3 .planmap.v4m-panning > svg .zn{transition:none}
/* area labels = calm chips: name over count, surface fill, hairline border */
.v3 .planmap .lbl .v4m-chip{fill:var(--v4-surface);stroke:var(--v4-line-strong);stroke-width:1;vector-effect:non-scaling-stroke}
.v3 .planmap .lbl text{paint-order:normal;stroke:none}
.v3 .planmap .lbl .zt{fill:var(--v4-ink);font-weight:var(--v4-fw-semi)}
.v3 .planmap .lbl .zn-n{fill:var(--v4-ink-2);font-family:var(--v4-font);font-weight:var(--v4-fw-med)}
/* Chip text size (SVG user units; the plan renders at ~0.66x, so these read ~14/11 px and ~11/9 px) */
.v3 .planmap .lbl .zt{font-size:var(--v4-fs-kpi-sm)}
.v3 .planmap .lbl .zn-n{font-size:var(--v4-fs-h2)}
.v3 .planmap .lbl.sm .zt{font-size:var(--v4-fs-h2)}
.v3 .planmap .lbl.sm .zn-n{font-size:var(--v4-fs-md)}
/* Unmapped rooms: the wordy "no area configured" sub-label is dropped (as ui-v3's phone stylesheet
   already does) — the dimmed chip, dashed outline and the legend's "No area configured" say it. */
.v3 .planmap .lbl .zn-unmapped{display:none}
/* Customer map: rooms with no area configured show NO label at all (setup wording never reaches a
   customer) and their shape stays faint — present in the plan, but visually quiet. Engine classes only. */
.v3 .planmap .lbl.dim{display:none}
.v3 .planmap .zn.unmapped{opacity:.45;stroke-dasharray:none}
html[data-theme="dark"] .v3 .planmap .zn.unmapped{opacity:.45}
.v3 .planmap .lbl.dim .v4m-chip{fill:var(--v4-surface-2);stroke:var(--v4-line)}
.v3 .planmap .lbl.dim{opacity:.85}
.v3 .planmap .v-movement .lbl{opacity:.6}

/* Criterion 9 — an id-only sub-line (internal identity key) is never visible text */
[data-v4noid]{display:none!important}

/* ---------------------------------------------------------------------------------------------
   4b. ROLE STATE — "Not available for your role" inside the module's own frame (no request made)
   --------------------------------------------------------------------------------------------- */
.v4m-noaccess{display:flex;align-items:center;justify-content:center;gap:var(--v4-space-3);text-align:left;
  padding:var(--v4-space-8) var(--v4-space-4);border:1px dashed var(--v4-line-strong);border-radius:var(--v4-r-lg);background:var(--v4-surface-2);color:var(--v4-ink-2)}
.v4m-noaccess b{display:block;font:var(--v4-fw-semi) var(--v4-fs-md)/var(--v4-lh-tight) var(--v4-font);color:var(--v4-ink)}
.v4m-noaccess small{display:block;margin-top:var(--v4-space-1);font-size:var(--v4-fs-sm);color:var(--v4-muted)}
.v4m-noaccess-ic{flex:none;display:grid;place-items:center;width:var(--v4-h-lg);height:var(--v4-h-lg);border-radius:var(--v4-r-lg);
  background:var(--v4-surface);border:1px solid var(--v4-line);color:var(--v4-ink-3)}
.v4m-noaccess-ic svg{width:var(--v4-ic-lg);height:var(--v4-ic-lg);fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
tr.v4m-noaccess-row td,tr.v4m-noaccess-row:hover td{padding:var(--v4-space-4)!important;background:var(--v4-surface)!important;box-shadow:none!important}

/* ---------------------------------------------------------------------------------------------
   5. PHONE (≤560) — modals become full-height sheets; nothing wider than the viewport.
   --------------------------------------------------------------------------------------------- */
@media (max-width:560px){
  .v4m-modal .modalbox{width:100vw!important;max-width:100vw;max-height:100dvh;height:100dvh;border-radius:0}
  .v4m-modal .modalhead{padding:var(--v4-space-3)}
  .v4m-modal .modalbody{padding:var(--v4-space-3)}
  .v4m-modal .modalbody div[style*="grid-template-columns"]{grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:var(--v4-space-2)!important}
  .v4m-enrbar{width:100%}
  .v4m-enrbar .btn{flex:1 1 auto}
  .v3 .planmap{padding:var(--v4-space-2)}
  .v3 .planmap .mapbar{flex-direction:column;align-items:stretch;margin:0 0 var(--v4-space-2)}
  .v3 .planmap .mapbar .chips{width:100%;overflow-x:auto;flex-wrap:nowrap}
  .gen-v2 .genv2-main,.gen-v2 .genv2-side{padding:var(--v4-space-3)}
  .gen-v2 .genv2-step + .genv2-step::before{display:none}
}

@media (prefers-reduced-motion:reduce){
  .v4m-modal.open .modalbox,.gen-modal .gen-v2,.colmenu,.detbulk,.gen-v2 .gen-status:not(:empty),
  .gen-v2 .genv2-dot.on,.mdet-note.live::before,.gen-v2 .genv2-progressbar i::after{animation:none!important}
  .gen-v2 .genv2-btn,.v4m-modal .modalbody div[style*="grid-template-columns"] > div,.v4m-modal .modalbody div[style*="grid-template-columns"] img,
  #srV3 .srchips .chip,#detRows td > div[style*="width:52px"],.detfoot .aspg,.attfoot .aspg,.heat .hc,#mdetMore,#mdetLive,
  .v3 .planmap .zn,#asResults .wsav{transition:none!important}
  .gen-v2 .genv2-btn:hover,.v4m-modal .modalbody div[style*="grid-template-columns"] > div:hover,.v4m-modal .modalbody div[style*="grid-template-columns"] > div:hover img,
  #detRows tr:hover td > div[style*="width:52px"],#srV3 .srchips .chip:hover,.detfoot .aspg:hover,.heat .hc.cell:hover,#mdetMore:hover{transform:none!important}
}

/* ---------------------------------------------------------------------------------------------
   6. REVIEW E — no customer-facing truncation that removes meaning (never by shrinking type).
   --------------------------------------------------------------------------------------------- */
/* KPI sub-line: up to two lines inside the fixed tile height (label and value stay one line). Same
   selector shape as the ui-v4.css KPI rule, loaded later, so it replaces only the sub-line behaviour. */
:is(#view,#mobileShellRoot) :is(.kpi,.v4-kpi,.mkpi,[class$="-kpi"],[class*="-kpi "]):not(.mh-app *)
  :is(.kd,.k-sub,.v4-kpi-s,.mkd,[class*="kpi-s"]){white-space:normal;text-overflow:clip;display:-webkit-box;
  -webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;line-height:1.25;overflow-wrap:anywhere}
/* Bar-row labels (departments, areas): wrap onto a second line instead of "Marketing an…". */
.v4p-arow-n{white-space:normal;text-overflow:clip;overflow-wrap:anywhere;line-height:1.2}
/* Key/value and list sub-lines: wrap. */
.v4p-kv b,.v4p-kv small,.v4p-lrow-t small{white-space:normal;text-overflow:clip;overflow-wrap:anywhere}
/* Detection Log column headers: ONE line, no wrapping (paired with wider column min-widths so
   full labels like "Detection time"/"Time Spent" fit without truncation). */
#detHead th,#detHead th .thlbl{white-space:nowrap!important;text-overflow:ellipsis;overflow:hidden}
/* Detection Log body cells: single-line ellipsis, never mid-word break (overrides the P2-012
   `overflow-wrap:anywhere` for log tables at ui-v4.css:1216). */
#view #detRows td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;overflow-wrap:normal;word-break:normal}
#view #detRows td b{overflow:hidden;text-overflow:ellipsis}
/* thumbnail crop must never exceed / overlap its Photo column */
#view #detRows td > div[style*="width:52px"]{max-width:100%}
/* ---- table containment + timestamp policy (batch: 1150px overflow fixes) ----
   Wrappers clip+scroll internally and never force page-level horizontal overflow (guards the
   flex/grid min-width:auto expansion). */
:where(#view) .tablewrap,:where(#view) .v4-tablewrap,:where(#view) .v4p-tablewrap,:where(#view) .v4q-tablewrap{min-width:0;max-width:100%}
:where(#view) .attreg{max-width:100%;overflow-x:auto}
/* Timestamp / mono cells must stay on one line (report + legacy log tables) so rows don't distort;
   complements the P2-012 exception at ui-v4.css:1219. */
:where(#view) :is(.v4q-mono,.v4q-nowrap,td.mono,.wfstd :is(th,td):nth-child(6)){white-space:nowrap;overflow-wrap:normal}
/* Evaluation: visible Correct / Wrong words beside the existing icons; Settings jump highlight. */
[data-vok] .v4m-vlbl,[data-vwrong] .v4m-vlbl{margin-left:var(--v4-space-1);font-weight:600}
.v4m-flash{box-shadow:0 0 0 2px var(--v4-accent)!important;transition:box-shadow .3s}
/* System pill (owner decision 2026-09-13): the one place camera health is stated outside the Cameras screen. */
.top .live .v4-pillcams{font-size:var(--v4-fs-sm);font-weight:600;color:var(--v4-ink-2);white-space:nowrap}
.top .live .v4-pillcams.is-bad{color:var(--v4-crit-ink)}
@media (max-width:760px){ .top .live .v4-pillcams{display:none} }
