/* يقِظ · YAQIDH — Abu Dhabi Civil Defence command platform. Sovereign UI, RTL/LTR, local Leaflet + three.js. */
:root{
  /* Warm-neutral design system — Abu Dhabi Civil Defence Command Center (2026 refresh) */
  --bg:#FFFFFF;--bg2:#FFFFFF;--card:#FFFFFF;--card2:#FFFFFF;--ink:#191C1A;--ink2:#3A423C;
  /* --mut was #5C6B61: 4.80:1 on white (passes) but 4.33:1 on the page background --bg, so muted text
     sitting outside a card missed AA. Nudged darker to 4.52:1 on --bg (5.01:1 on white). */
  --mut:#5C6B61;--line:#E4DDD1;
  /* UAE national identity (flag) — secondary accents only */
  --uae-red:#CC3D00;--uae-green:#1D2C22;--uae-white:#ffffff;--uae-black:#191C1A;
  --sovereign:#ffffff;   /* white = the dominant sovereign surface */
  /* identity + triad accents */
  --brand:#1D2C22;--eye:#1E6F9F;--thinker:#B4560A;--responder:#1D2C22;--admin:#232A25;
  /* severity ramp — the ONLY colors that encode severity */
  --sev-critical:#CC3D00;--sev-high:#FF4D00;--sev-medium:#B4560A;--sev-low:#127A4B;--sev-info:#1E6F9F;
  /* resources + status */
  --resource-water:#1E6F9F;--status-pumpoff:#1E6F9F;
  /* semantic */
  /* --warn was #B4560A: measured 2.68:1 on white, which fails WCAG AA for BOTH normal text (4.5) and
     large text/UI (3.0). It is the colour used for warnings and for «الحريق محصور»-class notices, so the
     least readable token was carrying some of the most important text. Darkened along the same hue to
     the minimum that passes — 4.54:1 — rather than restyled, so the palette's character is unchanged. */
  --ok:#1D2C22;--warn:#B4560A;--info:#1E6F9F;--danger:#CC3D00;
  /* radii + soft shadow tokens (no gradients, no gloss) */
  --r-sm:14px;--r:18px;--r-lg:22px;
  --shadow:0 1px 2px rgba(28,25,23,.03),0 8px 24px rgba(28,25,23,.06);
  --shadow-sm:0 1px 2px rgba(28,25,23,.04);
  --shadow-lift:0 2px 4px rgba(28,25,23,.05),0 14px 34px rgba(28,25,23,.1);
  /* legacy aliases → mapped onto the new system so existing refs resolve unchanged */
  --red:var(--sev-critical);--orange:var(--sev-high);--yellow:var(--sev-medium);--blue:var(--info);--green:var(--sev-low);--violet:#1D2C22;
}
*{box-sizing:border-box} html,body{margin:0}
body{background:var(--bg);color:var(--ink);
  font-family:"IBM Plex Sans Arabic","Cairo","Inter","Segoe UI",Tahoma,system-ui,Arial,sans-serif;
  font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
/* Lucide inline icons — consistent stroke, currentColor, no emoji */
.li{width:18px;height:18px;flex:0 0 auto;display:inline-block;vertical-align:-.18em}
[data-licon]{display:inline-flex;align-items:center}
.card-h .li,.band-title .li,.flowtag .li{width:20px;height:20px}
.logo .li,.logo-lg .li{width:26px;height:26px}
.mini .li,.chip .li,.crumb .li{width:16px;height:16px}
.trow .ti{display:inline-flex;vertical-align:-.18em}.trow .ti .li{width:17px;height:17px}
.trow small .li{width:13px;height:13px;vertical-align:-.15em;color:var(--mut)}
.ag-row .li,.trail-row .li,.seq-row .li{width:15px;height:15px;vertical-align:-.15em}
.hidden{display:none!important}
small{color:var(--mut);font-weight:400;font-size:12px}
/* `font-family:inherit` is not a nicety. A <button> does NOT inherit type from its ancestors — the UA
   sheet hands it the system default — and the rule below that fixes this for fields
   (`input,select,textarea{font:inherit}`) never listed buttons. So every button in this product, on
   every screen, was rendering in ARIAL while the rest of it is IBM Plex Sans Arabic. On Arabic labels
   the mismatch is not subtle; it is a different script style. Reported from the sign-in roster
   2026-08-16, but the defect was never local to that screen.
   Only the FAMILY is inherited, not `font:` wholesale — sizes stay as each screen authored them. */
button{cursor:pointer;font-family:inherit;border:1px solid transparent;border-radius:11px;background:var(--brand);color:#fff;font-weight:600;padding:9px 14px;display:inline-flex;align-items:center;gap:7px;justify-content:center;box-shadow:var(--shadow-sm);transition:filter .15s,background .15s,border-color .15s,box-shadow .15s,transform .12s}
button:hover{filter:brightness(.97);box-shadow:var(--shadow)}
/* refined scroll + selection — small details that read as "finished" */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:#D8D0C2;border-radius:99px;border:2px solid var(--bg)}
::-webkit-scrollbar-thumb:hover{background:#8A968E}
::selection{background:color-mix(in srgb,var(--brand) 22%,#fff)}
button:active{transform:translateY(1px)}
input,select,textarea{background:#fff;color:var(--ink);border:1px solid var(--line);border-radius:10px;padding:9px 11px;width:100%;font:inherit}
/* A checkbox/radio is a fixed-size glyph, never a full-width field. The blanket width:100% above was
   stretching them to their container (measured: a 261px checkbox), which shoves the label text out of
   its own box — with white-space:nowrap the glyphs then paint on top of the neighbouring label. Several
   screens had already papered over this with per-component `flex:0 0 auto`; fix it at the source. */
input[type=checkbox],input[type=radio]{width:auto;flex:0 0 auto;padding:0;border-radius:3px;accent-color:var(--brand)}
input:hover,select:hover,textarea:hover{border-color:#D8D0C2}
input:focus,select:focus,textarea:focus{border-color:var(--brand);outline:none;box-shadow:0 0 0 3px rgba(0,154,73,.12)}
/* keyboard operability — default focus ring is invisible on the dark theme */
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--responder);outline-offset:2px}
button:disabled{opacity:.55;cursor:not-allowed}
button.busy{opacity:.7;cursor:progress}
@media(prefers-reduced-motion:reduce){*{animation-duration:.001ms!important;transition-duration:.001ms!important}}

/* ═══ THE SIGN-IN CONSOLE ═════════════════════════════════════════════════════════════════════════
   Two panes: identity + sign-in inline-start, the 24-account roster beside it.

   It was one 388px column. `.persona-grp-row` asks for `minmax(168px,1fr)` columns, but that column's
   inner width is ~332px — so the grid could never fit two, every account stacked one per row, and the
   screen ran ~1400px long on a desktop with ~70% of the viewport empty on either side of it. The
   roster is the content here (this build is demonstrated by SWITCHING PERSONAS), so it gets the width.

   The flag is the signature and it is LOAD-BEARING, not decoration: a full-height four-band spine on
   the console's inline-start edge, pinned with `inset-inline-start` so it follows the reader into
   Arabic and Urdu instead of sitting behind their shoulder.

   No new typeface: `vendor/fonts/` carries IBM Plex Sans Arabic at 400/500/700 and nothing else, and
   this platform ships no CDN. The voice comes from scale, weight and case.

   NOTE — letter-spacing is scoped to `html[lang=en]` throughout. Tracking an Arabic string breaks the
   joins between its letterforms; it is not a cosmetic choice there, it is a misspelling. */
.login{position:fixed;inset:0;display:flex;align-items:flex-start;justify-content:center;z-index:50;padding:16px;overflow:auto;
  background:
    radial-gradient(rgba(0,154,73,.06) 1px, transparent 1.7px) 0 0/22px 22px,
    radial-gradient(rgba(255,59,48,.05) 1px, transparent 1.7px) 11px 11px/22px 22px,
    radial-gradient(1100px 720px at 50% -8%, #ffffff 0%, var(--bg) 62%);
  background-attachment:fixed}
.login-card{--spine:12px;
  position:relative;margin-block:auto;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding-block:30px;padding-inline:calc(30px + var(--spine)) 30px;
  width:min(1180px,calc(100vw - 32px));text-align:center;overflow:hidden;
  box-shadow:0 1px 2px rgba(17,24,39,.04),0 24px 60px rgba(16,30,60,.14),0 0 0 4px rgba(0,154,73,.045);
  animation:loginrise .5s cubic-bezier(.2,.7,.2,1)}
@keyframes loginrise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
/* the fire gate is a single question, not a console — it keeps the narrow card (see boot(): hidden) */
.login-card.fire-gate{width:min(420px,calc(100vw - 32px))}
/* SIGNATURE — the UAE flag as the console's spine.
   The flag's white band is the one that has to be handled: at #FFFFFF against a #FFFFFF card it does
   not read as a band, it reads as a hole punched between the green and the black. So the spine sits on
   a warm off-white ground and the band shows THAT — the nearest tone to white that is still a band —
   with a hairline separating spine from card. */
.login-card .uae-bar{position:absolute;inset-block:0;inset-inline-start:0;width:var(--spine);height:auto;margin:0;
  border-inline-end:1px solid var(--line);
  background:linear-gradient(180deg,var(--uae-red) 0 25%,var(--uae-green) 25% 50%,transparent 50% 75%,var(--uae-black) 75% 100%),
    color-mix(in srgb,var(--card2) 72%,#fff)}
.login-card h1{font-size:17px;margin:6px 0 0;color:var(--ink);font-weight:700}.login-card .sub{font-size:12.5px;color:var(--mut);margin:4px 0 0;font-weight:500}
.login-card label{display:flex;align-items:center;gap:6px;text-align:start;font-size:12px;color:var(--mut);margin:12px 0 3px;font-weight:500}
.login-card label .li{width:14px;height:14px;color:var(--mut)}
.login-identity>button{width:100%;margin-top:18px;padding:12px;font-size:14px;font-weight:700}
.login-body{display:grid;grid-template-columns:minmax(280px,332px) minmax(0,1fr);gap:36px;align-items:stretch;text-align:start}
.login-identity{display:flex;flex-direction:column;min-width:0}
.login-roster{display:flex;flex-direction:column;min-width:0}
.logo-lg{display:inline-flex;align-items:center;justify-content:center;width:62px;height:62px;border-radius:17px;background:var(--brand);color:#fff;
  box-shadow:0 10px 26px rgba(0,154,73,.34),0 0 0 6px rgba(0,154,73,.08);animation:shieldfloat 3.4s ease-in-out infinite}
@keyframes shieldfloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
.logo-lg .li{width:31px;height:31px}
/* Pre-login language picker (AR / EN / UR) — sits at the roster's outer corner, above the accounts,
   because the language you read the ROSTER in is the choice it actually governs. */
.login-card .lang-pick{display:flex;justify-content:flex-end;gap:6px;margin:0 0 16px}
.login-card.fire-gate .lang-pick{justify-content:center}
.login-card .lang-pick button{width:auto;margin:0;padding:5px 13px;font-size:11.5px;font-weight:700;
  border-radius:20px;background:var(--card2);color:var(--mut);border:1px solid var(--line);box-shadow:none}
.login-card .lang-pick button:hover{filter:none;border-color:#D8D0C2;color:var(--ink)}
.login-card .lang-pick button.active{background:var(--brand);color:#fff;border-color:var(--brand)}
.login-trust{display:flex;justify-content:flex-start;gap:7px;flex-wrap:wrap;margin:18px 0 0}
.ltrust{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--mut);background:var(--card2);border:1px solid var(--line);border-radius:20px;padding:4px 10px}
.ltrust .li{width:13px;height:13px;color:var(--brand)}
/* YAQIDH logo (full lockup) — login hero + topbar brand.
   The perpetual `shieldfloat` bob is gone: a 250px mark drifting forever behind a sign-in form is
   motion with nothing to say. It settles once on load and then holds still. It is also smaller — the
   console leads with the roster now, not with the crest. */
.login-logo{display:block;width:164px;max-width:70%;height:auto;margin:0 0 4px;
  animation:loginrise .55s cubic-bezier(.2,.7,.2,1) both}
.logo-img{height:46px;width:auto;max-width:130px;object-fit:contain;flex:0 0 auto;display:block}
/* UAE national flag identity bar */
.uae-bar{height:4px;width:100%;background:linear-gradient(90deg,var(--uae-red) 0 25%,var(--uae-green) 25% 50%,var(--uae-white) 50% 75%,var(--uae-black) 75% 100%)}
.login-err{color:var(--danger);font-size:12px;min-height:16px;margin-top:8px}
.hint{color:var(--mut);font-size:12px;margin-top:10px}
/* ── Evaluation persona quick-login — the roster ────────────────────────────────────────────────
   The three groups are not three lists that happen to be adjacent: they are RINGS OF REACH around
   one fire — the Civil Defence responders, the people inside the burning tower, and the residents of
   the towers next door. That is the system's own doctrine, and the roster is the only place a reader
   meets it, so the bands are typed rather than decorated: a solid marker and a solid rule for the two
   rings inside the perimeter, a hollow marker and a DASHED rule for the ring outside it.

   Typed by marker and rule, never by colour. CLAUDE.md reserves the severity ramp as the only palette
   that encodes severity, and a red band over «أهل المبنى» would be read as exactly that. */
.persona-head{margin:0 0 14px;font-size:11px;font-weight:700;color:var(--ink2);text-align:start;
  text-transform:uppercase;display:flex;align-items:center;gap:10px}
.persona-head::after{content:"";flex:1;height:1px;background:var(--line)}
.login-personas{display:flex;flex-direction:column;gap:22px}
.persona-group{animation:rosterin .45s cubic-bezier(.2,.7,.2,1) both}
.persona-group:nth-child(2){animation-delay:.07s}
.persona-group:nth-child(3){animation-delay:.14s}
@keyframes rosterin{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
.persona-grp-h{display:flex;align-items:center;gap:10px;margin-bottom:9px;
  font-size:10.5px;font-weight:700;color:var(--ink2);text-transform:uppercase}
.persona-grp-h::before{content:"";width:7px;height:7px;border-radius:2px;background:var(--brand);flex:0 0 auto}
.persona-grp-h::after{content:"";flex:1;height:1px;background:var(--line)}
/* ring 3 — outside the perimeter: hollow marker, dashed rule. `renderPersonas()` emits the groups in
   a fixed order (cd, bp, nb) and `#resumeSession` is inserted BEFORE `#loginPersonas`, not inside it,
   so this index is stable. */
#loginPersonas .persona-group:nth-child(3) .persona-grp-h::before{background:none;box-shadow:inset 0 0 0 1.5px var(--mut)}
#loginPersonas .persona-group:nth-child(3) .persona-grp-h::after{background:none;height:0;border-top:1px dashed var(--line)}
.persona-grp-row{display:grid;grid-template-columns:repeat(auto-fill,minmax(224px,1fr));gap:8px}
/* Two lines per chip — the person on top, the account beneath — laid out from the SAME three children
   `renderPersonas()` already emits (svg.li · span · small) via named grid areas, so the roster template
   is untouched. */
.persona-chip{display:grid!important;grid-template-columns:auto minmax(0,1fr);grid-template-areas:"ic name" "ic user";
  column-gap:10px;row-gap:1px;align-content:center;width:100%;min-width:0;min-height:54px;margin:0!important;padding:9px 11px!important;
  background:var(--card);border:1px solid var(--line);border-radius:12px;color:var(--ink);font-size:12.5px;font-weight:600;
  cursor:pointer;text-align:start;box-shadow:none;
  transition:border-color .13s,background .13s,box-shadow .13s,transform .07s}
.persona-chip:hover{border-color:var(--brand);background:#fff;transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.persona-chip:active{transform:translateY(0)}
/* Selected — the account the panel is currently describing, and the one its button will sign in as.
   Marked by a filled inline-start edge rather than a fill, so the mark survives the hover state
   passing over other chips on the way to the panel. */
#loginPersonas .persona-chip.sel{border-color:var(--brand);background:color-mix(in srgb,var(--brand) 6%,#fff);
  box-shadow:inset 3px 0 0 0 var(--brand),var(--shadow-sm)}
html[dir=rtl] #loginPersonas .persona-chip.sel{box-shadow:inset -3px 0 0 0 var(--brand),var(--shadow-sm)}
#loginPersonas .persona-chip.sel>.li{background:color-mix(in srgb,var(--brand) 18%,#fff)}
.persona-chip>.li{grid-area:ic;width:30px;height:30px;padding:6px;border-radius:9px;
  background:color-mix(in srgb,var(--brand) 9%,#fff);color:var(--brand);flex:0 0 auto;
  transition:background .13s}
.persona-chip:hover>.li{background:color-mix(in srgb,var(--brand) 16%,#fff)}
.persona-chip>span{grid-area:name;min-width:0;white-space:normal;overflow-wrap:break-word;font-size:13px;line-height:1.3}
/* The account handle stays in the page's own face (IBM Plex Sans Arabic) at a size you can actually
   read. It was set in ui-monospace at 10px, which put a second typeface on the screen — one that
   appears nowhere else in the product — to say nothing worth a second typeface. */
.persona-chip>small{grid-area:user;color:var(--mut);font-weight:500;font-size:11.5px;line-height:1.35;text-align:start}
/* A stored session is OFFERED here, above the roster (showResumeChip()). It had no rule of its own at
   all, so it rendered as bare text with two buttons loose beside it. Its buttons carry no icon and no
   <small>, so they opt out of the two-line grid above. */
.resume-session{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 18px;padding:11px 14px;
  background:color-mix(in srgb,var(--brand) 5%,#fff);border:1px solid color-mix(in srgb,var(--brand) 24%,var(--line));
  border-radius:12px;font-size:12.5px;color:var(--mut)}
.resume-session>span{flex:1;min-width:140px}
.resume-session>span b{color:var(--ink);font-weight:700}
.resume-session .persona-chip{display:inline-flex!important;grid-template-areas:none;align-items:center;
  min-height:0;padding:7px 14px!important;background:var(--card2);font-size:12px}
html[lang=en] .persona-head,html[lang=en] .persona-grp-h{letter-spacing:.085em}
@media(max-width:400px){ .persona-chip>small{display:none} .persona-chip{min-height:0} }
/* Console → column. Below 1180px the hint panel is already gone (it needs a pane to dock into), so the
   two panes collapse at the same breakpoint and the roster keeps the full width on the way down. */
@media(max-width:1179px){
  .login-body{grid-template-columns:1fr;gap:26px}
  /* Stacked, the form must NOT inherit the console's full width — an 880px-wide password field and a
     matching submit button read as a page that lost its layout, not as a sign-in form. */
  .login-identity{max-width:420px;margin-inline:auto;align-items:stretch;text-align:center}
  .login-logo{margin-inline:auto}
  .login-trust{justify-content:center}
  .login-card .lang-pick{justify-content:center}
}
@media(max-width:760px){
  .login-card{--spine:7px;padding-block:22px;padding-inline:calc(18px + var(--spine)) 18px}
  .login-logo{width:142px}
  .persona-grp-row{grid-template-columns:1fr}
  .login-personas{gap:18px}
}
/* Dynamic alert-workflow editor */
.af-stage{border:1px solid var(--line);border-radius:12px;padding:12px;margin:10px 0;background:var(--card2)}
.af-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.af-top .af-label{flex:1;min-width:160px;padding:6px 8px;border:1px solid var(--line);border-radius:8px;font-weight:700}
.af-mv{display:inline-flex;flex-direction:column;gap:2px}
.af-mv .mini-btn{padding:1px 6px;line-height:1.1;font-size:11px}
.af-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:8px}
.af-f{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--mut)}
.af-f select,.af-f input,.af-f textarea{padding:6px 8px;border:1px solid var(--line);border-radius:8px;font-family:inherit;font-size:12.5px;color:var(--ink);background:#fff;width:100%}
/* what the delay MEANS for the selected trigger — inert documentation vs a live escalation
   clock. The server ships this text (catalog.delaySemantics) precisely so an operator never
   believes a non-timeout stage is silently delayed; nothing rendered it until 2026-08-22. */
/* a role the selected scope will not honour: shown, explained, and not clickable — so the editor
   never offers a filter the resolver has already decided to ignore. */
.af-ck-off{opacity:.45;cursor:not-allowed}
.af-ck-off input{cursor:not-allowed}
.af-sem{display:flex;align-items:center;gap:4px;margin-top:3px;font-size:11px;line-height:1.35}
.af-sem svg{width:12px;height:12px;flex:none}
.af-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:6px 0;font-size:12.5px}
.af-row .af-lbl{color:var(--mut);font-weight:600}
.af-row .af-users{flex:1;min-width:180px;padding:6px 8px;border:1px solid var(--line);border-radius:8px}
.af-ck{display:inline-flex;align-items:center;gap:4px;font-size:12px}
.af-msgs{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:6px}
/* The reason a policy version exists — required by PUT /api/alert-workflow, so this row is not
   optional furniture. `.af-reason-need` is the only red on this panel and appears once, after an
   operator has tried to publish without one. */
.af-reason-row{margin:10px 0 6px;display:flex;flex-direction:column;gap:4px}
.af-reason{width:100%;box-sizing:border-box;padding:7px 9px;border-radius:8px;
  border:1px solid var(--line,#EDEDED);background:var(--card,#fff);color:inherit;font:inherit}
.af-reason:focus{outline:2px solid var(--brand,#1D2C22);outline-offset:1px}
.af-reason-need{border-color:#CC3D00;background:rgba(220,38,38,.05)}
.af-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}
.af-preview:not(:empty){margin-top:6px;padding:6px 8px;background:#1D2C2210;border-radius:8px}
@media(max-width:820px){ .af-grid,.af-msgs{grid-template-columns:1fr} }

/* Neighbouring-building spread-risk: quantitative score meter + per-building broadcast button */
.f2-quant{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;color:var(--ink)}
.f2-meter{display:inline-block;width:96px;height:7px;border-radius:4px;background:var(--line);overflow:hidden;vertical-align:middle}
.f2-meter>span{display:block;height:100%;border-radius:4px}
.f2-bcast{background:#CC3D0012;border:1px solid #CC3D0055;color:#9E2F00;font-weight:700}
.f2-bcast:hover{background:#CC3D001f}
.f2-bmsg:not(:empty){margin-top:6px}

/* Persona description panel — WHO the selected account is, and the only control that signs in as them.

   It was `position:fixed; left:max(20px,3vw)` — a hard PHYSICAL left. Arabic is this platform's default
   language, so the panel opened on the far side of the screen from its reader, ~500px from the chips it
   described, and it was re-pinned on every hover so it jumped as the cursor moved down the list.

   Now it is a static block docked at the foot of the sign-in pane: beside the roster in both
   directions, and it flips with `dir` for nothing.

   It also carries the sign-in action, so it is no longer optional furniture — everything below is
   sized so the button cannot end up somewhere the reader can't reach. */
.persona-desc{display:none}
@media(min-width:1180px){
  /* `flex-basis:0` is the load-bearing part: the panel claims the sign-in pane's leftover height
     rather than contributing its own content height to it, so a two-line hint and a nine-line role
     description produce the same console. Without it the card grew as the panel filled and — being
     centred by `margin-block:auto` — slid up the screen under the cursor. */
  .persona-desc{display:block;flex:1 1 0;min-height:186px;margin-top:20px;position:relative;
    background:var(--card2);border:1px solid var(--line);border-radius:var(--r);
    padding:16px 18px;overflow-y:auto;text-align:start;
    animation:loginrise .5s cubic-bezier(.2,.7,.2,1) both}
  /* Resting state — nothing chosen yet. `personaDescDefault()` fills it with the invitation to choose,
     and a filled panel holding one sentence reads as a card that failed to load. Dashed and unfilled,
     it reads as the slot it is. (`:has()` keys off the two shapes that function emits.) */
  .persona-desc:has(.pd-hint){display:flex;align-items:center;background:none;border-style:dashed}
  .pd-close{display:none}        /* nothing to dismiss: the panel is a permanent slot on this layout */
}
/* Below the two-pane breakpoint the panel is the ONLY route into the system from the roster, so it
   cannot stay hidden — it becomes a sheet at the bottom of the screen. Docking it in the sign-in pane
   would put it far ABOVE the account you just tapped, which on a phone is off-screen entirely. */
@media(max-width:1179px){
  .persona-desc:has(.pd-name){display:block;position:fixed;inset-inline:0;bottom:0;z-index:60;
    max-height:min(72vh,540px);overflow-y:auto;margin:0;text-align:start;
    background:var(--card);border-top:1px solid var(--line);border-radius:var(--r-lg) var(--r-lg) 0 0;
    box-shadow:0 -6px 40px rgba(16,30,60,.18);padding:18px 20px 20px;
    animation:sheetup .28s cubic-bezier(.2,.7,.2,1)}
  @keyframes sheetup{from{transform:translateY(100%)}to{transform:none}}
  /* The sheet floats OVER the roster, so while it is open it sits on top of the accounts at the bottom
     of the list and swallows their taps — you could read one account and then not reach the next.
     Give the scroll container exactly the sheet's own maximum height back, so every chip can be
     scrolled clear of it. Matches `max-height` above; keep the two in step. */
  .login:has(#personaDesc .pd-name){padding-bottom:min(72vh,540px)}
}
.pd-close{position:absolute;inset-inline-end:10px;top:10px;width:30px;height:30px;padding:0;
  background:var(--card2);color:var(--mut);border:1px solid var(--line);border-radius:9px;box-shadow:none}
.pd-close:hover{filter:none;color:var(--ink);border-color:#D8D0C2}
.pd-close .li{width:15px;height:15px}
/* Where the account went. `position:sticky` keeps it visible while a long role description scrolls
   under it, because it is the line that tells you the form above is now armed — on the phone layout
   that form is off-screen behind this sheet, so the reader has no other way to know. */
.pd-ready{position:sticky;bottom:-16px;display:flex;align-items:center;gap:9px;margin-top:16px;
  padding:10px 12px;border-radius:11px;font-size:12.5px;
  background:color-mix(in srgb,var(--brand) 10%,#fff);border:1px solid color-mix(in srgb,var(--brand) 30%,var(--line));
  box-shadow:0 -10px 14px -8px var(--card2)}
.pd-ready .li{width:16px;height:16px;color:var(--brand);flex:0 0 auto}
.pd-ready>span{display:flex;flex-direction:column;line-height:1.3}
.pd-ready b{color:var(--ink);font-weight:700}
.pd-ready small{color:var(--mut);font-size:11px;font-weight:500;direction:ltr;text-align:start}
.persona-desc .pd-hint{color:var(--mut);font-size:12.5px;line-height:1.7}
.persona-desc .pd-hint b{color:var(--ink);font-weight:700}
.persona-desc .pd-name{font-size:15px;font-weight:800;color:var(--ink);display:flex;align-items:center;gap:8px}
.persona-desc .pd-name .li{width:18px;height:18px;color:var(--brand);flex:0 0 auto}
.persona-desc .pd-user{font-size:12px;color:var(--mut);font-weight:500;margin:2px 0 10px}
.persona-desc .pd-role{display:inline-block;font-size:10.5px;font-weight:700;color:var(--brand);
  background:rgba(0,154,73,.08);border:1px solid rgba(0,154,73,.2);border-radius:999px;padding:2px 9px;margin-bottom:10px}
.persona-desc .pd-body{color:var(--ink);font-size:12.8px;line-height:1.75}
.persona-desc .pd-body.en{color:var(--mut);font-size:12px;direction:ltr;text-align:left;margin-top:3px}
.persona-desc .pd-role .sep{opacity:.5;font-weight:500;margin:0 4px}
.persona-desc .pd-caps li .en{display:block;color:var(--mut);font-size:11px;direction:ltr;text-align:left;font-weight:500}
.persona-desc .pd-caps{margin:10px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;gap:5px}
.persona-desc .pd-caps li{display:flex;gap:7px;align-items:flex-start;font-size:12px;color:var(--mut);line-height:1.5}
.persona-desc .pd-caps li .li{width:13px;height:13px;color:var(--brand);flex:0 0 auto;margin-top:2px}

/* ═══ header — the government command bar ════════════════════════════════════════════════════
   A GRID, not a wrapping flex row, and that distinction is the whole fix. Measured at a 1920px
   viewport on the old one-row build:
     .topbar          101px tall
     .brand .t         45px  → a 14.5px title broken over TWO lines
     .brand .sub       37px  → the subtitle too
     #scopebar         76px  → #crumbOverview y=16 · #crumbSep y=22 · #crumbIncident y=58
   That last row is not a cosmetic complaint. The breadcrumb SPLIT: the «‹» separator was orphaned at
   the end of row 1 with the crumb it points at stranded on row 2. This app's stated premise is that
   navigation is by PERSON / scope, and its scope spine was rendering broken at every width.
   Meanwhile .tb-nav had 1084px for eleven sections while 523px went to passive status chips.

   Two explicit rows, each with one job:
     row 1  brand · scope spine · health + session      (nothing in it may wrap — see the nowrap rules)
     row 2  the section rail, at the FULL header width
   Header height is now a designed number instead of whatever the wrap produced. */
/* ═══ the command bar palette ═════════════════════════════════════════════════════════════════
   CREAM and GREEN. What made the old bar read as a dated admin toolbar was never the light surface —
   it was the warm-GRAY furniture on it: eleven bordered gray pills, a recessed gray rail track, a
   gray badge for the build number. Gray is what a control wears when nobody decided what it should
   look like.
   So: a warm cream ground, lighter and warmer than the page's --bg so the bar lifts off the work
   below rather than blending into it; every resting control drawn with NOTHING; and where a control
   does need to exist it is raised in WHITE, not recessed in gray. The emirate's green is the only
   accent in the bar, and it is spent on the three things that are actually state — the scope you are
   standing in, the section you are on, and whether the model is answering.
   Contrast on --hdr: --brand 5.2:1 · --ink2 9.5:1 · --mut 4.6:1 — all AA. */
:root{
  --hdr:#FFFFFF;                                          /* warm cream — lighter than --bg #FFFFFF */
  --hdr-raise:#FFFFFF;                                    /* a control that exists is RAISED, not sunken */
  /* HOVER GOES TOWARD THE GREEN, NOT TOWARD WHITE. The first pass raised a hovered chip to #FFFFFF on
     this #FFFFFF ground — a 3/255 difference, which is to say no feedback at all; the chip looked
     dead under the pointer. On a cream surface "lighter" has nowhere left to go, so the two states
     step along the accent instead, and the gap between them is what makes each one legible:
        ground #FFFFFF  →  hover #F2F2F2 (8%)  →  active #DFF5EA (15%)
     Roughly a 16-point jump per step on the red channel, so hover is unmistakable and active is
     unmistakably more than hover — before the underline and the green text even arrive. */
  --hdr-tint:color-mix(in srgb,var(--brand) 8%,#fff);     /* hover */
  --hdr-tint-2:color-mix(in srgb,var(--brand) 15%,#fff);  /* "you are here" */
  --hdr-edge:color-mix(in srgb,var(--brand) 22%,var(--line));
  --hdr-line:var(--line);
}
.topstick{position:sticky;top:0;z-index:60}
.topbar{position:relative;display:grid;align-items:center;
  grid-template-columns:auto 1fr auto;
  grid-template-areas:"brand scope session"
                      "nav   nav   nav";
  column-gap:20px;row-gap:6px;
  /* ORGANISED SPACE, and the number is not a guess: `.band` is `max-width:1720px` with 24px of its
     own padding, so page content starts at (100% − 1720)/2 + 24. The header used a flat 22px gutter
     and therefore lined up with nothing — on a 1920 screen the brand sat 100px inside of the band
     title it is supposed to head. This makes the header share the page's grid exactly, at every
     width, while the cream still runs edge to edge.
     Bottom padding is 0 on purpose: the section rail DOCKS on the bar's bottom edge, so the active
     tab's green underline lands on the border rather than floating above it. */
  padding:11px max(24px,calc((100% - 1720px) / 2 + 24px)) 0;
  background:var(--hdr);color:var(--ink);
  border-bottom:1px solid var(--hdr-line);
  box-shadow:0 1px 2px rgba(28,25,23,.04),0 10px 26px rgba(28,25,23,.06)}
/* the sovereign edge, pinned. `.uae-bar` used to sit OUTSIDE the header and scrolled away on the
   first wheel tick; inside it, it is the header's top edge and stays for the whole session. Same
   device the sign-in console uses as its vertical spine (`.login-card .uae-bar`). Absolute so it
   costs the grid neither a row nor a row-gap — and on this ground the flag finally reads. */
.topbar>.uae-bar{position:absolute;top:0;inset-inline:0;height:3px;width:auto;margin:0}
.brand{grid-area:brand;min-width:0}
/* THE SEAL — why the mark read as tiny, and why cropping is what makes it big.
   `mustajeeb-logo.png` is a full VERTICAL LOCKUP: measured at 1254×1254, it stacks the shield
   (x330-918 / y36-805), «مستجيب», «MUSTAJEEB», a three-item tagline row and a final tagline. Dropped
   whole into a header slot, five stacked elements share the height and the shield — the only part
   anyone can actually recognise — gets about half of it. At the old 46px lockup the emblem was ~28px
   and everything under it was sub-pixel mush.
   Clipped to the shield alone, a 54px tile carries a 39px emblem: the mark is HALF AGAIN as large
   while the header grows by eight pixels. The maths is the measurement — 153% height with a -1.2%
   top nudge lands source rows 10-830 in the tile, the shield with even margins, and the tile centres
   it (the emblem's centre is 3px off the canvas centre, i.e. centred).
   The tile stays white on the cream ground for a second reason: the PNG is opaque, colour type 2
   with no tRNS, so it carries its own white rectangle no matter what. A rounded white tile with a
   hairline ring turns that from an artifact into a mounted seal. */
.topbar .brand-seal{width:54px;height:54px;flex:0 0 auto;border-radius:16px;overflow:hidden;
  background:var(--hdr-raise);display:flex;justify-content:center;
  box-shadow:0 0 0 1px var(--hdr-line),0 2px 8px rgba(28,25,23,.07)}
.topbar .brand-seal .logo-img{height:153%;width:auto;max-width:none;flex:0 0 auto;margin-top:-1.2%;
  border-radius:0;padding:0;background:none;box-shadow:none}
.topbar .scopebar{grid-area:scope;justify-self:start}
.topbar .status{grid-area:session;justify-self:end}
.topbar .tb-nav{grid-area:nav}
/* row 1 never wraps — one line of title, one of subtitle, ellipsis before either breaks */
.topbar .brand .t{color:var(--ink);font-weight:800;font-size:15.5px;letter-spacing:-.2px;white-space:nowrap}
.topbar .brand .sub{color:var(--mut);font-size:11.5px;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar .logo{background:var(--brand);border-color:var(--brand);color:#fff;filter:none}
/* passive STATUS chips: quiet, borderless — they inform, they don't compete with navigation */
.topbar .chip{background:transparent;border-color:transparent;color:var(--mut);font-size:11.5px;padding:4px 7px}
/* the build string used to be a filled badge, which made it the loudest thing in the header's health
   cluster — louder than whether the model is answering. It only needed that emphasis back when it
   was one chip lost in a flat row of eleven; in a grouped cluster it can be as quiet as it is
   important. */
.topbar .chip.ver{background:transparent;border-color:transparent;font-weight:600;color:var(--mut)}
/* NAV chips: nothing drawn at rest. Eleven bordered gray pills is precisely what made the old rail
   read as a toolbar — a section that is not the one you are in has no business drawing a box. Hover
   RAISES it in white off the cream; only the active one takes the green. */
.topbar .chip.gear{background:transparent;border:1px solid transparent;color:var(--ink2);font-size:12.5px;
  border-radius:10px 10px 0 0;padding:8px 13px 9px;font-weight:600;
  transition:background .13s,color .13s,box-shadow .13s}
.topbar .chip.gear:hover{background:var(--hdr-tint);border-color:transparent;color:var(--brand);box-shadow:none}
.topbar .crumb{background:transparent;border-color:transparent;color:var(--ink2)}
.topbar .iconbtn,.topbar .lang{background:var(--hdr-raise);border:1px solid var(--hdr-line);color:var(--ink);
  font-size:12px;padding:6px 11px;border-radius:10px;box-shadow:var(--shadow-sm);
  transition:background .13s,border-color .13s,box-shadow .13s}
.topbar .iconbtn:hover,.topbar .lang:hover{background:var(--hdr-tint);border-color:var(--hdr-edge);box-shadow:var(--shadow);filter:none}
.topbar .logout{background:transparent;border:1px solid transparent;color:var(--danger);box-shadow:none;font-size:12px;padding:6px 11px;border-radius:10px}
.topbar .logout:hover{background:#FFE7DC;border-color:#FFE7DC;filter:none}
.topbar .badge-count{color:#fff;background:var(--brand)}
.brand{display:flex;align-items:center;gap:13px}
.logo{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
  background:var(--brand);color:#fff;border:0;border-radius:11px;line-height:1}
.logo .li{width:22px;height:22px}
.brand .t{font-weight:700;color:var(--ink);letter-spacing:.2px}
.brand .sub{font-size:12px;color:var(--mut)}
.triad{display:flex;gap:8px;flex-wrap:wrap}
.pill{display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:var(--ink);
  border:1px solid var(--line);background:var(--card);border-radius:22px;padding:6px 12px;font-size:13px;
  transition:filter .15s,background .15s,color .15s,border-color .15s}
.pill:hover{filter:brightness(1.25)}
/* real tabs: colored active state does the wayfinding the accents weren't doing */
.pill.active{font-weight:700}
.pill.eye.active{background:var(--eye);color:#191C1A;border-color:var(--eye)}
.pill.thinker.active{background:var(--thinker);color:#191C1A;border-color:var(--thinker)}
.pill.responder.active{background:var(--responder);color:#14201A;border-color:var(--responder)}
.pill.admin.active{background:var(--admin);color:#191C1A;border-color:var(--admin)}
.status{display:flex;align-items:center;gap:14px;flex-wrap:nowrap}
/* topbar GROUPS: status (quiet) · nav (segmented control) · session — easier to scan than a flat chip row */
.tb-group{display:flex;align-items:center;gap:4px}
/* PLATFORM health, and only that — `#whoami` moved to the session cluster where identity belongs.
   tabular-nums because #st-fresh reprints a clock on every stampFresh(); proportional digits made
   the whole cluster twitch sideways once a poll. (Same reason as `.kpi .v`.) */
.tb-status{gap:6px;padding-inline-end:14px;border-inline-end:1px solid var(--hdr-line);font-variant-numeric:tabular-nums}
/* «هل النموذج مُجيب؟» is operational state, not trivia: llmUsed:false means the model was unreachable
   and the operator is reading the deterministic grounded fallback. It was printing the word
   «fallback» in the same muted gray as the build number and the clock. Here it is a lit LED — the
   one thing on a console that is allowed to glow, because it is the one thing that changes on its
   own and changes what you can trust. */
#st-llm::before{content:"";width:7px;height:7px;border-radius:50%;flex:0 0 auto;
  background:var(--mut);transition:background .2s,box-shadow .2s}
#st-llm.ok{color:var(--ink2)}
#st-llm.ok::before{background:var(--brand);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 16%,transparent)}
#st-llm.degraded::before{background:var(--warn);box-shadow:0 0 0 3px color-mix(in srgb,var(--warn) 18%,transparent)}
#st-llm.down::before{background:var(--danger);box-shadow:0 0 0 3px color-mix(in srgb,var(--danger) 18%,transparent)}
#st-llm.degraded,#st-llm.down{color:var(--ink);font-weight:600}
/* WRAPS, and this was MEASURED rather than assumed — the first version of this comment claimed the
   nav itself overflowed, and it never does: its chips shrink, and below ~980px they drop their labels
   for icons. What overflows is the TOPBAR. With eleven chips on it, `.topbar` scrollWidth exceeded its
   clientWidth at every width from 1200px down — 1280×800 and 1366×768 being the two commonest
   laptops, so on most screens the session controls were pushed off the edge.
     nowrap            1600 ✓  1400 ✓  1280 ✗  1200 ✗  1100 ✗  1000 ✗  900 ✗
     wrap              every width ✓ (2 rows ≥1000, 3 rows below)
     wrap+max-content  1600 ✓  1400 ✓  1280 ✗ …   — looks better wide, fails where it matters
   Plain wrap is the only one that never overflows, so it STAYS as the safety net. What changed is
   that the rail no longer shares a row with the brand, the health chips and the session buttons: on
   its own grid row it has the full header width (~1500px at 1568 viewport) for ~1084px of chips, so
   above ~1150px the wrap never has to fire. Below that it still can, and still must. */
/* no recessed gray track around the rail either — that track was the single biggest reason the bar
   read as an old admin toolbar. The sections sit directly on the cream and DOCK on the bar's bottom
   edge, so they read as what they are: tabs into the page below, not buttons in a strip. */
.tb-nav{background:transparent;border:0;border-radius:0;padding:0;gap:2px;
        flex-wrap:wrap;justify-content:flex-start}
.tb-nav .chip.gear{position:relative}
/* ONE active rule, and it is green. There were three — styles.css had `.topbar .chip.gear.active`
   twice and `.tb-nav .chip.gear.active` once, so last-rule-wins painted the active SECTION in --eye
   blue while the active scope CRUMB stayed --brand green: two "you are here" colours in one header,
   by accident rather than intent. The crumb is the more authoritative of the two, so green wins. */
.tb-nav .chip.gear.active{background:var(--hdr-tint-2);color:var(--brand);box-shadow:none}
.tb-nav .chip.gear.active::after{content:"";position:absolute;inset-inline:0;bottom:-1px;height:2px;
  background:var(--brand)}
/* VISUAL clustering only — nothing is hidden and no click is added; every chip keeps its id and its
   perm-* class, and applyPerms()/checkGroupVisibility() are untouched.
   Grouped by PROXIMITY, not by a divider rule, and that was a correction: `.tb-cluster+.tb-cluster
   {border-inline-start}` looked right until a restricted persona hit it. `+` matches DOM order, not
   what is rendered — so with the command cluster permission-hidden, the *registers* cluster is still
   the second child and drew a leading hairline in front of nothing at the start of the rail. Every
   role except admin hides at least one cluster, so that was the common case, not the edge one.
   2px inside a group against 12px between them is a 6× ratio; the grouping reads without a rule that
   can point at nothing. The empty-cluster collapse stays — an empty group must not hold its gap.
   (`:has()` is already load-bearing in this sheet — see `.kpi:has(.kpi-ic)`.) */
.tb-cluster{display:inline-flex;align-items:center;gap:2px}
.tb-cluster+.tb-cluster{margin-inline-start:12px}
.tb-cluster:not(:has(> :not(.hidden))){display:none}
/* and if a role reaches NO section at all, the rail track goes too — an empty recessed pill under
   the brand reads as a control that failed to load rather than as one that does not apply. */
.tb-nav:not(:has(.tb-cluster > :not(.hidden))){display:none}
/* grouped nav dropdowns (Live ops / Registers / More) — wraps existing .chip.gear items, no permission-logic change */
.nav-group{position:relative;display:inline-flex}
.nav-group-toggle{background:transparent;border-color:transparent;box-shadow:none;border-radius:10px}
.nav-group-toggle:hover{background:#fff;box-shadow:var(--shadow-sm)}
.ng-chev{width:13px;height:13px;transition:transform .15s}
.nav-group.open .ng-chev{transform:rotate(180deg)}
.nav-group-menu{position:absolute;inset-inline-start:0;top:calc(100% + 6px);display:none;flex-direction:column;gap:2px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:var(--shadow-lift);padding:6px;z-index:40;min-width:180px}
.nav-group.open .nav-group-menu{display:flex}
.nav-group-menu .chip.gear{justify-content:flex-start;width:100%;border-radius:8px}
/* same hover as the rail it drops out of — this rule sits after `.topbar .chip.gear:hover` at equal
   specificity, so leaving it on the old gray would have made «أكثر»'s items the one place in the bar
   that still highlighted in gray. */
.nav-group-menu .chip.gear:hover{background:var(--hdr-tint);color:var(--brand)}
/* ⛔ الخطّ الأخضر تحت الشارة (`.tb-nav .chip.gear.active::after`) صُمّم لشريطٍ أفقيّ: قاعدة الشارة هي
   قاعدة الشريط. داخل قائمةٍ منسدلة يصير شريطًا بعرض الصفّ كاملًا يشبه فاصلًا مكسورًا. */
.nav-group-menu .chip.gear.active::after{display:none}
/* القسم المفتوح حاليًّا داخل القائمة. كان يأخذ نفس تظليل المرور تمامًا، فلا يُميَّز أين أنت وأنت تتصفّح؛
   وكان يهزم المرور نفسه (نفس الخصوصية، وهذه القاعدة أحدث) فيموت التحويم على الصفّ المفتوح. الآن:
   شارةٌ جانبية + وزنٌ أثقل تقول «أنت هنا»، والتظليل يبقى حرًّا ليقول «هذا ما ستفتحه». */
.nav-group-menu .chip.gear.active{background:transparent;color:var(--brand);font-weight:700;position:relative}
/* `inset-inline-start` لا `inset:left` — الشارة تقف عند بداية السطر في العربية والإنجليزية معًا */
.nav-group-menu .chip.gear.active::before{content:"";position:absolute;inset-inline-start:2px;top:6px;bottom:6px;
  width:2px;border-radius:2px;background:var(--brand)}
.nav-group-menu .chip.gear.active:where(:hover,:focus-visible){background:var(--hdr-tint-2);color:var(--brand)}
/* المجموعة المشقوقة: «الإدارة» تبقى رابطًا يفتح الصفحة (نقرةٌ واحدة كما كانت)، والسهم وحده يفتح قائمة
   أقسامها الستّة. المجموعة الوحيدة الأخرى («أكثر») ليس لها وجهةٌ بذاتها فزرّها يحمل الاسم والسهم معًا.
   بلا هذه القواعد كان السهم يطفو قرصًا مستقلًّا (نصف قطر ١٨ من `.chip`) بجانب الشارة، فيُقرأ زرَّين
   لا زرًّا واحدًا بنصفين. الآن: لا فجوة، والزاويتان الداخليّتان مسطّحتان، وفاصلٌ شعرة بينهما.

   وشارات الشريط مقصوصةٌ كتبويب متصفّح — `border-radius:10px 10px 0 0` — لأنها تقف على حافّة الشريط
   ويرسم المُختار منها خطًّا تحته. فالوحدة المشقوقة تُبقي الزاويتين العلويّتين الخارجيّتين وتُربّع
   اللحام بينهما وحده. القواعد بخصوصية (٠،٣،٠) فما فوق لأن `.topbar .chip.gear` يضبط الاختصار. */
.nav-group-split{gap:0}
.tb-nav .nav-group-split>.chip.gear:not(.ng-caret){border-start-end-radius:0;padding-inline-end:9px}
.tb-nav .nav-group-split>.ng-caret{border-start-start-radius:0;padding-inline:7px;min-width:0;position:relative}
.nav-group-split .ng-caret::before{content:"";position:absolute;inset-inline-start:0;top:7px;bottom:7px;
  width:1px;background:var(--hdr-line)}
/* والنصفان يضيئان معًا حين يكون القسم مفتوحًا، وإلّا بدت الشارة مُختارةً والسهم مُطفأً بجوارها،
   وانقطع الخطّ الأخضر في منتصف الوحدة */
.nav-group-split:has(>.chip.gear.active)>.ng-caret{background:var(--hdr-tint-2);color:var(--brand)}
.nav-group-split:has(>.chip.gear.active)>.ng-caret::after{content:"";position:absolute;inset-inline:0;bottom:-1px;
  height:2px;background:var(--brand)}
/* المرور على أي نصفٍ يُضيء النصفين: الوحدة هدفٌ واحد بصريًّا، ونصفاها يفعلان شيئين مختلفين */
.tb-nav .nav-group-split:hover>.chip.gear{background:var(--hdr-tint);color:var(--brand)}
.tb-nav .nav-group-split:has(>.chip.gear.active):hover>.chip.gear{background:var(--hdr-tint-2)}
.tb-session{gap:6px}
.chip{font-size:12px;color:var(--mut);background:var(--card2);border:1px solid var(--line);border-radius:18px;padding:4px 10px;white-space:nowrap;display:inline-flex;align-items:center;gap:5px}
.lang{background:var(--card2);color:var(--ink);border:1px solid var(--line)}.logout{background:#FFE7DC;color:var(--danger)}

/* banners */
.banners{display:flex;flex-wrap:wrap;gap:8px;padding:8px 18px 0}
/* DEMO notice — slim, quiet, professional (was a loud hazard-tape bar) */
.demo-banner{display:flex;align-items:center;gap:8px;justify-content:center;background:#FFFFFF;
  border-bottom:1px solid #FBEFD6;color:#9E2F00;font-weight:600;font-size:12px;padding:6px 14px;text-align:center}
.demo-banner .li{width:14px;height:14px;color:#B4560A}
.demo-banner span{background:none;padding:0;border-radius:0}
.banner{flex:1;min-width:260px;background:#FBEFD6;border:1px solid #E4DDD1;color:#7A4A08;border-radius:var(--r-sm);padding:9px 12px;font-size:12.5px}
.banner b{color:#B4560A}

/* layout */
/* ── THE HEIGHT OF THE COMMAND BAR IS A NUMBER OTHER THINGS NEED ────────────────────────────────
   Two things have to sit below a sticky, two-row header: the stop for every `#hash` jump, and the
   dossier's own sticky tab strip. Both used to carry a hard-coded guess, and both were wrong —
   `.inc-tabs` said `top:57px` against a bar measured at 107px, so 50px of a 63px strip parked
   underneath it and «العين · المفكّر · المجيب» was a sliver. A hash jump put the band title at y=18,
   behind the bar entirely.

   The bar's height is not a constant to guess at: the section row is permission-filtered, so an
   inspector's bar is not a commander's, and it grows again as the viewport narrows. `trackHeaderHeight()`
   in app.js measures the real element and publishes it here; the value below is only the fallback that
   applies before that runs. One source of truth, and it stays true. */
:root{--hdr-h:107px}
/* `:has(#app)` scopes this to the console shell. `sos.html` and `simulator.html` also load this sheet
   and have no such header; without the scope they would inherit a 123px anchor offset for a bar that
   is not there. */
html:has(#app){scroll-padding-top:calc(var(--hdr-h) + 16px)}
.band{padding:20px 24px 28px;display:none;max-width:1720px;margin:0 auto}   /* tab panels — one shown at a time */
.band.active{display:block;animation:bandfade .18s ease}
@keyframes bandfade{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.band-title{display:flex;align-items:center;gap:10px;margin:2px 0 16px;font-size:19px;font-weight:800;letter-spacing:-.2px;color:var(--ink)}
.band-title small{font-size:12.5px;font-weight:500;color:var(--mut);letter-spacing:0}
#eye .band-title{border-inline-start:3px solid var(--eye);padding-inline-start:9px}
#thinker .band-title{border-inline-start:3px solid var(--thinker);padding-inline-start:9px}
#responder .band-title{border-inline-start:3px solid var(--responder);padding-inline-start:9px}
#admin .band-title{border-inline-start:3px solid var(--admin);padding-inline-start:9px}
.grid{display:grid;gap:14px;grid-template-columns:1fr}
.grid.two{grid-template-columns:repeat(2,1fr)}.grid.four{grid-template-columns:1.05fr 1fr 1.3fr 1.15fr}
@media(max-width:1150px){.grid.two,.grid.four{grid-template-columns:1fr}}
/* The situation pair: a MAP beside a COLUMN of two cards.

   This was `align-items:start`, added because a 50/50 `.grid.two` stretched a 135px fires list into a
   442px card and left ~290px of dead white. Letting the column end wherever its content ended fixed
   the whitespace and created a different fault: the row closed on a ragged edge, 442px of map against
   393px of column, which is what reads as "the cards don't line up".

   Both are avoidable. The column STRETCHES to the map again, and the fires card — not the card after
   it — absorbs the difference, with its list scrolling inside. The slack goes somewhere that can use
   it (a longer visible list) instead of becoming padding under a short one, and the row closes flush. */
.grid.two.situation{grid-template-columns:1.35fr 1fr;align-items:stretch}
@media(max-width:1150px){.grid.two.situation{grid-template-columns:1fr}}
.ov-col{display:flex;flex-direction:column;gap:14px;min-width:0}
.ov-col>.card:first-child{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.ov-col>.card:first-child>.triage{flex:1 1 auto;min-height:120px;max-height:none}
/* auto-fit, not `two`: the copilot card is permission-gated (perm-copilot), and with a fixed 2-track
   grid hiding it left a half-width card beside an empty column. auto-fit collapses the empty track. */
.grid.fit{grid-template-columns:repeat(auto-fit,minmax(45%,1fr))}
/* the three tiers of the command room — الموقف · الاستجابة · التحليل. The 3px inline-start marker is
   the device this sheet already uses for the dossier band titles (`#eye .band-title` &c), reused
   rather than reinvented. No numbering: the tiers are a priority order, not a sequence you step
   through, and «01 / 02 / 03» would claim otherwise. */
.ov-tier{display:flex;align-items:center;gap:8px;margin:24px 0 11px;font-size:12px;font-weight:700;
  letter-spacing:.2px;color:var(--mut);border-inline-start:3px solid var(--tier,var(--line));
  padding-inline-start:9px;line-height:1.35}
.ov-tier .li{width:15px;height:15px;color:var(--tier,var(--mut))}
.ov-tier:first-of-type{margin-top:4px}
.tier-situation{--tier:var(--eye)}
.tier-act{--tier:var(--responder)}
.tier-analyse{--tier:var(--thinker)}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:16px 18px;box-shadow:var(--shadow)}
.card+.card,.grid+.grid,.grid+.card,.card+.grid{margin-top:14px}
/* …but NOT between siblings that a grid is already spacing with `gap`. The rule above is for cards
   stacked in normal flow; inside a grid it fires on the second child as well and adds 14px on top of
   the 14px gap. Measured on #overview: the copilot card sat 14px BELOW the agents card beside it — two
   cards in one row, visibly out of line — and the left column ran a 28px gap between its two cards
   where every other gap on the page was 14px. Grids own their own spacing. */
.grid>.card+.card,.ov-col>.card+.card{margin-top:0}
/* A card header is IDENTITY then, optionally, META. It was `justify-content:space-between`, which
   spreads ALL children edge to edge — fine for the two-child «title · meta» case it was written for,
   and wrong for every header that leads with an icon: the glyph was pinned to one end of the card and
   its own title to the other, ~1450px apart on the fleet-KPI card. That is why some headers looked
   like the icon belonged to a different card.

   So: pack from the start, and let the FIRST trailing element take the slack. The `~ *` reset matters —
   without it a header with both a `<small>` and a button gives each an auto margin and the free space
   splits between them, pushing the pair apart instead of grouping them at the end. */
.card-h{font-size:13.5px;font-weight:700;color:var(--ink2);margin:0 -18px 13px;padding:0 18px 11px;border-bottom:1px solid var(--line);
  display:flex;gap:8px;align-items:center;justify-content:flex-start;flex-wrap:wrap}
.card-h>.card-collapse{order:-1}   /* injected as firstChild by makeCollapsible(); keep it leading */
.card-h>small,.card-h>.meta,.card-h>.badge,.card-h>button:not(.card-collapse){margin-inline-start:auto}
.card-h>small~*,.card-h>.meta~*,.card-h>.badge~*,.card-h>button:not(.card-collapse)~*{margin-inline-start:0}

.card.collapsed{background:#FFFFFF;box-shadow:var(--shadow-sm);transition:border-color .12s,background .12s;align-self:start}
.card.collapsed:hover{border-color:#D8D0C2;background:#fff}
.card.collapsed .card-h{margin-bottom:0;padding-bottom:0;border-bottom:none}
/* Leaflet fit & polish: full-width container + the layers toggle glyph (vendored css points at a missing png)

   `z-index:0` is the line that stops the map climbing over the command bar, and it is doing something
   less obvious than it looks. Leaflet gives `.leaflet-container` `position:relative` but no z-index, so
   it creates NO stacking context — which means its internal panes (`.leaflet-pane`, z-index 400) and
   its controls (`.leaflet-top`, z-index 1000) were competing directly against `.topstick` at z-index
   60, in the root stacking context, and winning. Measured on #overview: with the page scrolled so the
   map ran under the header, `document.elementFromPoint()` 20px above the header's bottom edge returned
   `leaflet-zoom-animated` — the map was not merely painting over the sticky header, it was taking the
   clicks meant for it.

   `position:relative` + an explicit z-index makes the container a stacking context, so all of Leaflet's
   400s and 1000s are resolved INSIDE it and the whole map composites as one layer at 0. Raising
   `.topstick` instead would not have worked: no header z-index survives a control that asks for 1000. */
.leaflet-map{width:100%;border-radius:12px;position:relative;z-index:0}
.leaflet-control-layers-toggle{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23334155' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2 2 7l10 5 10-5-10-5Z'/%3E%3Cpath d='m2 17 10 5 10-5'/%3E%3Cpath d='m2 12 10 5 10-5'/%3E%3C/svg%3E")!important;
  background-size:22px 22px;background-position:center;background-repeat:no-repeat}
.leaflet-control-layers{border-radius:10px!important;box-shadow:var(--shadow)!important;border:1px solid var(--line)!important}
.card-h>span:first-child,.card-h>span:nth-child(2){display:inline-flex;align-items:center;gap:7px}

/* KPIs */
/* Six fixed tracks meant each tile got whatever 1/6 of the viewport happened to be — at 1150px that is
   a 178px tile holding a 23px number, an icon and a label, and the label wrapped. Sized by CONTENT
   instead: as many 196px-or-wider tiles as fit, so they reflow 6→4→3→2 instead of crushing. */
.kpi-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(196px,1fr));gap:12px}
@media(max-width:640px){.kpi-row{grid-template-columns:repeat(2,1fr)}}
.kpi{position:relative;overflow:hidden;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:14px 15px;
  display:flex;align-items:center;gap:12px;text-align:start;box-shadow:var(--shadow-sm)}
.kpi::before{content:"";position:absolute;inset-inline-start:0;top:0;bottom:0;width:3px;background:var(--kpi-accent,transparent)}
.kpi-ic{position:relative;flex:0 0 auto;width:42px;height:42px;border-radius:12px;display:inline-flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--kc) 10%,#fff);border:1px solid color-mix(in srgb,var(--kc) 26%,#fff);color:var(--kc)}
.kpi:has(.kpi-ic){--kpi-accent:color-mix(in srgb,var(--kc,transparent) 55%,transparent)}
.kpi-ic .li{width:21px;height:21px}
.kpi-tx{min-width:0}
.kpi .v{font-size:23px;font-weight:800;line-height:1.08;letter-spacing:-.4px;font-variant-numeric:tabular-nums;color:var(--ink)}
.kpi .k{font-size:11.5px;color:var(--mut);margin-top:2px;font-weight:500}
/* Share ring restates a ratio already on the tile (value / estate). Never a invented series. */
.viz-ring{width:40px;height:40px;display:block;transform:rotate(-90deg)}
.viz-ring-bg{fill:none;stroke:var(--line);stroke-width:3.4}
.viz-ring-fg{fill:none;stroke-width:3.4;stroke-linecap:round}
.kpi-share{position:absolute;inset:-6px;pointer-events:none}
.kpi-share .viz-ring{width:100%;height:100%}
.viz-donut-wrap{display:flex;align-items:center;gap:12px;margin:0 0 10px;padding-bottom:10px;border-bottom:1px solid var(--line)}
.dash-card-b .viz-donut-wrap{flex-wrap:wrap}
.viz-donut{width:72px;height:72px;flex:0 0 auto}
.viz-donut-seg{fill:none;stroke-width:10;transform-origin:36px 36px}
.viz-donut-legs{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
.viz-leg{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--ink);min-width:0}
.viz-leg i{width:8px;height:8px;border-radius:99px;flex:0 0 auto}
.viz-leg>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.viz-leg b{margin-inline-start:auto;font-variant-numeric:tabular-nums;font-size:11px}
/* KPI drill-down: clickable tiles + modal */
.kpi-drill{cursor:pointer;transition:transform .08s ease,box-shadow .12s ease,border-color .12s ease}
.kpi-drill:hover{transform:translateY(-1px);box-shadow:var(--shadow);border-color:color-mix(in srgb,var(--eye) 40%,var(--line))}
.kpi-drill:focus-visible{outline:2px solid var(--eye);outline-offset:2px}
.ovl{position:fixed;inset:0;z-index:1000;display:none;align-items:flex-start;justify-content:center;background:rgba(15,23,42,.42);backdrop-filter:blur(2px);padding:5vh 16px}
.ovl.open{display:flex}
.ovl-card{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);width:min(880px,96vw);max-height:90vh;display:flex;flex-direction:column;overflow:hidden}
.ovl-h{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 16px;border-bottom:1px solid var(--line)}
.ovl-h b{font-size:15px}
.ovl-ic{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:9px;vertical-align:middle;margin-inline-end:6px;background:color-mix(in srgb,var(--kc) 12%,#fff);border:1px solid color-mix(in srgb,var(--kc) 32%,#fff);color:var(--kc)}
.ovl-ic .li{width:17px;height:17px}
.ovl-x{background:none;border:none;cursor:pointer;color:var(--mut);padding:4px;border-radius:8px;display:inline-flex}
.ovl-x:hover{background:var(--card2);color:var(--ink)}
.ovl-bd{padding:12px 16px;overflow:auto}
.ovl-sum{margin-bottom:9px}
.ovl-f{display:flex;align-items:center;gap:8px;padding:10px 16px;border-top:1px solid var(--line)}
.mini-btn{font-size:12px;background:var(--card2);border:1px solid var(--line);border-radius:8px;padding:3px 9px;cursor:pointer;color:var(--ink);display:inline-flex;align-items:center;gap:4px}
.mini-btn:hover:not([disabled]){border-color:var(--eye);color:var(--eye)}
.mini-btn[disabled]{opacity:.45;cursor:default}
.mini-btn .li{width:13px;height:13px}
/* prompt -> dashboard */
.dash-kpis{grid-template-columns:repeat(auto-fit,minmax(215px,1fr));margin:6px 0 10px}
@media(max-width:760px){.dash-kpis{grid-template-columns:repeat(2,1fr)}}
.dash-bar{display:grid;grid-template-columns:130px 1fr 60px;gap:9px;align-items:center;margin:5px 0;font-size:12px}
.dash-bar .dl{color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dash-bar .dt{background:var(--card2);border:1px solid var(--line);border-radius:6px;height:15px;overflow:hidden}
.dash-bar .df{display:block;height:100%;background:var(--brand);border-radius:6px;min-width:2px}
.dash-bar .dn{text-align:end;color:var(--mut);font-weight:600}
/* Prompt → Plotly dashboard: section tabs + figure grid */
.dash-tabs{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 10px}
.dash-tab{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;background:var(--card2);border:1px solid var(--line);border-radius:9px;padding:6px 11px;cursor:pointer;color:var(--ink)}
.dash-tab:hover{border-color:color-mix(in srgb,var(--eye) 40%,var(--line))}
.dash-tab.active{background:color-mix(in srgb,var(--eye) 12%,#fff);border-color:var(--eye);color:var(--eye);font-weight:600}
.dash-tab .li{width:15px;height:15px}
.dash-plots{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-top:6px}
@media(max-width:760px){.dash-plots{grid-template-columns:1fr}}
.dash-plot{background:var(--card);border:1px solid var(--line);border-radius:11px;padding:6px;min-height:300px;box-shadow:var(--shadow-sm)}

/* leaflet map (no external tiles -> dark bg) */
.leaflet-map{height:360px;border-radius:10px;border:1px solid var(--line);background:#191C1A}
.leaflet-map.inc{height:460px}
.incsel{max-width:260px;font-size:12.5px;width:auto;background:var(--card2);border:1px solid var(--line);
  border-radius:11px;padding:8px 12px;font-weight:600;color:var(--ink);cursor:pointer}
.incsel:hover{background:#fff;border-color:#D8D0C2}
.fire-mk .fire{position:relative;font-size:18px;line-height:26px;text-align:center;filter:drop-shadow(0 0 5px var(--fc));animation:firepulse 1.6s infinite}
.fire-mk .sevtag{position:absolute;top:-7px;inset-inline-end:-7px;font-size:11px;font-style:normal;line-height:1;text-shadow:0 0 3px #191C1A,0 0 3px #191C1A}
@keyframes firepulse{0%,100%{transform:scale(1)}50%{transform:scale(1.28)}}
/* Lucide map pins — white fill, severity-colored (mockup style) */
.map-pin-wrap{background:none!important;border:0!important}
.map-pin{width:30px;height:30px;border-radius:50% 50% 50% 2px;background:#fff;border:2px solid var(--mc);
  display:flex;align-items:center;justify-content:center;box-shadow:0 3px 8px rgba(17,24,39,.30);transform:rotate(45deg)}
.map-pin .li{width:16px;height:16px;color:var(--mc);transform:rotate(-45deg)}
#incidentInfo .li,#respInfo .li,.ctx-row .li,#incTitle .li{width:14px;height:14px;vertical-align:-.15em}
.emo-mk .emo .li{width:19px;height:19px;filter:drop-shadow(0 1px 2px rgba(0,0,0,.4))}
.unit-mk .unit .li{width:15px;height:15px}
.leaflet-container{background:#191C1A}
.legend{display:flex;flex-wrap:wrap;gap:12px;margin-top:8px;font-size:12px;color:var(--mut)}
.legend.sm{font-size:12px;gap:9px}
.legend i.d{display:inline-block;width:10px;height:10px;border-radius:50%;margin-inline-end:5px;vertical-align:middle}
.d.red{background:var(--red)}.d.orange{background:var(--orange)}.d.blue{background:var(--blue)}.d.green{background:var(--green)}
.d.focus{background:var(--red)}.d.smoke{background:var(--orange)}.d.threat{background:var(--yellow)}.d.evac{background:#FF4D00}.d.refuge{background:#127A4B}.d.safe{background:var(--green)}

/* copilot */
.copilot{display:flex;gap:8px}.copilot input{flex:1}
.chips{display:flex;flex-wrap:wrap;gap:6px;margin:9px 0}
.chips .c{cursor:pointer;font-size:12px;background:var(--card2);border:1px solid var(--line);border-radius:16px;padding:5px 10px;color:var(--mut)}
.chips .c:hover{color:var(--ink);border-color:var(--eye)}
.cp-out,.cv-out{margin-top:8px;font-size:12.5px}
.cp-answer{background:#DFF5EA;border:1px solid #DFF5EA;color:#1D2C22;border-radius:8px;padding:8px 10px;margin-bottom:6px;font-size:13px}
.devices{display:flex;flex-direction:column;gap:8px}
.devices .dev{display:inline-flex;align-items:center;gap:8px;background:var(--card2);border:1px solid var(--line);border-radius:10px;padding:6px 10px;font-size:12px}
.estate-sum{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:13px;color:var(--ink);padding:2px 2px 4px}
.estate-sum b{font-size:15px}
.estate-sum .lucide{width:16px;height:16px;vertical-align:-3px;color:var(--mut)}
.estate-tally{display:inline-flex;gap:6px;margin-inline-start:auto}
.et{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--line);border-radius:999px;padding:2px 9px;font-size:12px;font-weight:700;background:var(--card)}
.et .lucide{width:14px;height:14px}
.et-rtsp{color:var(--sev-low);border-color:#DFF5EA}
.et-picars{color:var(--info);border-color:#F2F2F2}
.et-alarm{color:var(--mut)}
.estate-row{display:flex;align-items:center;gap:10px;background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:9px 11px;cursor:pointer;transition:box-shadow .12s,border-color .12s;border-inline-start-width:3px}
.estate-row:hover{box-shadow:0 2px 10px rgba(17,24,39,.08);border-color:#EDEDED}
.estate-row.feed-rtsp{border-inline-start-color:var(--sev-low)}
.estate-row.feed-picars{border-inline-start-color:var(--info)}
.estate-row.feed-alarm{border-inline-start-color:var(--line)}
.estate-ic{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:10px;border:1px solid var(--line);background:#fff;color:var(--mc,var(--ink))}
.estate-ic .lucide{width:18px;height:18px}
.estate-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:1px}
.estate-main b{font-size:13px}
.estate-sigs{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}
.estate-sigs .sig{font-size:11px;background:var(--bg);color:var(--mut);border:1px solid var(--line);border-radius:6px;padding:1px 7px}
.estate-feed{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;border:1px solid var(--line);border-radius:999px;padding:4px 10px;background:#fff}
.estate-feed .lucide{width:15px;height:15px}
.estate-feed small{font-weight:500;opacity:.75;margin-inline-start:2px}
.estate-feed.feed-rtsp{color:var(--sev-low);border-color:#DFF5EA;background:#DFF5EA}
.estate-feed.feed-picars{color:var(--info);border-color:#F2F2F2;background:#F2F2F2}
.estate-feed.feed-alarm{color:var(--mut)}
/* ---- agent roster (THINKER catalog) ---- */
.agent-roster{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
.agent-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:13px 14px;border-top:3px solid var(--ac,var(--brand));display:flex;flex-direction:column;gap:8px;box-shadow:0 1px 2px rgba(17,24,39,.04)}
.agent-top{display:flex;align-items:center;gap:10px}
.agent-ic{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:11px;border:1px solid var(--line);background:#fff;color:var(--ac,var(--ink))}
.agent-ic .lucide{width:20px;height:20px}
.agent-id{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;line-height:1.25}
.agent-id b{font-size:14px}
.agent-no{flex:0 0 auto;font-size:12px;font-weight:800;color:#fff;background:var(--ac,var(--brand));min-width:23px;height:23px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;padding:0 5px}
.agent-chips{display:flex;flex-wrap:wrap;gap:5px}
.ag-chip{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;border-radius:999px;padding:2px 8px;border:1px solid var(--line);background:#fff}
/* ✍️ The count of proposals awaiting a signature, on the «الوكلاء» nav chip. Amber, not red: a
   proposal is a question, not a fault — and red on this bar already means an incident. */
.aip-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;
  margin-inline-start:6px;padding:0 5px;border-radius:999px;background:#B4560A;color:#fff;
  font-size:11px;font-weight:800;line-height:1}
/* The sign button carries the weight of the act: full width, and it is the only primary control in
   the row so a tired reader cannot hit it by aiming for something else. */
#aiProposals .aip-sign{display:inline-flex;align-items:center;gap:6px;padding:9px 16px;border-radius:10px;
  border:1px solid #1E6F9F;background:#1E6F9F;color:#fff;font-family:inherit;font-weight:800;
  font-size:14px;cursor:pointer;min-height:42px}
#aiProposals .aip-sign:disabled{opacity:.6;cursor:default}
#aiProposals details summary{cursor:pointer}
/* ⏱️ A countdown must not be discoverable only by reading carefully. Red, because unlike a proposal
   awaiting a signature this one happens whether or not anybody looks. */
#aiProposals .aip-countdown{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;
  padding:8px 11px;border-radius:9px;background:#FFE7DC;border:1px solid #FFE7DC;color:#9E2F00;
  font-size:13.5px}
#aiProposals .aip-countdown small{color:#B4560A}
#aiProposals .aip-left{font-variant-numeric:tabular-nums;font-weight:800}
/* ⚡ An action already taken with nobody asked. The loudest thing in the ledger, and `aip-unseen`
   keeps it loud until somebody says they have looked — the platform acting alone must not be
   something a reader can scroll past without noticing. */
#aiProposals .aip-direct{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;
  padding:9px 12px;border-radius:9px;background:#FFE7DC;border:1px solid #FFE7DC;color:#9E2F00;
  font-size:13.5px}
#aiProposals .aip-unseen{border-inline-start:5px solid #CC3D00;background:#FFE7DC}
#aiProposals pre.mono{background:#F2F2F2;border:1px solid #F2F2F2;border-radius:8px;padding:8px;margin:6px 0 0}
.ag-chip .lucide{width:13px;height:13px}
.ag-chip.ok{color:var(--sev-low);border-color:#DFF5EA;background:#DFF5EA}
.ag-chip.off{color:var(--mut)}
.ag-chip.gate{color:var(--info);border-color:#F2F2F2;background:#F2F2F2}
.ag-chip.defer{color:var(--sev-high);border-color:#FFE7DC;background:#FFE7DC}
.ag-chip.beyond{color:#1D2C22;border-color:#EDEDED;background:#FFFFFF}
.agent-prod{display:flex;align-items:flex-start;gap:6px;font-size:13px;color:var(--ink);font-weight:600}
.agent-prod .lucide{width:15px;height:15px;flex:0 0 auto;color:var(--mut);margin-top:2px}
.agent-srcs{font-size:12px;display:flex;flex-wrap:wrap;gap:4px;align-items:center}
.agent-srcs .meta{margin-inline-end:2px}
.ag-src{font-size:11px;background:var(--bg);color:var(--mut);border:1px solid var(--line);border-radius:6px;padding:1px 7px}
.agent-collab{font-size:12px;display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.agent-collab .lucide{width:14px;height:14px;color:var(--mut)}
.agent-ep{font-size:11px;display:flex;align-items:center;gap:5px;border-top:1px dashed var(--line);padding-top:7px;margin-top:2px}
.agent-ep .lucide{width:13px;height:13px}
.agent-ep code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11px;color:var(--ink)}
.ag-gov{font-size:11.5px;display:flex;align-items:flex-start;gap:5px;border-radius:8px;padding:5px 8px;border:1px solid var(--line)}
.ag-gov .lucide{width:14px;height:14px;flex:0 0 auto;margin-top:1px}
.ag-gov.ok{background:#DFF5EA;color:#127A4B;border-color:#DFF5EA}
.ag-gov.defer{background:var(--bg);color:var(--mut)}
.ag-cite{font-size:11.5px;display:flex;align-items:flex-start;gap:5px;margin-top:6px;padding:5px 8px;border-radius:8px;background:#DFF5EA;color:#127A4B;border:1px solid #DFF5EA}
.ag-cite .li{width:14px;height:14px;flex:0 0 auto;margin-top:1px}
.cl-chip{display:inline-flex;align-items:center;gap:3px;cursor:pointer;font-size:11px;font-weight:700;color:#127A4B;background:#DFF5EA;border:1px solid #DFF5EA;border-radius:7px;padding:2px 7px;margin:2px 2px 0 0}
.cl-chip:hover{background:#DFF5EA}
.cl-chip .li{width:12px;height:12px}
.cl-reveal:not(:empty){margin-top:7px}
.ct-inline{border:1px solid var(--line);border-radius:10px;padding:8px 10px;background:var(--card);font-size:11.5px}
.ct-inline .ct-wrap{overflow-x:auto;margin-top:5px}
/* admin settings */
.setrow{display:flex;align-items:center;gap:8px;margin-top:6px;font-size:12.5px}
.setrow label{flex:0 0 130px;color:var(--mut)}
.setrow input{flex:1 1 auto;min-width:0;padding:6px 9px;border:1px solid var(--line);border-radius:8px;font-size:12.5px;font-family:ui-monospace,Menlo,Consolas,monospace}
.setbtns{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:9px}
.reg-row{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 9px;border:1px solid var(--line);border-radius:9px;margin-top:5px;font-size:12.5px}
.reg-row.spec{border-style:dashed;background:var(--bg)}
.reg-tog{border-color:var(--line)} .reg-tog.on{background:#DFF5EA;color:#127A4B;border-color:#DFF5EA}
.reg-add{margin-top:10px;padding-top:9px;border-top:1px dashed var(--line);display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.reg-add input{padding:6px 9px;border:1px solid var(--line);border-radius:8px;font-size:12px;width:150px}
.reg-add b{flex:1 1 100%}
.const-list{margin-top:5px;max-height:220px;overflow-y:auto;border:1px solid var(--line);border-radius:9px}
.const-row{display:flex;gap:8px;padding:5px 9px;border-bottom:1px solid var(--line);font-size:12px}
.const-row:last-child{border-bottom:none}
.const-row b{flex:0 0 86px;color:var(--brand)}
/* hazard verification table */
.hz-head{display:flex;align-items:center;gap:6px;margin-bottom:6px;font-size:13px}
.hz-tbl{border-collapse:collapse;width:100%;font-size:12px}
.hz-tbl th{background:var(--bg);color:var(--ink);text-align:start;padding:5px 8px;border:1px solid var(--line);font-weight:700}
.hz-tbl td{padding:5px 8px;border:1px solid var(--line);vertical-align:middle}
.hz-tbl .li{width:14px;height:14px}
/* live watch */
/* ═══ LIVE WATCH ═════════════════════════════════════════════════════════════════════════════════
   The camera is the page. It used to be a `max-width:880px` card centred in a 1920px viewport with
   ~400px of empty page beneath it and the frame itself missing entirely (see loadWatch()'s note and
   the main.py:1637 fix) — so the screen was three identical bordered rows of run-on cue text and a
   lot of nothing. Now: a status strip, a 16:9 stage that takes the width, a signal readout beside it,
   and the human-in-the-loop control on its own footing. */
.watch-top{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:12px;font-size:12.5px}
.watch-live{display:inline-flex;align-items:center;gap:7px;font-weight:700;color:var(--ok);
  background:color-mix(in srgb,var(--ok) 9%,#fff);border:1px solid color-mix(in srgb,var(--ok) 26%,#fff);
  border-radius:999px;padding:4px 12px;letter-spacing:.3px}
.watch-live i{width:7px;height:7px;border-radius:50%;background:var(--ok);animation:pulse 1.4s ease-in-out infinite}
.watch-path{display:inline-flex;align-items:center;gap:7px;color:var(--ink2);font-variant-numeric:tabular-nums}
.watch-path .li{width:15px;height:15px;color:var(--mut)}
.watch-arrow{color:var(--mut)}
/* PENDING_CONFIRMATION was in the payload and on no screen. A vision cue that a human has not yet
   promoted is the single most load-bearing fact on this page; it gets a badge. */
.watch-gate{display:inline-flex;align-items:center;gap:6px;font-weight:700;color:var(--warn);
  background:color-mix(in srgb,var(--warn) 10%,#fff);border:1px solid color-mix(in srgb,var(--warn) 28%,#fff);
  border-radius:9px;padding:4px 10px}
.watch-gate .li{width:14px;height:14px}
.watch-freshness{margin-inline-start:auto;display:inline-flex;align-items:center;gap:5px}
.watch-freshness .li{width:14px;height:14px}
.watch-grid{display:grid;grid-template-columns:minmax(0,1.75fr) minmax(300px,1fr);gap:14px;align-items:start}
@media(max-width:1080px){.watch-grid{grid-template-columns:1fr}}
/* THE STAGE — 16:9, dark, the frame cropped to fill it. A camera view that letterboxes into a white
   card looks like a document; one that fills a black stage looks like a camera. */
.watch-stage{position:relative;aspect-ratio:16/9;background:#191C1A;border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;box-shadow:var(--shadow)}
.watch-frame-host{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.watch-frame{width:100%;height:100%;object-fit:cover;display:block}
.watch-stage-foot{position:absolute;inset-inline:0;bottom:0;display:flex;align-items:center;
  justify-content:space-between;gap:10px;padding:8px 13px;font-size:11.5px;color:#EDEDED;
  background:linear-gradient(180deg,rgba(11,15,23,0) 0%,rgba(11,15,23,.82) 60%)}
.watch-stage-foot .meta{color:rgba(231,227,220,.66)}
/* the empty/awaiting state fills the stage instead of being a line of grey text under it */
.watch-blank{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  text-align:center;padding:34px 18px;color:var(--mut);font-size:13px}
.watch-stage .watch-blank{color:#8A968E}
.watch-stage .watch-blank b{color:#EDEDED}
.watch-blank .li{width:30px;height:30px;opacity:.8}
.watch-blank b{font-size:14px;color:var(--ink)}
#watchBody>.watch-blank{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  min-height:280px;justify-content:center;box-shadow:var(--shadow)}
/* THE READOUT — one tile per signal, each carrying the numbers that produced its state */
.watch-readout{display:grid;gap:10px;min-width:0}
.wsig{background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:11px 13px;
  box-shadow:var(--shadow-sm)}
.wsig-h{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink)}
.wsig-h .li{width:17px;height:17px;color:var(--mut)}
.wsig-cue{margin-inline-start:auto;font-size:11.5px;font-weight:700;letter-spacing:.2px;
  border-radius:999px;padding:3px 10px;background:var(--card2);color:var(--mut);border:1px solid var(--line)}
.wsig.moderate{border-color:color-mix(in srgb,var(--sev-high) 45%,var(--line))}
.wsig.moderate .wsig-cue{background:color-mix(in srgb,var(--sev-high) 12%,#fff);color:var(--sev-high);border-color:color-mix(in srgb,var(--sev-high) 32%,#fff)}
.wsig.moderate .wsig-h .li{color:var(--sev-high)}
.wsig.high{border-color:var(--sev-critical);background:color-mix(in srgb,var(--sev-critical) 4%,#fff)}
.wsig.high .wsig-cue{background:var(--sev-critical);color:#fff;border-color:var(--sev-critical)}
.wsig.high .wsig-h .li{color:var(--sev-critical)}
/* DEFERRED is a STATE, not an absence. «الدخان يحتاج VLM» is this system's doctrine working — the
   engine declining to claim what one frame's colour cannot support — and it was rendered as throwaway
   grey text, which reads as "nothing here". Dashed, labelled, with the reason attached. */
.wsig.defer{border-style:dashed;background:var(--bg)}
.wsig.defer .wsig-h{color:var(--ink2)}
.wsig.defer .wsig-cue{background:transparent;border-style:dashed}
.wsig-kv{display:grid;grid-template-columns:1fr auto;gap:3px 10px;margin:9px 0 0;font-size:12px}
.wsig-kv>div{display:contents}
.wsig-kv dt{color:var(--mut);min-width:0}
.wsig-kv dd{margin:0;text-align:end;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.wsig-kv .tr.rising{color:var(--sev-critical)}
.wsig-kv .tr.falling{color:var(--ok)}
.wsig-kv .tr.steady{color:var(--mut);font-weight:600}
.wsig-why{margin-top:8px;font-size:11.5px;line-height:1.6;color:var(--mut)}
/* the engine's own English string, shown as machine output rather than as UI copy it is not */
.wsig-raw{margin-top:5px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:10.5px;
  line-height:1.5;color:var(--mut);background:var(--bg);border-radius:7px;padding:5px 8px;
  border-inline-start:2px solid var(--line)}
/* THE GATE — one deliberate action zone; the button is disabled, never hidden (see loadWatch) */
.watch-action{margin-top:14px;background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:13px 16px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;box-shadow:var(--shadow-sm)}
.watch-action-btns{display:flex;gap:9px;flex-wrap:wrap}
.watch-act{font-weight:700;color:#fff;border:none;background:var(--mut);font-size:13px;padding:10px 16px}
.watch-act .li{width:16px;height:16px}
.watch-act[disabled]{background:var(--card2);color:var(--mut);border:1px solid var(--line);
  box-shadow:none;cursor:default}
.watch-act.fire{background:var(--sev-critical)}
.watch-act.safety{background:var(--sev-high)}
.watch-demo{background:transparent;color:var(--ink2);border:1px solid var(--line);font-size:13px;
  padding:10px 15px;box-shadow:none}
.watch-demo:hover{background:var(--card2);filter:none}
.watch-demo .li{width:15px;height:15px}
.watch-doctrine{flex:1 1 320px;margin:0;font-size:11.8px;line-height:1.65;color:var(--mut);
  display:flex;align-items:flex-start;gap:7px}
.watch-doctrine .li{width:15px;height:15px;flex:0 0 auto;margin-top:2px;color:var(--ok)}
.watch-doctrine b{color:var(--ink2)}
.watch-banner{display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--sev-critical);color:#fff;font-size:14px;padding:11px 14px;border-radius:12px;margin-bottom:12px;animation:tabIn .2s ease}
.watch-banner .li{width:18px;height:18px}
.watch-banner .mini{background:#fff;color:var(--sev-critical);border:none;font-weight:700}
.watch-banner.safety{background:var(--sev-high)}
.watch-banner.safety .mini{color:var(--sev-high)}
.agent-layer2{margin-top:14px;padding:10px 12px;background:var(--card);border:1px solid var(--line);border-radius:var(--r);display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.agent-layer2 .lucide{width:15px;height:15px;color:var(--mut)}
/* ---- user manual (accordion) ---- */
.manual{display:flex;flex-direction:column;gap:10px;max-width:1000px}
.man-sec{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.man-sec>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:9px;padding:14px 16px;font-size:15px;user-select:none}
.man-sec>summary::-webkit-details-marker{display:none}
.man-sec>summary::after{content:"‹";margin-inline-start:auto;color:var(--mut);font-size:18px;transform:rotate(-90deg);transition:transform .15s}
.man-sec[open]>summary::after{transform:rotate(-270deg)}
.man-sec>summary:hover{background:var(--bg)}
.man-sec .man-ic{display:inline-flex;color:var(--brand)}
.man-sec .man-ic .lucide{width:19px;height:19px}
.man-bd{padding:4px 16px 16px;border-top:1px solid var(--line)}
.man-p{font-size:14px;color:var(--ink);line-height:1.7;margin:10px 2px}
.man-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px;margin-top:6px}
.man-card{background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:12px;display:flex;flex-direction:column;gap:4px}
.man-card .man-ic{color:var(--brand)}.man-card .man-ic .lucide{width:20px;height:20px}
.man-card b{font-size:13.5px}
.man-row{padding:10px 0;border-bottom:1px solid var(--line)}
.man-row:last-child{border-bottom:none}
.man-row-h b{font-size:14px}
.man-row .meta{margin-top:2px;line-height:1.6}
.man-role{border:1px solid var(--line);border-inline-start:3px solid var(--rc,var(--brand));border-radius:var(--r);padding:11px 13px;margin:8px 0;background:var(--card)}
.man-role-h{display:flex;align-items:center;gap:8px}
.man-role-h b{font-size:14.5px}
.man-tag{margin-inline-start:auto;font-size:11px;font-weight:700;border-radius:999px;padding:2px 9px;border:1px solid var(--line);color:var(--mut)}
.man-tag.ok{color:var(--sev-low);border-color:#DFF5EA;background:#DFF5EA}
.man-perms{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.man-perm{font-size:11.5px;background:var(--bg);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:2px 8px}
.man-aglist{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:8px;margin-top:6px}
.man-ag{display:flex;gap:9px;align-items:flex-start;background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:9px 11px}
.man-ag .man-ic{color:var(--brand);flex:0 0 auto}.man-ag .man-ic .lucide{width:18px;height:18px}
.man-ag b{font-size:13px}
.man-dl{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px}
.man-dlbtn{display:flex;flex-direction:column;gap:2px;background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:12px 16px;text-decoration:none;color:var(--ink);box-shadow:0 1px 2px rgba(17,24,39,.05);min-width:230px}
.man-dlbtn:hover{border-color:var(--brand);box-shadow:0 2px 10px rgba(17,24,39,.1)}
.man-dlbtn .lucide{width:18px;height:18px;color:var(--brand);vertical-align:-3px}
.man-dlbtn b{font-size:13.5px}
.firebtn{background:var(--sev-critical);color:#fff;border-radius:7px;padding:5px 9px;font-size:12px;font-weight:700}
.dev-out{margin-top:9px;display:grid;gap:6px}
.cp-out table{width:100%;border-collapse:collapse}.cp-out td{border-bottom:1px solid var(--line);padding:4px 6px}
.defer{color:var(--warn)}

/* inputs / score */
.inputs label{display:block;font-size:12px;color:var(--mut);margin:7px 0 2px}
.inputs .rngval{font-size:12px}.checks{margin-top:8px;display:grid;gap:4px}
.checks label{display:flex;gap:6px;align-items:center;font-size:12px}
.recalc{margin-top:8px;font-size:12px;color:var(--ok);min-height:14px}
.gauge{display:flex;justify-content:center}
.score-dial{position:relative;width:132px;height:132px;margin:2px auto 6px}
.score-ring{position:absolute;inset:0;width:100%;height:100%}
.score-ring .sr-bg{fill:none;stroke:var(--line);stroke-width:10}
.score-ring .sr-fg{fill:none;stroke:var(--sev-info);stroke-width:10;stroke-linecap:round;
  stroke-dasharray:0 327;transform:rotate(-90deg);transform-origin:60px 60px;transition:stroke-dasharray .5s ease,stroke .3s}
.score-dial[data-sev=critical] .sr-fg{stroke:var(--sev-critical)}
.score-dial[data-sev=high] .sr-fg{stroke:var(--sev-high)}
.score-dial[data-sev=medium] .sr-fg{stroke:var(--sev-medium)}
.score-dial[data-sev=low] .sr-fg{stroke:var(--sev-low)}
.score-num{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.score .big{font-size:46px;font-weight:800;line-height:1}
.score .score-num .big{font-size:34px;letter-spacing:-.6px}
.score .of{color:var(--mut)}
.score .score-num .of{font-size:11px;margin-top:-1px}
.sev{margin-top:4px;font-weight:700}.sev.critical{color:var(--sev-critical)}.sev.high{color:var(--sev-high)}.sev.medium{color:var(--sev-medium)}.sev.low{color:var(--sev-low)}
.static{font-size:12px;color:var(--mut);margin-top:4px}
.factors{margin-top:8px;display:flex;flex-wrap:wrap;gap:5px}
.factors .f{font-size:12px;background:#FFE7DC;border:1px solid #FFE7DC;color:#9E2F00;border-radius:14px;padding:3px 8px}
/* A citation and a self-given name must not look the same. The clause is printed plainly; an id
   with nothing behind it is dimmed, italic and carries a warning mark — visible without reading,
   and the tooltip says which it is. Colour alone would fail a colour-blind operator, so the mark
   and the slant do the work. */
.factors .f small.cited{opacity:.85}
.factors .f small.uncited{opacity:.6;font-style:italic;text-decoration:underline dotted}

/* 3D twin */
/* `z-index:0` for the same reason the Leaflet container has it: make the box a stacking context so the
   overlays inside it (`.twin-detail` at 5, the loading veil) resolve against the twin and can never
   compete with the sticky command bar. `overflow:hidden` clips them visually but does not contain
   their z-index, and this canvas is the other full-bleed viewport on the dossier. */
.twin3d{height:300px;border-radius:10px;border:1px solid var(--line);background:#191C1A;overflow:hidden;position:relative;z-index:0}
.twin3d canvas{display:block}
.twin3d .loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--mut);font-size:12px}
/* max-height + scroll: the panel now carries a floor-plan drawing, and without a ceiling it grew past
   the bottom of the 300px twin and clipped its own content instead of scrolling it */
.twin-detail{position:absolute;top:10px;inset-inline-end:10px;width:248px;max-width:calc(100% - 20px);max-height:calc(100% - 20px);overflow-y:auto;overscroll-behavior:contain;background:rgba(255,255,255,.97);border:1px solid var(--line);border-radius:11px;box-shadow:var(--shadow);padding:11px 12px;font-size:12.5px;display:none;z-index:5}
.twin-detail.open{display:block}
.twin-detail .td-x{position:absolute;top:6px;inset-inline-end:6px;background:none;border:none;cursor:pointer;color:var(--mut);padding:2px;border-radius:6px;display:inline-flex}
.twin-detail .td-x:hover{background:var(--card2);color:var(--ink)}
.twin-detail .td-x .li{width:14px;height:14px}
.twin-detail .td-h{display:flex;align-items:center;gap:7px;font-size:14px;margin-bottom:2px}
.twin-detail .td-dot{width:11px;height:11px;border-radius:3px;flex:0 0 auto}
.twin-detail .td-status{font-weight:700;margin-bottom:1px}
.twin-detail .td-mean{margin-bottom:7px;line-height:1.35}
.twin-detail .td-row{display:flex;justify-content:space-between;gap:8px;padding:4px 0;border-top:1px solid var(--line)}
.twin-detail .td-k{color:var(--mut);flex:0 0 auto}
.twin-detail .td-v{text-align:end;display:inline-flex;align-items:center;gap:4px;justify-content:flex-end;flex-wrap:wrap}
.twin-detail .td-v .li,.twin-detail .td-row .li{width:14px;height:14px}
/* MINI interactive twin inside the what-if inputs */
.twin-mini{margin-top:10px;border-top:1px solid var(--line);padding-top:8px}
.twin-mini .tmini-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:6px}
.twin-mini .tmini-head b{font-size:12.5px}
.tmini-wrap{display:grid;grid-template-columns:96px 1fr;gap:10px;align-items:start}
.tmini-stack{display:flex;flex-direction:column;gap:2px;max-height:300px;overflow:auto;padding-inline-end:2px}
.tmini-fl{display:flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:5px;background:var(--card);
  padding:2px 5px;cursor:pointer;width:100%;text-align:start}
.tmini-fl:hover{border-color:color-mix(in srgb,var(--fc) 60%,var(--line))}
.tmini-fl.sel{border-color:#191C1A;box-shadow:0 0 0 1px #191C1A inset}
.tmini-fl[data-reach="1"]{border-bottom:2px solid #B4560A}
.tmini-fl .tmini-no{font-size:10.5px;color:var(--mut);width:20px;text-align:end;flex:0 0 auto}
.tmini-fl .tmini-bar{flex:1;height:12px;border-radius:3px;background:var(--fc);opacity:.85}
.tmini-fl .tmini-tag{flex:0 0 auto;color:#CC3D00;display:inline-flex}
.tmini-fl .tmini-tag .li{width:12px;height:12px}
.tmini-detail{font-size:12px;align-self:stretch}
.tmini-detail .td-h{display:flex;align-items:center;gap:6px;font-size:13px;margin-bottom:2px}
.tmini-detail .td-dot{width:10px;height:10px;border-radius:3px}
.tmini-detail .td-status{font-weight:700}
.tmini-detail .td-mean{margin-bottom:6px;line-height:1.35}
.tmini-detail .td-row{display:flex;justify-content:space-between;gap:8px;padding:3px 0;border-top:1px solid var(--line)}
.tmini-detail .td-k{color:var(--mut);flex:0 0 auto}
.tmini-detail .td-v{text-align:end;display:inline-flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}
.tmini-detail .td-v .li,.tmini-detail .td-row .li{width:13px;height:13px}

/* phases/priority/brief/tasks */
/* Evac phases — plain field-readable, numbered, with a short "why"; rule demoted to a subtle citation */
.phases{list-style:none;margin:0;padding:0;display:grid;gap:6px;font-size:12.5px}
.phases li{margin:0;background:var(--card2);border:1px solid var(--line);border-radius:9px;padding:7px 9px;display:flex;flex-direction:column;cursor:pointer;transition:border-color .12s ease}
.phases li:hover{border-color:color-mix(in srgb,var(--responder) 45%,var(--line))}
.phases li.open{background:var(--card);border-color:var(--responder)}
.phases li:focus-visible{outline:2px solid var(--responder);outline-offset:2px}
.ph-top{display:flex;gap:9px;align-items:flex-start}
.ph-n{flex:0 0 auto;width:20px;height:20px;border-radius:50%;background:var(--responder);color:#fff;font-weight:700;font-size:11px;display:inline-flex;align-items:center;justify-content:center;margin-top:1px}
.ph-b{flex:1;display:flex;flex-direction:column;gap:1px}.ph-b b{font-weight:600;color:var(--ink)}
.ph-why{color:var(--mut);font-size:11px}
.phases .r{flex:0 0 auto;color:var(--eye);font-size:10.5px;opacity:.7;align-self:center}
.ph-caret{flex:0 0 auto;color:var(--mut);display:inline-flex;align-self:center;transition:transform .15s ease}
.ph-caret .li{width:15px;height:15px}
.phases li.open .ph-caret{transform:rotate(180deg)}
.phd{margin-top:8px;padding-top:8px;border-top:1px dashed var(--line);font-size:12px}
.phd-why{margin-bottom:7px;line-height:1.4}.phd-why .li{width:14px;height:14px;vertical-align:-2px}
.phd-row{display:flex;justify-content:space-between;gap:8px;padding:3px 0}
.phd-k{color:var(--mut)}.phd-v{text-align:end}
.phd-floors{display:flex;flex-wrap:wrap;gap:4px;margin:5px 0}
.ph-fl{font-size:11px;background:var(--card2);border:1px solid var(--line);border-radius:6px;padding:1px 7px;color:var(--ink)}
.ph-fl.more{color:var(--mut)}
.phd-rule{margin-top:7px;padding:6px 8px;background:color-mix(in srgb,var(--eye) 7%,#fff);border:1px solid var(--line);border-radius:7px;line-height:1.4}
.phd-rule .li{width:14px;height:14px;vertical-align:-2px;color:var(--eye)}
.tmini-fl.phase{box-shadow:0 0 0 2px var(--responder) inset}
/* AI-trust internals (adversarial verify: confidence scores, CV reliability) — operator needs the
   DECISION not the model's self-assessment, so hide the card (it still drives the twin aerial layer). */
#verifyAgent{display:none}
/* AI fire-confirmation badge */
.ai-confirm{border:1px solid var(--ac);border-inline-start:4px solid var(--ac);border-radius:10px;background:color-mix(in srgb,var(--ac) 7%,#fff);padding:9px 11px;margin-bottom:10px}
.ai-confirm .aic-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ai-confirm .aic-dot{width:10px;height:10px;border-radius:50%;background:var(--ac);flex:0 0 auto;box-shadow:0 0 0 3px color-mix(in srgb,var(--ac) 22%,transparent)}
.ai-confirm .aic-label{font-size:14px;color:var(--ink)}
.ai-confirm .aic-act{margin-inline-start:auto;color:#fff;font-size:11.5px;font-weight:700;border-radius:7px;padding:2px 9px;display:inline-flex;align-items:center;gap:4px}
.ai-confirm .aic-act .li{width:13px;height:13px}
.ai-confirm .aic-tier{margin-top:3px}
.ai-confirm .aic-llm{margin-top:8px;border-radius:8px;background:color-mix(in srgb,var(--eye) 8%,#fff);border:1px solid color-mix(in srgb,var(--eye) 24%,transparent);padding:7px 9px}
.ai-confirm .aic-llm-h{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:800;color:var(--eye)}
.ai-confirm .aic-llm-h .li,.ai-confirm .aic-llm-h svg{width:14px;height:14px}
.ai-confirm .aic-llm-tag{margin-inline-start:auto;font-weight:700;font-size:10px;color:var(--eye);background:color-mix(in srgb,var(--eye) 15%,transparent);border-radius:6px;padding:1px 7px}
.ai-confirm .aic-llm-body{margin-top:5px;line-height:1.55;white-space:pre-line}
/* RFI — fire-official ⇄ building-person questions */
.rfi-card{margin-bottom:12px}
.rfi-item{border:1px solid var(--line);border-radius:10px;padding:8px 10px;margin-top:8px;background:var(--card2)}
.rfi-item.pending{border-inline-start:4px solid var(--sev-high)}
.rfi-item.done{border-inline-start:4px solid var(--sev-low)}
.rfi-q{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:13.5px;color:var(--ink)}
.rfi-q .li,.rfi-q svg{width:14px;height:14px;flex:0 0 auto}
.rfi-a{margin-top:6px;display:flex;align-items:center;gap:6px;color:var(--ink2);font-size:13px}
.rfi-answer{margin-top:7px;display:flex;gap:6px;flex-wrap:wrap}
/* ONE TAP, AND BIG ENOUGH FOR A THUMB. These are pressed by somebody holding a phone in a stairwell,
   so they are sized for that rather than for a desk: 44px is the smallest target a thumb hits
   reliably. Yes and No carry the colours the rest of the console already uses for safe and severe,
   and they wrap onto their own line before the text box is squeezed to nothing on a narrow screen. */
.rfi-yn{min-height:44px;padding:7px 16px;border:none;border-radius:8px;font-weight:800;cursor:pointer;color:#fff}
.rfi-yn.yes{background:var(--sev-low)}
.rfi-yn.no{background:var(--sev-high)}
.rfi-yn:active{filter:brightness(.9)}
.rfi-answer input,.rfi-compose input,.rfi-compose select{flex:1;min-width:0;padding:7px 9px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink);font:inherit}
.rfi-answer button,.rfi-compose button{padding:7px 14px;border:none;border-radius:8px;background:var(--brand);color:#fff;font-weight:700;cursor:pointer}
.rfi-compose{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:8px}
/* agentic-AI reading of an answer */
.rfi-ai{margin-top:7px;border-radius:8px;padding:6px 9px;font-size:12.5px;line-height:1.5;
  background:color-mix(in srgb,var(--eye) 8%,#fff);border:1px solid color-mix(in srgb,var(--eye) 22%,transparent);color:var(--ink2)}
.rfi-ai .li,.rfi-ai svg{width:14px;height:14px;vertical-align:-2px}
.rfi-ai b{color:var(--eye)}
.rfi-ai.sev-critical{background:color-mix(in srgb,var(--sev-critical) 12%,#fff);border-color:var(--sev-critical)} .rfi-ai.sev-critical b{color:var(--sev-critical)}
.rfi-ai.sev-high{background:color-mix(in srgb,var(--sev-high) 12%,#fff);border-color:var(--sev-high)} .rfi-ai.sev-high b{color:var(--sev-high)}
.rfi-ai.sev-medium{background:color-mix(in srgb,var(--sev-medium) 14%,#fff);border-color:var(--sev-medium)} .rfi-ai.sev-medium b{color:#7A4A08}
.rfi-ai.sev-none b,.rfi-ai.sev-low b{color:var(--sev-low)}
/* contextual AI read inside the twin floor-detail popup */
.twin-detail .td-ai{margin-top:8px;border-top:1px solid var(--line);padding-top:7px}
.twin-detail .td-ai-h{display:flex;align-items:center;gap:5px;font-size:11.5px;font-weight:800;color:var(--eye)}
.twin-detail .td-ai-h .li,.twin-detail .td-ai-h svg{width:13px;height:13px}
.twin-detail .td-ai-b{margin-top:4px;font-size:12px;line-height:1.5;color:var(--ink2)}
/* the floor's own DRAWING inside the floor-detail popup (3D panel AND the mini twin) */
.td-plan{margin-top:8px;border-top:1px solid var(--line);padding-top:7px}
.td-plan-h{display:flex;align-items:center;gap:5px;font-size:11.5px;font-weight:800;color:var(--ink);flex-wrap:wrap}
.td-plan-h .li,.td-plan .li{width:13px;height:13px}
.td-plan-fire{display:inline-flex;align-items:center;gap:3px;color:var(--sev-critical);font-weight:800}
.td-plan-f{margin:6px 0 0}
.td-plan-f figcaption{font-size:11px;color:var(--mut);margin-bottom:3px}
.td-plan-img{display:block;width:100%;max-height:160px;object-fit:contain;background:#fff;border:1px solid var(--line);border-radius:8px;cursor:zoom-in}
/* SUBSTITUTED drawing: this is another floor's plan. It must be impossible to mistake for this one —
   loud amber banner, amber frame, and the substitute floor number repeated in the caption. */
.td-plan-sub{margin:6px 0 0;padding:6px 8px;border-radius:8px;background:color-mix(in srgb,var(--sev-medium) 16%,#fff);border:1px solid var(--sev-medium);color:#7A4A08;font-size:11.5px;line-height:1.4;display:flex;gap:5px;align-items:flex-start}
.td-plan-sub .li{width:13px;height:13px;flex:0 0 auto;margin-top:1px}
.td-plan-body.is-sub .td-plan-img{border:2px dashed var(--sev-medium)}
.td-plan-sub-f{color:#7A4A08}
.td-plan-open{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap}
/* agentic auto-escalation banner (commander) */
#rfiEscBanner{margin:8px 0}
.rfi-esc{border-radius:12px;padding:11px 13px;margin-bottom:8px;color:#fff;background:var(--sev-high);box-shadow:0 2px 10px rgba(0,0,0,.12)}
.rfi-esc.sev-critical{background:var(--sev-critical)}
.rfi-esc-h{display:flex;align-items:center;gap:7px;font-size:14px;font-weight:800}
.rfi-esc-h .li,.rfi-esc-h svg{width:17px;height:17px}
.rfi-esc-sev{margin-inline-start:auto;font-size:11px;font-weight:800;background:#ffffff2e;border-radius:6px;padding:2px 8px;letter-spacing:.5px}
.rfi-esc-b{margin-top:5px;font-size:13.5px;line-height:1.5}
.rfi-esc-b .meta,.rfi-esc-src{color:#ffffffcc !important}
.rfi-esc-src{margin-top:4px;font-size:11.5px}
.rfi-esc-ack{margin-top:9px;background:#fff;color:var(--ink);border:none;border-radius:8px;padding:7px 15px;font-weight:800;cursor:pointer}
.ai-confirm .aic-sig{margin-top:6px;display:flex;flex-wrap:wrap;gap:4px;align-items:center}
.ai-confirm .aic-note{margin-top:5px}
/* Preventive inspection */
.pv-tabs{display:flex;gap:6px;margin:4px 0 12px;flex-wrap:wrap}
.pv-tab{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;background:var(--card2);border:1px solid var(--line);border-radius:9px;padding:6px 12px;cursor:pointer;color:var(--ink)}
.pv-tab:hover{border-color:color-mix(in srgb,var(--eye) 40%,var(--line))}
.pv-tab.active{background:color-mix(in srgb,var(--eye) 12%,#fff);border-color:var(--eye);color:var(--eye);font-weight:600}
.pv-tab .li{width:15px;height:15px}
.pvr-head{margin-bottom:8px}
.pvr-appt{margin:8px 0;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--card2)}
.pvr-appt .li{width:15px;height:15px;vertical-align:-2px}
.ovl-bd h4{margin:14px 0 4px;font-size:13px}
.pvr-recs{margin:4px 0;padding-inline-start:18px}.pvr-recs li{margin:3px 0}.pvr-recs .li{width:13px;height:13px;vertical-align:-2px}
@media print{ body *{visibility:hidden} #pvPrintArea,#pvPrintArea *{visibility:visible} #pvPrintArea{position:absolute;inset:0} }
.priority{margin-top:8px;font-size:12px;color:var(--mut)}
.pri-lead{display:flex;gap:6px;align-items:flex-start;color:var(--ink);font-size:12.5px;background:#FBEFD6;border:1px solid #FBEFD6;border-radius:9px;padding:7px 9px}
.pri-lead .li{width:15px;height:15px;color:var(--sev-high);flex:0 0 auto;margin-top:1px}.pri-lead b{font-weight:600}
.pri-facts{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px}
.pri-facts span{display:inline-flex;align-items:center;gap:4px;color:var(--mut)}
.pri-facts .li{width:13px;height:13px}
.brief{white-space:pre-wrap;background:#FFFFFF;border:1px solid var(--line);border-radius:10px;padding:11px;color:#232A25;font-size:13px;min-height:80px}
.badge{font-size:12px;border-radius:12px;padding:3px 8px;border:1px solid var(--line)}
.badge.live{background:#DFF5EA;color:#127A4B;border-color:#DFF5EA}.badge.fb{background:#FBEFD6;color:#7A4A08;border-color:#FBEFD6}.badge.ext{background:#FFE7DC;color:#9E2F00;border-color:#FFE7DC}
.tasks{list-style:none;margin:0;padding:0;display:grid;gap:7px}
.tasks li{background:var(--card2);border:1px solid var(--line);border-radius:10px;padding:9px;display:flex;gap:9px;align-items:center;justify-content:space-between}
.tasks .id{font-weight:700;color:var(--responder)}.tasks .r{font-size:12px;color:var(--eye)}
.gate{font-weight:700;border-radius:8px;padding:6px 10px;font-size:12px}
.gate.t1{background:#F2F2F2;color:#1E6F9F}.gate.t2{background:#FFE7DC;color:#CC3D00}.gate.authed{background:var(--ok);color:#fff}
/* decision-gate confirm / receipt / revoke (life-safety, human-in-the-loop) */
.gate-cf,.gate-rec{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.gate-cf-q{font-size:12px;color:var(--warn)}
.gate-x,.gate-revoke{font-weight:700;border-radius:8px;padding:6px 10px;font-size:12px;background:var(--card2);color:var(--mut);border:1px solid var(--line);cursor:pointer}
.gate-revoke:hover,.gate-x:hover{filter:brightness(1.2);border-color:var(--responder)}
.rec-by{font-size:12px;color:var(--ok)}
.audit{margin-top:9px;font-size:12px;color:var(--mut);white-space:pre-wrap}
.cv-card{background:var(--card2);border:1px solid var(--line);border-radius:8px;padding:8px;margin-top:6px;font-size:12px;display:flex;gap:9px;align-items:center;justify-content:space-between}
.cv-card .meta{color:var(--mut);font-size:12px}.pending{color:var(--warn)}.confirmed{color:var(--ok)}

/* admin */
.utable{width:100%;border-collapse:collapse;font-size:12.5px}
.utable th{font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--mut);
  background:var(--card2);position:sticky;top:0;z-index:1}
.utable th,.utable td{border-bottom:1px solid var(--line);padding:8px 10px;text-align:start}
.utable tbody tr{transition:background .1s}
.utable tbody tr:hover{background:#FFFFFF}
.utable .role{font-size:12px;background:var(--card2);border:1px solid var(--line);border-radius:12px;padding:2px 8px}
.auditlog{font-size:12px;max-height:280px;overflow:auto}
.auditlog .a{border-bottom:1px solid var(--line);padding:5px 0;display:flex;gap:8px;justify-content:space-between}
.auditlog .act{color:var(--responder)}

/* drill-down modal */
.drill{position:fixed;inset:0;z-index:60;background:rgba(4,8,18,.72);backdrop-filter:blur(3px);overflow:auto;padding:24px}
.drill-card{max-width:1100px;margin:0 auto;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px;box-shadow:var(--shadow)}
.drill-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:10px}
.dr-name{font-size:18px;font-weight:800}
.dr-close{background:#232A25;color:#FFE7DC;font-size:16px;border-radius:8px;padding:4px 12px}
.emo-mk .emo{font-size:17px;line-height:24px;text-align:center;filter:drop-shadow(0 0 3px #191C1A)}
.ctx{display:grid;gap:6px}
.ctx-row{background:var(--card2);border:1px solid var(--line);border-radius:8px;padding:7px 10px;font-size:12.5px}
.ctx-row.hazard{background:#FFE7DC;border-color:#FFE7DC;color:#9E2F00}
.drill .leaflet-map.inc{height:280px}
.drill .factors{margin-top:8px}
/* floor strip (used in drill twin) */
.twin{display:flex;flex-direction:column;gap:2px;max-height:260px;overflow:auto}
.twin .fl{display:flex;align-items:center;gap:8px;font-size:12px}
.twin .bar{height:13px;border-radius:3px;flex:1}
.twin .num{width:24px;color:var(--mut);text-align:end}
.bar.focus{background:var(--red)}.bar.smoke{background:var(--orange)}.bar.threat{background:var(--yellow)}
.bar.evac{background:var(--responder)}.bar.refuge{background:var(--violet)}.bar.safe{background:var(--green);opacity:.5}

/* ===== scope breadcrumb — navigation by PERSON / scope (not function) ===== */
/* ═══ the scope spine ═════════════════════════════════════════════════════════════════════════
   ONE recessed track holding both crumbs and the «‹» between them. It used to be a bare
   `flex-wrap:wrap` row sharing the header's only line, and it wrapped: measured at 1920px the
   overview crumb sat at y=16, the separator at y=22 and the incident crumb at y=58 — the separator
   pointing at a crumb on the row below it. A breadcrumb that wraps is not a breadcrumb.
   nowrap + a shared track makes that structurally impossible; the crumbs ellipsis instead. */
.scopebar{display:flex;align-items:center;gap:3px;flex-wrap:nowrap;min-width:0;
  background:var(--hdr-raise);border:1px solid var(--hdr-line);border-radius:13px;padding:3px;
  box-shadow:var(--shadow-sm)}
.crumb{display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:var(--ink);
  border:1px solid var(--line);background:var(--card);border-radius:10px;padding:6px 12px;font-size:13px;
  transition:filter .15s,background .15s,border-color .15s}
.crumb:hover{background:var(--card2);border-color:#D8D0C2}
.crumb.active{background:var(--brand);color:#fff;border-color:var(--brand);font-weight:600}
.crumb-inc.active{background:var(--ink);color:#fff;border-color:var(--ink)}
.crumb-sep{color:var(--mut);font-size:14px;flex:0 0 auto}
.scopebar .crumb{border-color:transparent;background:transparent;border-radius:10px;padding:5px 12px;
  color:var(--ink2);font-size:12.5px;font-weight:600;
  min-width:0;max-width:16.5rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.scopebar .crumb:hover{background:var(--hdr-tint);color:var(--brand);box-shadow:none}
/* WHERE YOU ARE, in the emirate's green — the loudest thing in the bar after the seal, which is
   right: this app navigates by scope, not by function. */
.scopebar .crumb.active{background:var(--brand);border-color:transparent;color:#fff;
  box-shadow:0 1px 8px color-mix(in srgb,var(--brand) 30%,transparent)}
.scopebar .crumb-inc.active{background:var(--danger);border-color:transparent;color:#fff;
  box-shadow:0 1px 8px color-mix(in srgb,var(--danger) 30%,transparent)}
.scopebar .crumb-sep{color:var(--mut);opacity:.6}
.gear{text-decoration:none}
.chip-lbl{font-size:12.5px;line-height:1}
a:focus-visible.crumb{outline-offset:3px}

/* ═══ header breakpoints ══════════════════════════════════════════════════════════════════════
   Shed row 1 before row 2: the subtitle, the build string and the clock are all readable elsewhere
   (page title, /api/health, a refresh), while the LLM state dot is the one thing an operator needs
   mid-incident, so it survives every width. */
@media(max-width:1280px){
  .topbar .brand .sub{display:none}
  #st-build,#st-fresh{display:none}
  .tb-status{padding-inline-end:6px}
}
@media(max-width:1180px){ .chip-lbl{display:none} .topbar .chip.gear{padding:5px 9px} }
@media(max-width:860px){
  /* the gutter is NOT narrowed here: `.band` keeps its 24px at every width, and the whole point of
     the header's max() gutter is that the two share one column. Narrowing one of them re-introduces
     exactly the misalignment it was written to remove. */
  .topbar{grid-template-columns:1fr auto;
          grid-template-areas:"brand session" "scope scope" "nav nav";
          column-gap:10px}
  .topbar .scopebar{justify-self:stretch}
  .scopebar .crumb{max-width:none;flex:1 1 auto;justify-content:center}
}

/* ===== triage list — ranked active fires ===== */
.triage{display:grid;gap:6px;max-height:360px;overflow:auto}
.trow{display:flex;align-items:center;gap:9px;background:var(--card2);border:1px solid var(--line);
  border-radius:10px;padding:8px 10px;cursor:pointer;transition:border-color .15s,filter .15s}
.trow:hover{background:#fff;border-color:#D8D0C2;box-shadow:var(--shadow-sm);transform:translateY(-1px)}
.trow{transition:background .12s,border-color .12s,box-shadow .12s,transform .1s;position:relative;overflow:hidden}
/* severity edge: the row's threat level reads at a glance (shape glyph stays for colorblind safety) */
.trow::before{content:"";position:absolute;inset-inline-start:0;top:0;bottom:0;width:3px;background:transparent}
.trow:has(.tsev.critical)::before{background:var(--sev-critical)}
.trow:has(.tsev.high)::before{background:var(--sev-high)}
.trow:has(.tsev.medium)::before{background:var(--sev-medium)}
.trow:has(.tsev.low)::before{background:var(--sev-low)}
.tsev{flex:0 0 auto;width:16px;text-align:center;font-size:14px;line-height:1}   /* shape glyph, not color-only */
.tsev.critical{color:var(--sev-critical);animation:sevpulse 2.2s ease-in-out infinite}
@keyframes sevpulse{0%,100%{opacity:1}50%{opacity:.45}}
.tsev.high{color:var(--sev-high)}
.tsev.medium{color:var(--sev-medium)}.tsev.low{color:var(--sev-low)}
.tname{flex:1;display:flex;flex-direction:column;line-height:1.35}.tname small{color:var(--mut)}
.tprio{display:flex;flex-direction:column;align-items:center;line-height:1.1;min-width:42px}
.tprio b{font-size:17px;font-weight:800}.tprio small{font-size:12px;color:var(--mut)}
.tprio.critical b{color:var(--sev-critical)}.tprio.high b{color:var(--sev-high)}.tprio.medium b{color:var(--sev-medium)}.tprio.low b{color:var(--sev-low)}
.trisk{font-size:12px;color:var(--mut);min-width:46px;text-align:center;position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:40px}
.trisk .kpi-share{inset:0;opacity:.95}
.trisk .trisk-n{position:relative;z-index:1;font-weight:800;font-variant-numeric:tabular-nums;color:var(--ink);line-height:1}
/* human-verified fire that the scorer hasn't scored yet — the dash is a real state, not a gap */
.trisk.unscored{opacity:.55}
.tscore{font-weight:800;font-size:16px;margin:0}
/* incident-priority badge in the dossier header */
.inc-head-r{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.incprio{font-size:12px;background:var(--card2);border:1px solid var(--line);border-radius:10px;padding:5px 10px}
.incprio b{font-size:14px}
.incprio .prio-bd{color:var(--mut);margin-inline-start:6px}

/* ===== incident dossier — the assistant MIND as a flow (perceive -> reason -> respond) ===== */
.inc-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.flowbar{display:flex;align-items:center;gap:8px;margin:2px 0 14px;flex-wrap:wrap}
.flowstep{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:700;
  border:1px solid var(--line);border-radius:18px;padding:4px 11px;background:var(--card2)}
.flowstep.eye{color:var(--eye);border-color:var(--eye)}
.flowstep.thinker{color:#B4560A;border-color:#B4560A}
.flowstep.responder{color:var(--responder);border-color:var(--responder)}
.flowstep.notify{color:#CC3D00;border-color:#CC3D00}
.inc-tabs .flowstep.notify.active{background:#CC3D00;border-color:#CC3D00;color:#fff}
.flowsec.notify{border-inline-start-color:#CC3D00}
.flowarrow{color:var(--mut);font-size:14px}
/* ---- incident INSPECTOR tabs ---- */
/* Parks directly beneath the command bar — see --hdr-h. `z-index:30` keeps it UNDER the bar (60) and
   over the dossier, which is the order a reader expects when both are pinned. */
.inc-tabs{position:sticky;top:var(--hdr-h);z-index:30;background:var(--bg);gap:10px;padding:9px 0 10px;margin:0 0 16px;border-bottom:1px solid var(--line);counter-reset:pstep}
.inc-tabs .flowstep{cursor:pointer;font-size:14px;font-weight:700;border-radius:13px;padding:9px 18px;background:var(--card);color:var(--ink);border:1px solid var(--line);box-shadow:0 1px 2px rgba(17,24,39,.05);transition:border-color .12s,box-shadow .12s,background .12s;display:inline-flex;align-items:center;gap:8px}
.inc-tabs .flowstep::before{counter-increment:pstep;content:counter(pstep);flex:0 0 auto;width:21px;height:21px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;font-size:11.5px;font-weight:800;
  background:var(--card2);border:1px solid var(--line);color:var(--mut)}
.inc-tabs .flowstep.active::before{background:rgba(255,255,255,.28);border-color:transparent;color:#fff}
.inc-tabs .flowstep:hover{border-color:#C9D3CC}
.inc-tabs .flowstep [data-licon],.inc-tabs .flowstep .li{width:18px;height:18px}
.inc-tabs .flowstep.eye.active{background:var(--eye);border-color:var(--eye);color:#fff}
.inc-tabs .flowstep.thinker.active{background:#B4560A;border-color:#B4560A;color:#fff}
.inc-tabs .flowstep.responder.active{background:var(--responder);border-color:var(--responder);color:#fff}
.inc-tabs .flowstep.active{box-shadow:0 3px 10px rgba(17,24,39,.13)}
.tabpanel{display:none}
.tabpanel.active{display:block;animation:tabIn .16s ease}
@keyframes tabIn{from{opacity:.35;transform:translateY(3px)}to{opacity:1;transform:none}}
/* nested sub-tabs INSIDE the Eye tab (it was too long — split by relatedness)
   ‹الإدارة› تلبس الشكل نفسه بلونها (`.adm-tab`) — الشكل مُعرَّف مرّةً واحدة هنا لا مرّتين، والفارق
   الوحيد هو لهجة اللون في كتلة `#adminTabs` أدناه. `.dash-tab`/`.pv-tab` مقاسٌ أصغر لتبويبٍ ثانوي. */
.eye-subtabs,.adm-tabs{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px}
.eye-subtab,.adm-tab{cursor:pointer;font-size:13px;font-weight:700;border-radius:11px;padding:7px 15px;background:var(--card2);color:var(--ink2);border:1px solid var(--line);display:inline-flex;align-items:center;gap:7px;transition:background .12s,color .12s,border-color .12s}
.eye-subtab [data-licon],.eye-subtab .li,.adm-tab [data-licon],.adm-tab .li{width:16px;height:16px}
.eye-subtab:hover{border-color:var(--eye)}
.eye-subtab.active{background:var(--eye);border-color:var(--eye);color:#fff}
.eye-subpanel{display:none}
.eye-subpanel.active{display:block;animation:tabIn .16s ease}
/* 🗂️ شريط أقسام «الإدارة». الصفحة كانت ١٥١١٢ بكسل في تمريرة واحدة (١٦ شاشة)، فلو مرّ الشريط مع
   المحتوى لضاع القسم بعد أول شاشة — يَركن تحت شريط القيادة تمامًا كـ`.inc-tabs`، وبالعمق نفسه (٣٠)
   ليبقى *تحت* الشريط (٦٠) لا فوقه. اللون `--admin` هو لون هذا القسم أصلًا (انظر `#admin .band-title`). */
#adminTabs{position:sticky;top:var(--hdr-h);z-index:30;background:var(--bg);padding:9px 0 10px;margin:0 0 16px;border-bottom:1px solid var(--line)}
/* التبويب زرٌّ، والقاعدة العامة `button:hover` تُلبسه ظلّ البطاقة (`--shadow`) ومرشّح إضاءة —
   ظلُّ بطاقةٍ كاملة تحت قرصٍ ارتفاعه ٣٢ بكسل، ومرشّحٌ لا يُرى أصلًا على القرص شبه الأسود. أوقفهما هنا
   وأعطِ كل حالةٍ استجابتها الصحيحة. */
#adminTabs .adm-tab{box-shadow:none;filter:none}
/* المرور على تبويبٍ غير مُختار كان يرسم حدًّا بلون `--admin` نفسه — أي بلون التبويب المختار تمامًا،
   فيبدو تبويبان مُختارَين في آنٍ واحد. المرور يرفع البطاقة قليلًا، ولا يدّعي الاختيار. */
#adminTabs .adm-tab:hover{background:var(--card);color:var(--ink);border-color:color-mix(in srgb,var(--admin) 32%,var(--line))}
#adminTabs .adm-tab.active{background:var(--admin);border-color:var(--admin);color:#fff}
/* والمرور على التبويب المختار كان بلا أثرٍ مرئيّ إطلاقًا (`brightness(.97)` على #232A25 لا يُرى) */
#adminTabs .adm-tab.active:hover{background:color-mix(in srgb,var(--admin) 84%,#fff);border-color:color-mix(in srgb,var(--admin) 84%,#fff);color:#fff}
#adminTabs .adm-tab:focus-visible{outline-offset:3px}

/* 🗂️ شريط أقسام «سجل المباني» — نفس علاج «الإدارة» لنفس الداء، ولنفس السبب.
   ────────────────────────────────────────────────────────────────────────────────────────────────
   بطاقةُ مبنًى واحد كانت ٩٣١٧ بكسل في تمريرة واحدة (ثلاث عشرة شاشة)، ملفُّ الـFRA وحده ٣٤٧٠ منها —
   وموضعُه الثاني، أي بين الترويسة وكلِّ ما جاء المشغّل ليحرّره. والترتيبُ كان ترتيبَ استيرادٍ لا
   ترتيبَ إخلاء: مستندٌ مرجعيّ ثمّ رفعُ مجسَّمٍ ثلاثيّ الأبعاد فوق سُكّان البرج.
   القسّمة **عرضٌ فقط**: البطاقات كما هي بمعرّفاتها ومنادِيها، تُخفى هنا بالـCSS ولا تُحذف من الشجرة،
   فيظلّ كلُّ مُصيِّرٍ يخاطب `#brBody …` واجدًا حقولَه (`.r_need`, `#fp_body`, `#br_prot_body` …).
   واللون `--eye` ليس اختيارًا جديدًا: هو لون هذا القسم أصلًا (`#buildreg .br-form button`).
   والشرط الذي يجعل التبويب مسموحًا به أصلًا في نظام حياة: **التبويب يُخفي بطاقةً، ولا يُخفي خطرًا.**
   كلُّ عطلٍ قائم ومخرجٍ لم يُفحص وساكنٍ أوّلَ بالإخلاء يظهر شارةً على تبويبه قبل أن يُفتح — انظر
   `brTabBadge` في app.js. شريطٌ بلا شارات يعني: لا شيء ينتظر خلفه. */
#brTabs{position:sticky;top:var(--hdr-h);z-index:30;background:var(--bg);padding:9px 0 10px;margin:0 0 16px;border-bottom:1px solid var(--line)}
#brTabs:empty{display:none}
#brTabs .adm-tab{box-shadow:none;filter:none}
#brTabs .adm-tab:hover{background:var(--card);color:var(--ink);border-color:color-mix(in srgb,var(--eye) 32%,var(--line))}
#brTabs .adm-tab.active{background:var(--eye);border-color:var(--eye);color:#fff}
#brTabs .adm-tab.active:hover{background:color-mix(in srgb,var(--eye) 84%,#fff);border-color:color-mix(in srgb,var(--eye) 84%,#fff);color:#fff}
#brTabs .adm-tab:focus-visible{outline-offset:3px}
/* الشارة تقول ما ينتظر خلف التبويب. النغمة من سلّم الخطورة وحده — لا عائلةَ لونٍ أخرى تُشفِّر خطورة. */
.br-badge{min-width:19px;height:19px;padding:0 6px;border-radius:999px;font-size:11px;font-weight:800;line-height:1;
  display:inline-flex;align-items:center;justify-content:center;font-variant-numeric:tabular-nums;
  background:var(--card2);color:var(--mut);border:1px solid var(--line)}
.br-badge.warn{background:color-mix(in srgb,var(--sev-medium) 14%,#fff);color:var(--sev-medium);border-color:color-mix(in srgb,var(--sev-medium) 34%,#fff)}
.br-badge.hot{background:color-mix(in srgb,var(--sev-critical) 14%,#fff);color:var(--sev-critical);border-color:color-mix(in srgb,var(--sev-critical) 34%,#fff)}
/* على التبويب المُختار الخلفيّةُ مصمتة، فالشارة تُقلَب إلى أرضٍ بيضاء ويبقى لونُ الخطورة على الرقم
   نفسه — لأنّ فتحَ التبويب لا يُلغي الخطر الذي أعلنته الشارة. */
#brTabs .adm-tab.active .br-badge{background:#fff;border-color:transparent;color:var(--eye)}
#brTabs .adm-tab.active .br-badge.warn{color:var(--sev-medium)}
#brTabs .adm-tab.active .br-badge.hot{color:var(--sev-critical)}
/* الإظهار والإخفاء. البطاقة تبقى في الشجرة؛ `.hidden` الخاص بالصلاحيات يعلوها بـ`!important` فيظلّ
   ما منعته الصلاحية ممنوعًا داخل تبويبه المفتوح. */
#buildreg [data-brtab]{display:none}
#buildreg [data-brtab].brtab-on{display:block;animation:tabIn .16s ease}
#buildreg #brHead:empty{display:none}
/* ترويسةُ المبنى هي المرجع الثابت فوق التبويبات: بطاقةٌ واحدة، بلا هامشٍ سفليٍّ مضاعَف تحتها. */
#brHead>.card{margin-bottom:0}

/* بطاقةٌ أخفتها الصلاحية (`admin:all` وحده) كانت تترك عمودًا فارغًا بجانب أختها — اطوِ الصفّ لعمودٍ واحد */
#admin .grid.two:has(> .card.hidden){grid-template-columns:1fr}
/* 📜 قائمتان تُقصّان صفًّا في منتصفه عند حدّ ارتفاعهما، فيقرأ ذلك «معطوب» لا «تكملة بالأسفل».
   الحدّ باقٍ — سجلّ التدقيق وحده مئات الأسطر — لكن الحاوية صارت مُعلَّمة: إطارٌ يُنهي المنطقة،
   وتلاشٍ سفليّ يقول إنّ تحته المزيد. */
#admin .auditlog{border:1px solid var(--line);border-radius:9px;padding:2px 10px;scrollbar-gutter:stable}
/* وجدول المستخدمين ٢٢ صفًّا بينما سجلّ التدقيق مسقوفٌ بـ٢٨٠ بكسل، فكان الصفّ يمطّ بطاقة السجلّ إلى
   ارتفاع الجدول ويترك تحتها ٤٠٠ بكسل بيضاء. السقف يُرفع داخل الصفّ وحده فيبتلع السجلّ الفائض أسطرًا
   مرئيّة بدل أن يصير حشوًا — وهو الحلّ المكتوب فوق `.grid.two.situation` نفسه. */
#admin .tabpanel[data-admtab="people"] .card:has(>.auditlog){display:flex;flex-direction:column}
#admin .tabpanel[data-admtab="people"] .auditlog{flex:1 1 auto;min-height:180px;max-height:none}
#admin .auditlog,#admin .const-list{-webkit-mask-image:linear-gradient(to bottom,#191C1A calc(100% - 26px),transparent 100%);
  mask-image:linear-gradient(to bottom,#191C1A calc(100% - 26px),transparent 100%)}
#admin .auditlog .a:last-child,#admin .const-list .const-row:last-child{border-bottom:none}
.flowsec{margin:0 0 16px;padding-inline-start:11px;border-inline-start:2px solid var(--line)}
.flowsec.eye{border-inline-start-color:var(--eye)}
.flowsec.thinker{border-inline-start-color:#B4560A}
.flowsec.responder{border-inline-start-color:var(--responder)}
.flowtag{font-size:13px;font-weight:600;margin:0 0 10px;color:var(--mut);display:flex;align-items:center;gap:7px}
.flowsec.eye .flowtag{color:var(--eye)}
.flowsec.thinker .flowtag{color:#B4560A}
.flowsec.responder .flowtag{color:var(--responder)}
.mini{font-size:12.5px;font-weight:500;padding:7px 11px;background:var(--card);color:var(--ink);border:1px solid var(--line);border-radius:10px;box-shadow:0 2px 5px rgba(17,24,39,.08)}
.mini:hover{background:var(--card2);border-color:#D8D0C2;filter:none;box-shadow:0 3px 9px rgba(17,24,39,.12)}
.mini .li{color:var(--mut)}
/* agent buttons — each a bordered chip with soft shadow + its own identity-colored icon tile */
.agentbar{gap:9px}
.agbtn{padding:7px 13px;gap:9px;box-shadow:var(--shadow-sm);font-weight:600;color:var(--ink);background:var(--card);border:1px solid var(--line);border-radius:12px}
.agbtn:hover{background:color-mix(in srgb,var(--ac) 6%,#fff);border-color:color-mix(in srgb,var(--ac) 45%,var(--line));box-shadow:var(--shadow);transform:translateY(-1px)}
.agbtn .ag-ic{width:28px;height:28px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--ac) 12%,#fff);border:1px solid color-mix(in srgb,var(--ac) 32%,#fff)}
.agbtn .ag-ic .li{width:16px;height:16px;color:var(--ac)}
.inp-body{margin-top:4px}
.drilltools{display:inline-flex;gap:6px}
/* command agents */
.agentbar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.ag-out{font-size:13px;display:grid;gap:6px}
.ag-out:empty{display:none}
.ag-h{font-weight:600;margin:6px 0 2px;color:var(--ink);display:flex;align-items:center;gap:7px}
.ag-row{background:var(--card2);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 11px;display:flex;gap:8px;align-items:center;justify-content:space-between;flex-wrap:wrap}
.ag-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:6px;margin:6px 0}
/* Statistics dashboard — representable estate-wide charts (sovereign, inline) */
.dashbody{display:flex;flex-direction:column;gap:12px}
.dash-kpis{margin:0}
.dash-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
/* Cap the wide layout at 4 columns. auto-fit alone gave 5 across on a 1440-wide screen, which left
   the last row three-quarters empty and read as a broken grid; the card count is a multiple of 4. */
@media(min-width:1180px){.dash-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
.dash-card{padding:12px}
.dash-card .card-h{display:flex;align-items:center;gap:7px;font-weight:700;font-size:13px;margin-bottom:9px;color:var(--ink)}
.dash-card .card-h .li{width:16px;height:16px;color:var(--mut)}
.hbars{display:flex;flex-direction:column;gap:7px}
.hbar{display:grid;grid-template-columns:96px 1fr 48px;gap:8px;align-items:center;font-size:12px}
.hbar-l{color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hbar-t{background:var(--card2);border:1px solid var(--line);border-radius:99px;height:12px;overflow:hidden}
.hbar-f{display:block;height:100%;border-radius:99px;min-width:6px;transition:width .45s cubic-bezier(.2,.7,.2,1)}
.hbar-v{text-align:end;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
/* ── Registry-sourced dashboard (2026-08-16, with the fleet.stats() re-source onto V2.10) ────────
   Before this, an empty card was a bare header over blank space and every untracked field drew a
   zero. Both are corrected here: cards hold their height and say when they are empty, and a fact
   the workbook does not record renders hatched and dashed, never as 0. */
.dash-card{display:flex;flex-direction:column;min-height:186px}
/* .card-h bleeds -18px so its divider spans a .card's 18px padding; .dash-card pads 12px, so the
   header hung 6px past the card on each side. Match the bleed to THIS card's padding instead. */
.dash-card .card-h{flex:0 0 auto;align-items:flex-start;flex-wrap:wrap;gap:7px;
  margin-inline:-12px;padding-inline:12px}
.dash-card .card-h .li{margin-top:1px}
.dash-card .card-h>span:not(.dash-prov){min-width:0;flex:1 1 auto;line-height:1.35}
.dash-card-b{flex:1 1 auto;display:flex;flex-direction:column;gap:8px}
.dash-card .hbar{grid-template-columns:minmax(84px,1.15fr) minmax(56px,1fr) 54px}
/* per-card provenance: which source these numbers came from, stated on the card itself. The chips
   are whatever provChip() renders from /api/data-provenance — so a card fed by the V2.10 DUMMY
   workbook is labelled as such and never borrows the registry's "real data" badge. */
.dash-provs{margin-inline-start:auto;flex:0 0 auto;display:flex;gap:4px;justify-content:flex-end}
.dash-provs:empty{display:none}
.dash-prov{font-size:9.5px;font-weight:700;padding:2px 6px;white-space:nowrap;cursor:help}
.dash-prov.is-dummy::before{content:"⚠ "}
/* the full statement, once, above the cards — the per-card badges are terse on purpose */
.dash-banner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap;padding:9px 12px;border-radius:12px;
  background:#B4560A10;border:1px solid #B4560A33;color:#7A4A08;font-size:11.5px;line-height:1.6}
.dash-banner .li{width:15px;height:15px;flex:0 0 auto;margin-top:2px;color:#B4560A}
.dash-banner>span{flex:1 1 260px;min-width:0}
.dash-banner small{flex:0 0 auto;opacity:.75;font-size:10px;direction:ltr;unicode-bidi:isolate}
/* a card with nothing to show must SAY it has nothing to show */
.dash-empty{display:flex;align-items:center;justify-content:center;gap:7px;padding:18px 10px;
  color:var(--mut);font-size:12px;text-align:center;line-height:1.5;
  border:1px dashed var(--line);border-radius:10px;background:var(--card2)}
.dash-empty .li{width:15px;height:15px;flex:0 0 auto}
.dash-note{display:flex;align-items:flex-start;gap:7px;margin-top:auto;padding-top:9px;
  border-top:1px solid var(--line);color:var(--mut);font-size:11px;line-height:1.55}
.dash-note .li{width:14px;height:14px;flex:0 0 auto;margin-top:2px}
/* NOT RECORDED — hatched track, em-dash value. Never a zero-length bar labelled 0: on this screen
   that asserts a fact ("nothing offline") the V2.10 workbook simply does not carry. */
.hbar-unknown .hbar-l{color:var(--mut)}
.hbar-unknown .hbar-t{border-style:dashed;background-image:repeating-linear-gradient(135deg,
  color-mix(in srgb,var(--mut) 20%,transparent) 0 4px,transparent 4px 8px)}
.hbar-unknown .hbar-v{color:var(--mut);font-weight:600}
/* coverage ratio: "2/4" reads as two OF four, so a small number cannot pass for an achievement */
.hbar-cov small{color:var(--mut);font-weight:600;margin-inline-start:1px}
/* split track: PRESENT (green) then NOT PRESENT (grey); the remainder of the track is what nobody
   surveyed. Three states in one bar, because collapsing "has none" into "unknown" loses the survey. */
.hbar-tri{display:flex}
.hbar-tri .hbar-f{border-radius:0;min-width:0}
.hbar-tri .hbar-f:first-child{border-start-start-radius:99px;border-end-start-radius:99px}
/* secondary strip: estate totals with no drill-down behind them */
.dash-kpis2{margin-top:-4px}
.dash-kpis2 .kpi{padding:11px 13px}
.dash-kpis2 .kpi .v{font-size:20px}
.dash-cov{font-weight:700;color:var(--mut);font-size:10px;padding:1px 5px;border-radius:99px;
  background:var(--card2);border:1px solid var(--line);margin-inline-start:4px;white-space:nowrap}
/* loading skeleton — replaces the bare «يحسب…» line so the grid does not jump when data lands */
.dash-skel{border:1px solid var(--line);border-radius:14px;background:var(--card2);position:relative;overflow:hidden}
.dash-skel.sk-kpi{height:72px}
.dash-skel.sk-card{min-height:186px}
.dash-skel::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--ink) 7%,transparent),transparent);
  animation:dashShimmer 1.25s infinite}
@keyframes dashShimmer{100%{transform:translateX(100%)}}
@media(prefers-reduced-motion:reduce){.dash-skel::after{animation:none}}
/* Collapsible secondary cards — let the user hide "not necessary" parts of a view (persisted) */
.card-collapse{background:none;border:0;padding:2px;margin-inline-end:5px;cursor:pointer;color:var(--mut);display:inline-flex;align-items:center;border-radius:6px;flex:0 0 auto;order:-1}
.card-collapse:hover{background:var(--card2);color:var(--ink)}
.card-collapse .li{width:15px;height:15px;transition:transform .15s}
.card.collapsed > .card-h .card-collapse .li{transform:rotate(-90deg)}
.card.collapsed > :not(.card-h){display:none!important}
/* Alarm disposition (scenario class) control — incident workspace */
.inc-disp{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:7px 0 2px;font-size:12px}
.inc-disp:empty{display:none}
/* AI-confirmed-fire push alert (fire_alert.py) — building manager/security, resident /sos view */
.fire-alert-banner{display:flex;align-items:center;gap:10px;background:var(--danger);color:#fff;
  border-radius:var(--r-sm);padding:12px 16px;margin:8px 0 4px;font-size:13.5px;font-weight:700;
  box-shadow:0 8px 20px rgba(255,59,48,.3)}
.fire-alert-banner .li{width:20px;height:20px;flex:0 0 auto}
.fire-alert-banner.flash{animation:fabpulse 1.2s infinite}
@keyframes fabpulse{0%,100%{box-shadow:0 8px 20px rgba(255,59,48,.3)}50%{box-shadow:0 8px 20px rgba(255,59,48,.65)}}
.disp-lbl{display:inline-flex;align-items:center;gap:4px;color:var(--mut);font-weight:600}
.disp-lbl .li{width:14px;height:14px}
.disp-badge{display:inline-flex;align-items:center;gap:4px;font-weight:700;color:var(--dc);background:#fff;border:1px solid var(--dc);border-radius:20px;padding:2px 9px}
.disp-badge .li{width:13px;height:13px}
.disp-opts{display:inline-flex;flex-wrap:wrap;gap:5px;margin-inline-start:auto}
.disp-opt{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:600;color:var(--mut);background:var(--card2);border:1px solid var(--line);border-radius:18px;padding:3px 9px;cursor:pointer;transition:color .12s,background .12s,border-color .12s}
.disp-opt .li{width:13px;height:13px}
.disp-opt:hover{border-color:var(--dc);color:var(--dc)}
.disp-opt.on{color:#fff;background:var(--dc);border-color:var(--dc)}
.disp-msg{flex-basis:100%;color:var(--sev-high)}
/* Agent orchestrator — visual collaboration chart (real handoff edges + gate) */
.collab-h{display:flex;align-items:center;gap:7px;font-weight:700;font-size:13px;margin:2px 0 8px;color:var(--ink)}
.collab-h .li{width:16px;height:16px;color:var(--thinker)}
.collab-chart{display:flex;flex-direction:column;align-items:stretch;gap:0}
.collab-node{border:1px solid var(--line);border-inline-start:3px solid var(--mut);border-radius:10px;background:var(--card2);padding:8px 11px}
.collab-node.st-ok{border-inline-start-color:var(--sev-low)}
.collab-node.st-caution{border-inline-start-color:var(--sev-medium)}
.collab-node.st-defer{border-inline-start-color:var(--sev-high)}
.collab-node.st-error{border-inline-start-color:var(--sev-critical)}
.collab-node.is-gate{background:#fff;box-shadow:0 0 0 1px var(--eye) inset}
.collab-top{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:12.5px;color:var(--ink)}
.collab-top .li{width:15px;height:15px}
.collab-node.st-ok .collab-ic .li{color:var(--sev-low)}
.collab-node.st-caution .collab-ic .li{color:var(--sev-medium)}
.collab-node.st-defer .collab-ic .li{color:var(--sev-high)}
.collab-node.st-error .collab-ic .li{color:var(--sev-critical)}
.collab-gate{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:700;color:var(--eye);background:#F2F2F2;border:1px solid #C9D3CC;border-radius:20px;padding:1px 7px}
.collab-gate .li{width:12px;height:12px;color:var(--eye)}
.collab-conf{margin-inline-start:auto;font-size:10.5px;color:var(--mut);font-weight:600}
.collab-sum{font-size:12px;color:var(--ink);margin-top:3px}
.collab-edges{font-size:11px;color:var(--mut);margin-top:4px;display:flex;flex-wrap:wrap;gap:5px;align-items:center}
.collab-from{display:inline-flex;align-items:center;background:#F2F2F2;border:1px solid var(--line);border-radius:20px;padding:0 8px;font-weight:600;color:var(--ink)}
.collab-src{font-size:10px;margin-top:3px;opacity:.8}
.collab-conn{display:flex;justify-content:center;color:var(--mut);margin:0}
.collab-conn .li{width:16px;height:16px}
/* MCI casualty provenance tags — field-confirmed vs declared-from-state (honesty) */
.prov{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:600;padding:1px 7px;border-radius:20px;border:1px solid;white-space:nowrap;vertical-align:.05em}
.prov .li{width:12px;height:12px}
.prov-field{color:#1D2C22;background:#F2F2F2;border-color:#C9D3CC}
.prov-declared{color:#B4560A;background:#FBEFD6;border-color:#FBEFD6}
.prov-note{margin-top:5px;font-style:italic;display:flex;align-items:center;gap:5px}
.prov-note .li{width:13px;height:13px;color:var(--mut);flex:0 0 auto}
.ag-kv{background:var(--card2);border:1px solid var(--line);border-radius:8px;padding:6px 8px;font-size:12px;color:var(--mut)}
.ag-kv b{display:block;font-size:15px;color:var(--ink)}
.triage-packet{border-inline-start:3px solid var(--eye)}
.triage-packet:empty,.verify-agent:empty,.evac-agent:empty{display:none}
.verify-agent{border-inline-start:3px solid var(--responder)}
.evac-agent{border-inline-start:3px solid var(--thinker)}
.seq-row{display:flex;gap:8px;align-items:flex-start;background:var(--card2);border:1px solid var(--line);border-radius:8px;padding:7px 10px;margin-top:5px;font-size:12.5px}
.seq-n{font-weight:800;color:var(--thinker);min-width:20px}
.chk-row{display:flex;gap:8px;align-items:center;justify-content:space-between;background:var(--card2);border:1px solid var(--line);border-radius:8px;padding:6px 10px;margin-top:5px;font-size:12.5px}
.chk-v{font-weight:700;border-radius:8px;padding:2px 9px;font-size:12px;flex:0 0 auto;display:inline-flex;align-items:center}
.chk-v .li{width:14px;height:14px}
.chk-v.ok{background:#DFF5EA;color:#127A4B;border:1px solid #DFF5EA}
.chk-v.caution{background:#FBEFD6;color:#7A4A08;border:1px solid #FBEFD6}
.chk-v.refuted{background:#FFE7DC;color:#9E2F00;border:1px solid #FFE7DC}
.chk-v.defer{background:#FBEFD6;color:#7A4A08;border:1px solid #FBEFD6}
.chk-v.error{background:#FFE7DC;color:#9E2F00;border:1px solid #FFE7DC}
.audit-trail{max-height:300px;overflow:auto;display:flex;flex-direction:column;gap:5px}
.trail-row{display:flex;gap:9px;align-items:flex-start;background:var(--card2);border:1px solid var(--line);border-inline-start:3px solid var(--line);border-radius:8px;padding:6px 10px;font-size:12.5px}
.trail-row.ok{border-inline-start-color:#127A4B}
.trail-row.caution{border-inline-start-color:#E0A82E}
.trail-row.refuted{border-inline-start-color:#CC3D00}
.trail-ic{flex:0 0 auto;font-size:14px;line-height:1.4}
.trail-body{flex:1 1 auto;min-width:0}
.unit-mk .unit{width:26px;height:26px;border-radius:50%;background:#fff;border:2.5px solid var(--responder);display:flex;align-items:center;justify-content:center;font-size:14px;box-shadow:0 1px 4px rgba(0,0,0,.35)}
.sitrep-form{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.sitrep-form .sr-row{display:flex;align-items:center;gap:8px}
.sitrep-form .sr-row>label{flex:0 0 90px;font-size:12.5px;color:var(--mut)}
.sitrep-form select,.sitrep-form input,.sitrep-form textarea{flex:1 1 auto;min-width:0;background:var(--card2);border:1px solid var(--line);border-radius:7px;padding:5px 8px;color:var(--ink);font:inherit;font-size:12.5px}
.sitrep-form .sr-need{display:flex;flex-wrap:wrap;gap:4px 10px}
.sitrep-form .sr-chip{flex:0 0 auto;display:inline-flex;align-items:center;gap:3px;font-size:12px;color:var(--ink)}
.sitrep-form .sr-chip input{flex:0 0 auto}
.sitrep-form textarea{resize:vertical}
.sitrep-form button{align-self:flex-start}
.sitrep-list{display:flex;flex-direction:column;gap:5px;max-height:240px;overflow:auto}
.orch-card{border-inline-start:3px solid var(--uae-green)}
.ag-rec.ok .meta{color:#1D2C22}
.refuge{background:#F2F2F2;border:1px solid #C9D3CC;color:#1E6F9F;border-radius:8px;padding:6px 10px;margin:6px 0;font-size:13px}
.domain-card{border-inline-start:3px solid var(--sev-medium)}
.domain-card:empty{display:none}
.unit-mk .unit{font-size:14px;line-height:18px;text-align:center;filter:drop-shadow(0 0 2px #191C1A)}
.unit-mk .unit.dispatched{opacity:.5}
.fra-card{border-inline-start:3px solid var(--admin)}
.fra-card:empty{display:none}
.ag-rec{display:flex;gap:8px;align-items:center;justify-content:space-between;flex-wrap:wrap;background:#FFE7DC;border:1px solid #FFE7DC;border-radius:8px;padding:7px 10px;margin-top:5px}
.ag-rec .meta{color:#9E2F00}
.camview{display:grid;gap:6px}
.cam-frame{width:100%;border-radius:10px;border:1px solid var(--line);display:block;background:#191C1A}
.cam-skel{display:flex;align-items:center;justify-content:center;gap:9px;padding:34px 12px;border:1px dashed var(--line);border-radius:10px;background:var(--bg)}
/* camera NOT working — clear "غير عاملة" state instead of a fake feed */
.cam-off{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:22px 12px;color:#CC3D00;font-weight:700;text-align:center}
.cam-off.big{padding:40px 14px;border:1px dashed #CC3D0055;border-radius:10px;background:#CC3D000c}
.cam-off .li{width:26px;height:26px}.cam-off .meta{color:var(--mut);font-weight:400}
.spin{width:16px;height:16px;border:2px solid var(--line);border-top-color:var(--eye);border-radius:50%;display:inline-block;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.cam-live{display:inline-flex;align-items:center;gap:4px;color:var(--sev-low);font-weight:700}
.cam-live .li{width:14px;height:14px}
.live-dot{width:8px;height:8px;border-radius:50%;background:var(--sev-low);display:inline-block;margin:0 3px;animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.2}}
.cam-correct{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:7px;padding:8px 10px;background:var(--bg);border:1px solid var(--line);border-radius:10px;font-size:12.5px}
.cam-correct .li{width:15px;height:15px;color:var(--responder)}
.cam-correct input{width:78px;padding:5px 8px;border:1px solid var(--line);border-radius:8px;font-size:13px}
.occsrc.confirmed{background:#DFF5EA;color:#127A4B;border:1px solid #DFF5EA}
/* 2018 reference tables viewer */
.ct{border:1px solid var(--line);border-radius:10px;margin-top:7px;background:var(--card)}
.ct>summary{cursor:pointer;padding:8px 10px;font-size:12.5px;list-style:none;border-inline-start:3px solid var(--brand);border-radius:10px}
.ct>summary::-webkit-details-marker{display:none}
.ct>summary:hover{background:var(--bg)}
.ct-wrap{overflow-x:auto;padding:4px 10px 8px}
.ct-tbl{border-collapse:collapse;width:100%;font-size:11.5px}
.ct-tbl th{background:var(--bg);color:var(--ink);text-align:start;padding:5px 8px;border:1px solid var(--line);font-weight:700}
.ct-tbl td{padding:5px 8px;border:1px solid var(--line);vertical-align:top;color:var(--ink)}
.occsrc{margin-top:6px;font-size:12px;border-radius:8px;padding:5px 8px;line-height:1.5}
.occsrc.cv{background:#DFF5EA;border:1px solid #DFF5EA;color:#1D2C22}
.occsrc.db{background:var(--card2);border:1px solid var(--line);color:var(--mut)}
.occsrc .mini{margin-inline-start:6px}
.iconbtn{background:var(--card2);color:var(--ink);border:1px solid var(--line);border-radius:18px;padding:4px 9px;font-size:13px}

/* ===== live alerts (new / escalating fires) ===== */
.alerts{display:flex;flex-direction:column;gap:8px;padding:8px 18px 0}
.alert{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border-radius:10px;padding:8px 12px;font-size:13px;
  border:1px solid var(--sev-high);background:#FFE7DC;animation:alertpulse 1.1s ease-in-out 3}
.alert.critical{border-color:var(--sev-critical);background:#FFE7DC}
.alert .al-h{font-weight:800;color:var(--sev-high);display:inline-flex;align-items:center;gap:6px}
.alert .al-h .li{width:15px;height:15px}
.alert.critical .al-h{color:var(--sev-critical)}
.alert .al-b{flex:1;min-width:200px}
.alert .al-x{display:flex;gap:6px}
.alert button{padding:4px 10px;font-size:12px}
@keyframes alertpulse{0%,100%{box-shadow:0 0 0 0 transparent}50%{box-shadow:0 0 0 3px #FF4D0040}}
.badge-count{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;
  border-radius:9px;background:var(--sev-critical);color:#fff;font-size:12px;font-weight:800;margin-inline-start:6px;padding:0 4px}

.foot{padding:16px 18px;color:var(--mut);font-size:12px;text-align:center;border-top:2px solid var(--uae-green);margin-top:10px}

/* ---- QA fixes: build stamp, triage loading/empty, info-tip caveats, today's route ---- */
.chip.ver{font-weight:700;letter-spacing:.2px}
/* triage skeleton (initial-load state) — distinct from the genuine 'no fires' empty state */
.triage-load{padding:6px 2px}
.trow.skel{pointer-events:none;opacity:.9}
.sk{display:inline-block;border-radius:6px;background:linear-gradient(90deg,#FFFFFF 25%,#EDEDED 37%,#FFFFFF 63%);
  background-size:400% 100%;animation:sksh 1.2s ease-in-out infinite}
.sk-sev{width:16px;height:16px;border-radius:50%}
.sk-line{width:62%;height:11px;margin-bottom:6px}
.sk-sub{width:42%;height:9px}
.sk-num{width:34px;height:22px}
@keyframes sksh{0%{background-position:100% 50%}100%{background-position:0 50%}}
.triage-empty{display:flex;flex-direction:column;gap:8px;align-items:center;justify-content:center;
  text-align:center;padding:26px 14px;color:var(--mut)}
.triage-empty svg,.triage-empty .li{width:32px;height:32px;color:#127A4B}
.triage-empty b{color:var(--ink,#191C1A)}
/* one consistent info affordance for provenance/confidence caveats */
.itip{cursor:help;opacity:.55;display:inline-flex;vertical-align:-2px}
.itip svg,.itip .li{width:13px;height:13px}
.itip:hover,.itip:focus{opacity:1;outline:none}
details.aic-more{margin-top:5px}
details.aic-more>summary{cursor:pointer;font-size:11.5px;color:var(--mut);display:inline-flex;
  align-items:center;gap:4px;list-style:none;user-select:none}
details.aic-more>summary svg,details.aic-more>summary .li{width:13px;height:13px}
details.aic-more>summary::-webkit-details-marker{display:none}
details.aic-more[open]>summary{margin-bottom:5px}
/* preventive — today's route */
.pv-route-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.pv-route-kpi{display:flex;flex-direction:column;align-items:flex-end;gap:2px;white-space:nowrap}
.pv-route-kpi .prk-big{font-size:15px}
.pv-route-kpi .prk-big b{font-size:20px;color:#1E6F9F}
.pv-route{display:flex;flex-direction:column;gap:8px;max-height:62vh;overflow:auto}
.pv-route-row{display:flex;gap:12px;align-items:flex-start;padding:10px 12px;border:1px solid var(--line,#E4DDD1);
  border-radius:10px;background:#fff}
.pv-route-n{flex:0 0 auto;width:28px;height:28px;border-radius:50%;display:inline-flex;align-items:center;
  justify-content:center;font-weight:800;color:#fff;background:var(--pc,#5C6B61)}
.pv-route-b{flex:1;min-width:0}
.pv-route-f{margin-top:5px;display:flex;gap:4px;flex-wrap:wrap}
.pv-route-a{display:flex;flex-direction:column;align-items:flex-end;gap:6px;white-space:nowrap}
.pv-route-btns{display:flex;gap:6px}
@media(max-width:640px){.pv-route-row{flex-wrap:wrap}.pv-route-a{align-items:flex-start;width:100%}}

/* ---- Prompt → Dashboard NL→SQL ---- */
.nl2-hint{padding:6px 2px}
.nl2-hint .chips{margin-top:8px}
details.nl2-sql{margin:2px 0 10px;border:1px solid var(--line);border-radius:9px;background:var(--card2);padding:8px 10px}
details.nl2-sql>summary{cursor:pointer;display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink);list-style:none}
details.nl2-sql>summary::-webkit-details-marker{display:none}
details.nl2-sql>summary svg,details.nl2-sql>summary .li{width:14px;height:14px}
details.nl2-sql pre.brief{margin:8px 0 0;white-space:pre-wrap;font-size:12px;background:#191C1A;color:#F2F2F2;border-radius:7px;padding:9px 11px}
.nl2-chart{margin:6px 0 10px}

/* ---- Building Registry ---- */
.br-contacts{display:flex;flex-wrap:wrap;gap:14px;font-size:12.5px;color:var(--ink);margin:2px 0 8px;padding:6px 10px;background:var(--bg2);border-radius:8px}
.br-contacts .li{width:14px;height:14px;vertical-align:-2px;color:var(--brand)}
.br-contacts a{color:var(--brand);text-decoration:none;font-weight:700}
/* 🛎️ 4-stage alarm verification stepper (Open → AI → Security → Occupant) */
.vpipe{margin:6px 0 10px;padding:8px 10px;border:1px solid var(--line);border-radius:10px;background:#fff}
.vsteps{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:6px}
.vstep{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border-radius:999px;border:1px solid var(--line);color:#8A968E;font-size:12.5px;font-weight:700;background:#FFFFFF}
.vstep.on{color:#1D2C22;border-color:#1D2C22;background:#1D2C2211}
.vstep.cur{box-shadow:0 0 0 2px #1D2C2233}
.vstep.false{color:#5C6B61;border-color:#5C6B61;background:#5C6B6111}
.vsep{color:#D8D0C2;font-weight:700}
/* generic form input (security fire-report modal + small forms) */
.inp{padding:8px 10px;border:1px solid var(--line);border-radius:8px;font-size:14px;background:#fff;color:var(--ink)}
.br-form{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:8px 0 12px}
.br-form input,.br-form select{padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-size:13px;background:#fff;color:var(--ink);min-width:0}
.br-form input{max-width:180px}
.br-form button{padding:7px 14px;border-radius:8px;border:1px solid var(--eye);background:var(--eye);color:#fff;font-weight:700;cursor:pointer;font-size:13px}
.br-form button:hover{filter:brightness(1.06)}
.br-needs{display:inline-flex;gap:10px;flex-wrap:wrap;align-items:center;font-size:12.5px;color:var(--mut)}
.br-chk{display:inline-flex;gap:4px;align-items:center;white-space:nowrap;color:var(--ink)}
ol.br-phases{margin:6px 0;padding-inline-start:18px}
ol.br-phases li{margin:3px 0}
/* incident-dossier registered-building impact card */
.reg-impact:empty{display:none}
.reg-impact{border-inline-start:3px solid #1E6F9F}
.reg-hit{padding:8px 2px;border-top:1px dashed var(--line)}
.reg-hit:first-of-type{border-top:none}
.reg-hit-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.reg-hit-k{margin:5px 0;font-size:13px}
.reg-hit-f{display:flex;gap:4px;flex-wrap:wrap;margin:4px 0}
.reg-hit-a{display:flex;gap:8px;flex-wrap:wrap;margin-top:6px}
/* A model-declared number must never wear the same clothes as a computed one. */
.pill.conf-model .conf-basis{font-size:9.5px;letter-spacing:.02em;text-transform:uppercase;
  opacity:.85;margin-inline-start:4px;padding-inline-start:5px;border-inline-start:1px solid currentColor}

/* 🎛️ الثوابت التشغيلية. شبكةٌ من ثلاثة أعمدة: التسمية · الأداة · الأثر.
   العروض مُصرَّحة على كل حقل بعينه ولا قاعدة شاملة على input — قاعدةٌ كتلك هي ما مطّ مربّعات
   الاختيار إلى ٢٦١ بكسل وجعل التسميات تتراكب في هذه الورقة من قبل، ومربّع الاختيار هنا بالذات
   هو الذي يقرّر أيصل إنذار الحريق لكلّ من في المبنى. */
.tun-list{display:flex;flex-direction:column;gap:2px}
.tun-row{display:grid;grid-template-columns:minmax(180px,1.1fr) auto minmax(200px,1.6fr);
         gap:10px;align-items:start;padding:8px 6px;border-top:1px dashed var(--line)}
.tun-row.over{background:#B4560A09;border-inline-start:3px solid #B4560A}
.tun-l{display:flex;flex-direction:column;gap:3px;min-width:0}
.tun-k{font-size:11px;color:var(--mut);direction:ltr;text-align:start;word-break:break-all}
.tun-c{display:flex;align-items:center;min-width:0}
.tun-c input[type=checkbox]{width:18px;height:18px;flex:none;margin:0}
.tun-c .tun-num{width:112px;min-width:0;padding:5px 7px;border:1px solid var(--line);
                border-radius:7px;font:inherit;color:var(--ink);background:var(--card);direction:ltr}
.tun-c .tun-json{width:100%;min-width:0;box-sizing:border-box;padding:6px;border:1px solid var(--line);
                 border-radius:7px;font:12px/1.45 ui-monospace,Menlo,Consolas,monospace;color:var(--ink);
                 background:var(--card);direction:ltr;text-align:start;resize:vertical}
.tun-e{font-size:12px;color:var(--mut);min-width:0}
.tun-e .meta{display:block;margin-top:3px}
.tun-err{grid-column:1/-1}
.tun-actions{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin-top:12px}
@media (max-width:760px){ .tun-row{grid-template-columns:1fr} .tun-c .tun-json{width:100%} }

/* 🏢 أمر المبنى المجاور — الخطوة الثانية بعد التنبيه الاحترازي التلقائي.
   العروض مُصرَّحة على الحقل بعينه: قاعدة عرضٍ شاملة على input/textarea هي ما مطّ مربّعات
   الاختيار إلى ٢٦١ بكسل وجعل النصوص تتراكب في هذه الصفحة من قبل. */
.nb-order{margin-top:8px;padding:9px 10px;border:1px solid var(--line);border-radius:10px;
          background:var(--card2)}
.nb-h{display:flex;align-items:center;gap:6px;font-weight:800;font-size:13px;margin-bottom:7px}
.nb-btns{display:flex;gap:6px;flex-wrap:wrap}
.nb-btns .nb-go{border-color:var(--nbc);color:var(--nbc)}
.nb-btns .nb-go:hover:not(:disabled){background:color-mix(in srgb,var(--nbc) 12%,transparent)}
.nb-free{display:flex;gap:6px;align-items:flex-start;margin-top:7px}
.nb-free textarea{flex:1;min-width:0;box-sizing:border-box;padding:7px;border:1px solid var(--line);
                  border-radius:8px;font:inherit;color:var(--ink);background:var(--card);resize:vertical}
.nb-out{margin-top:6px;min-height:0}
.nb-log{margin-top:7px;border-top:1px dashed var(--line);padding-top:6px}
.nb-log-row{margin-top:4px}
.reg-msg-box{margin-top:8px;padding:9px;border:1px solid var(--line);border-radius:10px;background:var(--card2)}
.reg-msg-t{width:100%;box-sizing:border-box;margin:6px 0;padding:8px;border:1px solid var(--line);border-radius:8px;font:inherit;color:var(--ink);background:var(--card);resize:vertical}
.reg-send-res{color:#1D2C22;font-weight:700}
/* two-way evacuation: live occupant status */
.reg-hit.has-trapped{background:#FFE7DC;border-radius:10px;padding:8px;margin-inline:-2px}
.reg-hit-status{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin:5px 0;font-size:12px;color:var(--mut)}
.occ-chip{display:inline-flex;align-items:center;gap:4px;border-radius:20px;padding:2px 9px;font-weight:700;font-size:11.5px;border:1px solid transparent}
.occ-chip .li{width:13px;height:13px}
.occ-trapped{background:#CC3D0018;color:#CC3D00;border-color:#CC3D0055;animation:sevpulse 1.6s ease-in-out infinite}
.occ-help{background:#B4560A18;color:#B4560A;border-color:#B4560A55}
.occ-safe{background:#127A4B18;color:#127A4B}
.occ-unknown{background:var(--card2);color:var(--mut)}
.reg-urgent{display:flex;flex-direction:column;gap:4px;margin:6px 0}
.reg-urgent-row{font-size:12.5px;padding:6px 9px;border-radius:9px;background:#fff;border:1px solid var(--line)}
.reg-urgent-row.trapped{border-inline-start:3px solid #CC3D00;background:#FFE7DC}
.reg-urgent-row.help{border-inline-start:3px solid #B4560A;background:#FFFFFF}
.reg-urgent-row .li{width:14px;height:14px;vertical-align:-2px}
/* proactive fire-spread forecast scrubber */
.spread-forecast{border-inline-start:3px solid #CC3D00}
.sf-ctl{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:2px 0 10px}
.sf-ctl input[type=range]{flex:1;min-width:180px;accent-color:#CC3D00;cursor:pointer}
.sf-t{font-variant-numeric:tabular-nums;font-weight:800;color:#CC3D00;min-width:56px;text-align:center}
.sf-out{display:flex;gap:8px;flex-wrap:wrap}
.sf-badge{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;font-weight:700;border-radius:9px;padding:4px 10px}
.sf-badge .li{width:14px;height:14px}
.sf-badge.inv{background:#CC3D0014;color:#CC3D00}
.sf-badge.thr{background:#B4560A18;color:#B4560A}
/* 🔗 camera ⇄ forecast ⇄ twin linkage */
.sf-badge.cam{border:1px dashed #1E6F9F66;background:#1E6F9F0d;color:#1E6F9F;cursor:pointer}
.sf-badge.cam.inv{background:#CC3D0014;color:#CC3D00;border-color:#CC3D0066}
.sf-badge.cam.thr{background:#B4560A18;color:#B4560A;border-color:#B4560A66}
.sf-badge.cam:hover{filter:brightness(.94)}
#sfCam{margin-top:6px}
#sfCam:empty{display:none}
.ctx-row.cam-link{cursor:pointer;border:1px solid #1E6F9F55;background:#1E6F9F08}
.ctx-row.cam-link:hover{background:#1E6F9F14}

/* 📗 Authoritative V2.10 workbook panel (incident dossier) */
.fra2-auth:empty{display:none}
.fra2-auth .prov-chip{margin-inline-start:auto;font-size:11px;font-weight:600;color:#1E6F9F;background:#1E6F9F14;border:1px solid #1E6F9F33;border-radius:999px;padding:2px 9px;display:inline-flex;align-items:center;gap:4px;max-width:46%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.f2-id{display:flex;flex-wrap:wrap;gap:6px 12px;align-items:center;padding:8px 4px;font-size:13px;border-bottom:1px solid var(--line,#E4DDD1)}
.f2-confirm{--fc:#CC3D00;display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:10px 0;padding:10px 12px;border:1px solid var(--fc);border-inline-start:4px solid var(--fc);border-radius:10px;background:color-mix(in srgb,var(--fc) 7%,transparent)}
.f2-confirm .f2-dot{width:10px;height:10px;border-radius:50%;background:var(--fc);box-shadow:0 0 0 4px color-mix(in srgb,var(--fc) 22%,transparent)}
.f2-confirm .f2-verdict{font-weight:800;color:var(--fc)}
.f2-corr{flex-basis:100%;display:flex;flex-wrap:wrap;gap:5px;margin-top:4px}
.f2-block{margin:10px 0}
.f2-block-h{font-weight:700;font-size:13px;display:flex;align-items:center;gap:6px;margin-bottom:6px}
.f2-timeline{display:flex;flex-direction:column;gap:3px;max-height:340px;overflow:auto;border:1px solid var(--line,#E4DDD1);border-radius:8px;padding:6px}
.f2-row{display:grid;grid-template-columns:26px 1fr auto auto;gap:6px 10px;align-items:center;padding:5px 8px;border-radius:6px;font-size:12.5px}
.f2-row:nth-child(odd){background:var(--card2,#FFFFFF)}
.f2-row.f2-crit{background:#CC3D000d;border:1px solid #CC3D0033}
.f2-row.f2-cur{background:var(--eye,#1E6F9F)1a;outline:2px solid var(--eye,#1E6F9F);outline-offset:-1px}
.f2-playbar{display:flex;align-items:center;gap:8px;margin:6px 0;flex-wrap:wrap}
.f2-pbtn{display:inline-flex;align-items:center;gap:5px;padding:5px 12px;border-radius:999px;border:1px solid var(--eye,#1E6F9F);background:var(--eye,#1E6F9F);color:#fff;font-weight:800;font-size:12.5px;cursor:pointer}
.f2-pbtn:active{transform:scale(.98)}
.f2-scrub{flex:1;min-width:120px;accent-color:var(--eye,#1E6F9F)}
.f2-speed{padding:4px 8px;border-radius:8px;border:1px solid var(--line,#E4DDD1);background:var(--card,#fff);font-weight:700;font-size:12.5px}
.f2-seq{color:#8A968E;font-variant-numeric:tabular-nums;text-align:center}
.f2-lbl{font-weight:600}
.f2-val{font-weight:800;font-variant-numeric:tabular-nums}
.f2-t{color:#5C6B61;font-size:11px;font-variant-numeric:tabular-nums}
.f2-flag{grid-column:2/5;color:#CC3D00;font-weight:700;font-size:11px;display:inline-flex;align-items:center;gap:4px}
.f2-note{grid-column:1/5;color:#9E2F00;font-size:11.5px;background:#CC3D000a;border-radius:5px;padding:3px 8px}
.f2-cont{border:1px solid #CC3D0044;border-inline-start:4px solid #CC3D00;border-radius:8px;padding:8px 10px;margin-bottom:6px;background:#CC3D0008}
.f2-cont-h{font-size:13px;margin-bottom:3px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.f2-cont-a{font-size:12.5px;color:var(--ink);display:flex;gap:6px;align-items:flex-start}
.f2-det{margin:8px 0;border:1px solid var(--line,#E4DDD1);border-radius:8px;padding:2px 10px}
.f2-det>summary{cursor:pointer;font-weight:700;font-size:13px;padding:6px 0;display:flex;align-items:center;gap:6px}
.f2-prof{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px;padding:6px 0}
.f2-grp{border:1px solid var(--line,#E4DDD1);border-radius:8px;padding:6px 8px;background:var(--card2,#FFFFFF)}
.f2-grp-h{font-weight:700;font-size:12px;color:#1E6F9F;margin-bottom:4px;border-bottom:1px solid var(--line,#E4DDD1);padding-bottom:3px}
.f2-kv{display:flex;justify-content:space-between;gap:10px;font-size:12px;padding:2px 0}
.f2-kv>span{color:#5C6B61}
.f2-kv>b{text-align:end;max-width:60%}
.f2-cov{border-color:#1D2C2255;background:rgba(14,124,90,.04)}
.f2-cov>summary{flex-wrap:wrap}
.f2-covbadge{background:color-mix(in srgb, var(--c) 15%, #fff);color:var(--c);border:1px solid var(--c);border-radius:20px;padding:1px 9px;font-size:11px;font-weight:800;margin-inline-start:6px}
.f2-cov .f2-kv>span{display:inline-flex;align-items:center;gap:5px}
.f2-cov .f2-kv .li{width:13px;height:13px}
/* Phase 2: operational firefighting facts panel */
.f2op{border:1px solid #B4560Aaa;background:rgba(180,83,9,.04)}
.f2op-comp{background:color-mix(in srgb, var(--c) 15%, #fff);color:var(--c);border:1px solid var(--c);border-radius:20px;padding:1px 9px;font-size:11px;font-weight:800;margin-inline-start:auto}
.f2op-hz{background:#CC3D0012;border:1px solid #CC3D0055;border-radius:8px;padding:6px 10px;margin:6px 0;font-size:12px;display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.f2op-hz .li{width:15px;height:15px;color:#CC3D00}
.f2op-flag{background:#CC3D00;color:#fff;border-radius:6px;padding:1px 8px;font-size:11px;font-weight:800}
.f2op-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px;margin-top:6px}
.f2op-grp{border:1px solid var(--line);border-radius:8px;padding:6px 10px;background:var(--card)}
.f2op-h{font-weight:800;font-size:11.5px;color:#B4560A;border-bottom:1px solid var(--line);padding-bottom:3px;margin-bottom:4px}
.f2op-kv{display:flex;justify-content:space-between;gap:8px;font-size:12px;padding:1px 0}
.f2op-kv>span{color:var(--mut)} .f2op-kv>b{text-align:end;max-width:58%}
/* Phase 3: nearby fire-relative direction chip */
.f2-ndir{display:inline-flex;align-items:center;gap:4px;background:#B4560A18;color:#B4560A;border:1px solid #B4560A66;border-radius:20px;padding:1px 9px;font-size:12px;font-weight:800}
.f2-ndir .li{width:13px;height:13px} .f2-ndir small{font-weight:600;opacity:.8}
/* Phase 4: spread-risk level badge */
.f2-risk{display:inline-flex;align-items:center;gap:4px;background:var(--rc);color:#fff;border-radius:20px;padding:1px 9px;font-size:11.5px;font-weight:800}
.f2-risk .li{width:13px;height:13px} .f2-risk small{background:#0003;border-radius:10px;padding:0 5px;font-weight:700}
/* Phase 5: resident reconciliation */
.f2rec-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:6px;margin:6px 0}
.f2rec-tile{border:1px solid var(--line);border-inline-start:3px solid var(--tc);border-radius:8px;padding:6px 10px;background:var(--card);text-align:center}
.f2rec-tile>b{display:block;font-size:20px;font-weight:800;color:var(--tc)}
.f2rec-tile>span{font-size:11px;color:var(--mut)}
.f2rec-roster{display:flex;flex-direction:column;gap:3px;margin-top:4px}
.f2rec-row{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:12.5px;padding:3px 8px;background:var(--card);border-radius:6px}
.f2rec-row .li{width:13px;height:13px;vertical-align:-2px}
.f2rec-st{font-weight:700;color:var(--sc);white-space:nowrap;font-size:12px;display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.f2rec-ev{background:var(--bg2);color:var(--mut);border-radius:6px;padding:0 6px;font-weight:600;font-size:11px}
.f2rec-ev .li{width:11px;height:11px}
.f2rec-set{font:inherit;font-size:11px;padding:1px 4px;border:1px solid var(--line);border-radius:6px;background:var(--card);color:var(--ink);max-width:150px}
/* Phase 7: Common Operational Picture */
.cop{border:1px solid #1E6F9Faa;background:rgba(59,111,209,.05)}
.cop-verdict{margin-inline-start:auto;background:var(--vc);color:#fff;border-radius:20px;padding:1px 10px;font-size:12px;font-weight:800;display:inline-flex;align-items:center;gap:4px}
.cop-verdict .li{width:14px;height:14px}
.cop-row{font-size:12.5px;margin:5px 0;display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.cop-src{background:color-mix(in srgb, var(--sc) 15%, #fff);color:var(--sc);border:1px solid var(--sc);border-radius:6px;padding:1px 8px;font-size:11px;font-weight:800}
.cop-people{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0}
.cop-p{background:var(--card);border:1px solid var(--line);border-inline-start:3px solid var(--pc);border-radius:6px;padding:2px 8px;font-size:12px}
.cop-p>b{color:var(--pc);font-weight:800}
.cop-on-row{display:flex;flex-wrap:wrap;gap:10px;margin-top:4px;font-size:11px;color:var(--mut);border-top:1px solid var(--line);padding-top:5px}
.cop-on>b{color:var(--ink)}
/* Phase 8: FRA → decisions */
.frd{border:1px solid #1D2C2266;background:rgba(124,58,237,.04)}
.frd-pri{margin-inline-start:auto;background:#1D2C22;color:#fff;border-radius:20px;padding:1px 10px;font-size:12px;font-weight:800;display:inline-flex;align-items:center;gap:4px}
.frd-pri .li{width:13px;height:13px}
.frd-reasons{font-size:11.5px;color:var(--mut);margin:4px 0;display:flex;flex-wrap:wrap;gap:5px}
.frd-rz{background:#1D2C2214;color:#1D2C22;border-radius:6px;padding:1px 7px;font-weight:600}
.frd-adv{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:12.5px;padding:4px 8px;margin:3px 0;background:var(--card);border-radius:6px;border-inline-start:3px solid #1D2C22}
.frd-adv.frd-hazmat{border-inline-start-color:#CC3D00} .frd-adv.frd-access{border-inline-start-color:#1E6F9F} .frd-adv.frd-evac{border-inline-start-color:#1D2C22}
.frd-k{display:inline-flex;align-items:center;gap:5px} .frd-k .li{width:14px;height:14px}
.frd-src{color:var(--mut);font-size:10.5px;white-space:nowrap;display:inline-flex;align-items:center;gap:3px} .frd-src .li{width:11px;height:11px}
/* Phase 9: confirmation paths A/B/C */
.cp{border:1px solid #CC3D0055}
.cp-verdict{margin-inline-start:auto;background:var(--vc);color:#fff;border-radius:20px;padding:1px 10px;font-size:12px;font-weight:800;display:inline-flex;align-items:center;gap:4px}
.cp-verdict .li{width:14px;height:14px}
.cp-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px;margin:6px 0}
.cp-path{border:1px solid var(--line);border-radius:8px;padding:8px 10px;background:var(--card)}
.cp-path.cp-on{border-color:#127A4B;background:rgba(16,185,129,.05)} .cp-path.cp-off{opacity:.75}
.cp-h{display:flex;align-items:center;gap:5px;font-size:13px} .cp-h .li{width:15px;height:15px}
.cp-on .cp-h .li{color:#127A4B}
.cp-badge{margin-inline-start:auto;background:#127A4B;color:#fff;border-radius:20px;padding:0 8px;font-size:10px;font-weight:800}
.cp-basis{font-size:12px;color:var(--mut);margin-top:3px}
.cp-chain{font-size:11px;color:var(--ink);margin-top:4px;background:var(--bg2);border-radius:6px;padding:3px 6px}
.cp-btn{margin-top:6px;background:var(--eye,#1E6F9F);color:#fff;border:none;border-radius:6px;padding:3px 10px;font-size:11.5px;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:4px}
.cp-btn .li{width:13px;height:13px}
.f2-find{width:100%;border-collapse:collapse;font-size:12px;margin:4px 0}
.f2-find th,.f2-find td{border:1px solid var(--line,#E4DDD1);padding:5px 7px;text-align:start;vertical-align:top}
.f2-find th{background:var(--card2,#FFFFFF);font-size:11.5px}
.f2-sev{font-weight:700;font-size:11px;border-radius:999px;padding:1px 8px;white-space:nowrap}
.f2-meth{margin:4px 0;padding-inline-start:18px;font-size:12.5px;display:flex;flex-direction:column;gap:2px}

/* 🎥 Zoom meeting card */
.mtg-join{display:flex;flex-direction:column;gap:8px;padding:4px 0}
.mtg-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;background:#1E6F9F;color:#fff;font-weight:800;font-size:15px;padding:12px 18px;border-radius:10px;text-decoration:none;transition:filter .15s}
.mtg-btn:hover{filter:brightness(1.06)}
.mtg-kv{display:flex;justify-content:space-between;align-items:center;gap:12px;font-size:13px;padding:5px 2px;border-bottom:1px solid var(--line,#E4DDD1)}
.mtg-kv>span{color:#5C6B61}
.mtg-kv>b,.mtg-kv a>b{font-variant-numeric:tabular-nums;letter-spacing:.5px}
.mtg-kv a{text-decoration:none;color:#1E6F9F}
.mtg-sub{display:inline-flex;align-items:center;gap:6px;color:#1E6F9F;text-decoration:none;font-size:12.5px;margin-top:2px}
.mtg-sub:hover{text-decoration:underline}
.mtg-dial{display:flex;flex-direction:column;gap:2px}

/* 🎥 multi-camera picker + digital zoom controls */
.cam-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:6px 0}
.cam-mode{display:inline-flex;gap:3px;border:1px solid var(--line,#E4DDD1);border-radius:8px;padding:2px}
.cam-mode .mini{border-radius:6px}
.cam-mode .mini.active{background:#1E6F9F;color:#fff}
.card.cam-single .cam-mode #camModeSingle,.card:not(.cam-single) .cam-mode #camModeGrid{background:#1E6F9F;color:#fff}
.card.cam-single #camGrid{display:none}
.card:not(.cam-single) #camView,.card:not(.cam-single) .cam-select,.card:not(.cam-single) .cam-zoom{display:none}
.camgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px}
.cam-evac{display:grid;gap:6px;margin-top:8px}
.cam-evac:empty{display:none}
.camtile{position:relative;border:1px solid var(--line,#E4DDD1);border-radius:10px;overflow:hidden;background:#191C1A;cursor:pointer}
.camtile:hover{outline:2px solid #1E6F9F}
.camtile-img{aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;overflow:hidden;background:#191C1A}
.camtile-img img{width:100%;height:100%;object-fit:cover;display:block}
.camtile-lbl{position:absolute;inset-inline-start:6px;bottom:6px;background:#000a;color:#fff;font-size:11px;padding:2px 8px;border-radius:6px}
.camtile-cnt{position:absolute;inset-inline-end:6px;top:6px;background:#000a;color:#fff;font-size:11px;padding:2px 8px;border-radius:6px}
/* 🕒 The frame's own age, bottom-start of the tile. Quiet while fresh; it only becomes loud once the
   picture has stopped arriving — a frozen feed must announce itself rather than pass for a live one. */
.camtile-age{position:absolute;inset-block-end:6px;inset-inline-start:8px;z-index:2;
  font-size:11px;font-weight:700;color:#E4DDD1;background:rgba(0,0,0,.45);
  border-radius:999px;padding:1px 7px;pointer-events:none;font-variant-numeric:tabular-nums}
.camtile-age.stale{color:#fff;background:rgba(225,29,42,.85)}
/* A tile carrying real continuous video says so, and in a different colour from a frame's age —
   the two are different claims and must not be read as the same badge with a different number. */
.camtile-age.islive{color:#0E2A1C;background:rgba(47,191,113,.92)}
.camtile-vid{display:block;width:100%;height:100%;object-fit:cover;background:#191C1A}
.cam-select{max-width:170px;font-size:12px;padding:3px 6px;border:1px solid var(--line,#E4DDD1);border-radius:7px;background:var(--card,#fff);color:var(--ink)}
.cam-add{flex:1;min-width:120px;font-size:12px;padding:4px 8px;border:1px solid var(--line,#E4DDD1);border-radius:7px}
.cam-videocall{display:inline-flex;align-items:center;gap:5px;background:#1D2C22;color:#fff;text-decoration:none;font-weight:700;border-radius:7px;padding:4px 10px;border:none;cursor:pointer}
.cam-videocall:hover{filter:brightness(1.07)}
.videocall{margin-top:8px;border:1px solid #1D2C2266;border-radius:10px;overflow:hidden;background:#191C1A}
.videocall.hidden{display:none}
.vc-head{display:flex;align-items:center;gap:8px;padding:6px 10px;background:#1D2C2214;color:var(--ink);font-size:13px}
.vc-close{margin-inline-start:auto;background:#CC3D00;color:#fff;border:none;border-radius:6px;padding:3px 10px;cursor:pointer;display:inline-flex;align-items:center;gap:4px}
.jitsi-box{width:100%;height:380px;background:#191C1A}
.jitsi-box iframe{width:100%;height:100%;border:0;display:block}
.vc-setup{padding:20px;color:#E4DDD1;text-align:center;display:flex;flex-direction:column;gap:6px;align-items:center;justify-content:center;height:100%}
.vc-setup .meta{color:#8A968E}
.zoom-cfg{display:flex;flex-direction:column;gap:5px;padding:4px 0}
.zoom-cfg label{font-size:12px;color:#5C6B61;margin-top:4px}
.zoom-cfg input{padding:6px 9px;border:1px solid var(--line,#E4DDD1);border-radius:7px;font-size:13px}
.zoom-cfg .agbtn{align-self:flex-start;margin-top:8px}
.lk-stage{min-height:300px;background:#191C1A;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:6px;padding:6px}
.lk-tile{position:relative;background:#191C1A;border-radius:8px;overflow:hidden;min-height:180px}
.lk-video{width:100%;height:100%;object-fit:cover;display:block}
.lk-lbl{position:absolute;bottom:6px;inset-inline-start:6px;background:#000a;color:#fff;font-size:11px;padding:2px 8px;border-radius:6px}
.lk-ai{position:absolute;top:6px;inset-inline-start:6px;background:#1E6F9Fdd;color:#fff;font-size:11px;font-weight:700;padding:3px 9px;border-radius:6px;display:inline-flex;align-items:center;gap:4px}
.lk-tile.lk-trapped{outline:3px solid #CC3D00;box-shadow:0 0 0 3px #CC3D0055;animation:trappedPulse 1.3s ease-in-out infinite}
.lk-tile.lk-trapped .lk-lbl{background:#CC3D00;color:#fff}
@keyframes trappedPulse{0%,100%{box-shadow:0 0 0 3px #CC3D0033}50%{box-shadow:0 0 0 6px #CC3D0088}}
.vc-trapped{margin-inline-start:auto;background:#CC3D00;color:#fff;border:none;border-radius:6px;padding:3px 10px;cursor:pointer;display:inline-flex;align-items:center;gap:4px}
.vc-close{margin-inline-start:6px}
.vc-endall{background:#9E2F00;color:#fff;border:none;border-radius:6px;padding:3px 10px;cursor:pointer;display:inline-flex;align-items:center;gap:4px;margin-inline-start:6px}
.lk-count{font-size:12px;font-weight:700;color:var(--brand);background:#1D2C2218;border-radius:20px;padding:2px 10px}
/* per-responder tile: RESPONDER outline (green) vs TRAPPED (red) */
.lk-tile.lk-responder{outline:2px solid #1D2C22;box-shadow:0 0 0 2px #1D2C2244}
.lk-tile.lk-responder .lk-lbl{background:#1D2C22;color:#fff}
.lk-kick{position:absolute;top:6px;inset-inline-end:6px;background:#9E2F00dd;color:#fff;border:none;border-radius:6px;width:28px;height:28px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.lk-kick .li{width:15px;height:15px}
/* command roster bar */
.lk-roster{display:flex;flex-wrap:wrap;gap:6px;padding:6px 10px;background:#191C1A08;border-bottom:1px solid var(--line);min-height:10px}
.lk-rchip{display:inline-flex;align-items:center;gap:5px;background:var(--card);border:1px solid var(--line);border-radius:20px;padding:2px 6px 2px 10px;font-size:12px;font-weight:700}
.lk-rchip .li{width:13px;height:13px}
.lk-rchip small{color:var(--mut);font-weight:500}
.lk-rchip.r-trapped{border-color:#CC3D00;color:#CC3D00} .lk-rchip.r-responder{border-color:#1D2C22;color:#1D2C22}
.lk-rkick{background:#9E2F0015;color:#9E2F00;border:none;border-radius:50%;width:22px;height:22px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.lk-rkick .li{width:13px;height:13px}
.vc-trapped-link{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 10px;background:#CC3D0012;border-bottom:1px solid #CC3D0044;font-size:12px}
.vc-trapped-link input{flex:1;min-width:180px;font-size:12px;padding:5px 8px;border:1px solid #CC3D0055;border-radius:6px;direction:ltr}
.sos-inv-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:2px 0}
.sos-qr{margin-top:8px;text-align:center} .sos-qr img{background:#fff;padding:8px;border-radius:8px}
.sos-alerts:empty{display:none}
.sos-alerts{border:1px solid #CC3D0055;background:#CC3D0008}
.sos-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:7px 10px;margin:4px 0;background:var(--card,#fff);border-radius:8px;font-size:13px}
.sos-row a{color:#1E6F9F;text-decoration:none}
.sos-flash{animation:sosFlash 1s ease-in-out infinite}
@keyframes sosFlash{0%,100%{box-shadow:0 0 0 0 #CC3D0000}50%{box-shadow:0 0 0 7px #CC3D0066}}
.incprio.sos-esc{background:#CC3D00;color:#fff;font-weight:800;animation:sosFlash 1.2s infinite}
/* ALL text inside the red priority banner must be white — overrides the global muted `small` + `.prio-bd` */
.incprio.sos-esc,.incprio.sos-esc *{color:#fff}
/* verbatim workbook building profile (registry building view) */
.wp-sec{margin-top:10px}
.wp-sec-h{font-weight:700;font-size:12.5px;color:var(--brand);margin-bottom:3px;padding-inline-start:2px}
.wp-tbl td{padding:4px 8px;vertical-align:top}
.wp-tbl .wp-f{color:var(--mut);width:44%;font-weight:500}
.wp-tbl .wp-v{color:var(--ink);font-weight:600}

/* ── سجل المباني — the building registry ─────────────────────────────────────────────────────────
   Scoped to #buildreg on purpose. Both rules below fix classes that are BROKEN app-wide (`.meta` and
   `.row` have no standalone definition in this sheet), but a global fix reaches thirty other panels
   and four pages that define their own incompatible `.row`. Same call as #evacplan: fix it where the
   defect was reported, leave the sweep to its own change with its own screenshots. */
#buildreg .meta{color:var(--mut);font-size:12px;line-height:1.6}
#buildreg .row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}

/* THE FRA PASSPORT IS LATIN TEXT INSIDE AN RTL PARAGRAPH, AND THE BIDI ALGORITHM WAS REORDERING IT.
   The workbook stores «2800 persons», «17 (3B+G+M+11+RF)», «400,000 L». Rendered into an rtl cell,
   the leading digits are BIDI-WEAK: they take the paragraph direction, the Latin word beside them
   takes its own, and the reader sees «persons 2800», «(3B+G+M+11+RF) 17», «L 400,000». The value was
   never wrong in the database — only on the screen, which is the harder kind to notice, and this is
   the water-tank capacity and the floor count of a tower on a fire-command console.

   `unicode-bidi:plaintext` resolves each value's direction from its OWN first strong character, so a
   Latin value lays out LTR and an Arabic one stays RTL — without hardcoding either. `text-align:start`
   would then follow the RESOLVED direction and shunt Latin values to the left of an RTL table, so the
   alignment is pinned separately to keep the column edge intact. */
#buildreg .wp-tbl .wp-v{unicode-bidi:plaintext}
html[dir=rtl] #buildreg .wp-tbl .wp-v{text-align:right}
html[dir=ltr] #buildreg .wp-tbl .wp-v{text-align:left}
/* The field NAMES are Latin identifiers too (Building_ID, Occupancy_Pattern) — same treatment. */
#buildreg .wp-tbl .wp-f{unicode-bidi:plaintext}
html[dir=rtl] #buildreg .wp-tbl .wp-f{text-align:right}
html[dir=ltr] #buildreg .wp-tbl .wp-f{text-align:left}

/* 83 fields over 14 sections arrived as one undivided wall. Each section becomes its own bounded
   block so the eye can find «Fire Protection Systems» without reading the twelve rows above it. */
/* ملفُّ الـFRA ثمانيةٌ وسبعون حقلًا في أربعة عشر قسمًا، كلُّها عمودٌ واحد بعرض ١٢٥٠ بكسل: كلُّ صفٍّ
   اسمُه في طرفٍ وقيمتُه في الطرف الآخر وبينهما فراغٌ لا يحمل شيئًا — ٣٤٧٠ بكسل طولًا لملء نصف العرض،
   وهي وحدها ٣٧٪ من الصفحة. والأقسام صناديقُ مغلقةٌ بذاتها، فتُصفّ في شبكةٍ تملأ العرض المتاح.
   لا شيء يُطوى ولا شيء يُخفى — الطولُ وحده هو ما ينقسم، والقاعدةُ التي تمنع طيَّ سجلِّ حمايةِ برجٍ
   خلف سهمٍ تبقى قائمةً كما هي.
   وهي أعمدةٌ متدفّقة (`columns`) لا شبكةُ صفوف: الأقسام تتفاوت من حقلٍ واحد إلى عشرة، فالشبكةُ
   تُحاذيها صفًّا صفًّا وتترك تحت القصير فراغَ الطويل (١٤٥٣ بكسل)، بينما التدفّق يوازن الأعمدة
   ويحشو الفراغ (٩٨٦). `break-inside:avoid` يمنع انقسام قسمٍ بين عمودين — ونصفُ جدولٍ في أسفل عمود
   يقرأ «مقطوعًا» لا «مُكمَّلًا». */
/* 🏗️ «المبنى نفسه» — صفٌّ واحد لكلّ حقل: اسمُه، مُدخَلُه، ثمّ حالتُه.
   كان الحقل يُرسم مرّتين (صفَّ قراءةٍ يقول «غير مسجَّل»، ومُدخَلًا مجهولًا تحته)، وستٌّ من قوائمه
   بلا عنوانٍ إلّا في `title` وبعرض ١٦٠١ بكسل — الرشّاشاتُ والتكسيةُ ومصعدُ الإطفاء قضبانٌ متطابقة.
   والسببُ الجذريُّ للعرض هنا: `.br-form input` مسقوفٌ بـ١٨٠ ولم يكن للـ`select` سقفٌ أصلًا. */
#buildreg .bf-tbl{table-layout:fixed;width:100%}
#buildreg .bf-tbl .bf-lab{width:46%;font-weight:600;color:var(--ink2);text-align:start;padding:7px 11px;
  font-size:13px;overflow-wrap:anywhere}
#buildreg .bf-tbl .bf-lab .bf-ok{vertical-align:-2px}
#buildreg .bf-tbl .bf-ctl{width:54%;padding:5px 11px}
#buildreg .bf-tbl .bf-ro{padding-inline-start:2px}
#buildreg .bf-tbl .bf-ctl input,#buildreg .bf-tbl .bf-ctl select{width:100%;max-width:260px;
  padding:6px 9px;border:1px solid var(--line);border-radius:8px;font-size:13px;background:#fff;color:var(--ink)}
#buildreg .bf-tbl tr:not(:last-child) th,#buildreg .bf-tbl tr:not(:last-child) td{border-bottom:1px solid var(--line)}
/* الحقلُ غير المُسجَّل يُوسَم ولا يُصرَخ به: تسعةٌ من اثني عشر غيرُ مسجَّلة هنا، فلو أخذ كلٌّ منها
   لونَ تحذيرٍ لأغرق الثلاثةَ المسجَّلة. الأرضيّةُ الباهتة تقول «ينقصك هذا» بلا أن تدّعي خطرًا. */
#buildreg .bf-tbl .bf-unset{background:color-mix(in srgb,var(--card2) 55%,transparent)}
#buildreg .bf-tbl .bf-unset .bf-lab{color:var(--mut);font-weight:500}
#buildreg .bf-tbl .bf-ok{color:var(--sev-low);display:inline-flex}
#buildreg .bf-tbl .bf-ok .li{width:15px;height:15px}
#buildreg .bf-actions{justify-content:flex-end;margin:10px 0 0}
/* حقولُ الصيانة إلى جانب حالةِ العقد التي تصفها، معنونةً لا مُلقاةً في صفٍّ من مُدخَلات بلا أسماء */
#buildreg .bf-maint{align-items:flex-end;gap:10px;margin:8px 0 4px}
#buildreg .bf-maint .fld{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--mut)}
#buildreg .bf-maint .fld input{max-width:190px}
/* 🩹 السببُ الجذريّ، وهو عامٌّ لا خاصٌّ بهذه البطاقة: كلُّ `select` في كلّ `.br-form` في هذا القسم
   (السكّان، الكاميرات، الأجهزة، المخارج) كان بلا سقفِ عرضٍ بينما جارُه `input` مسقوفٌ بـ١٨٠. */
#buildreg .br-form select{max-width:200px}
#buildreg .wp-grid{columns:330px;column-gap:12px}
#buildreg .wp-grid .wp-sec{margin-top:0;margin-bottom:12px;break-inside:avoid;-webkit-column-break-inside:avoid}
/* الأقسام التي يُفتَح لأجلها هذا الملفُّ في حريق (الحماية، الماء، سلامة الحياة، المواد الخطرة)
   تُعلَّم بحافّةٍ واحدة وترويسةٍ أغمق. علامةٌ واحدة لا لونٌ ثانٍ: سلّم الخطورة لا يُستعار للأهميّة. */
#buildreg .wp-sec.wp-hot{border-color:color-mix(in srgb,var(--eye) 38%,var(--line))}
#buildreg .wp-sec.wp-hot .wp-sec-h{background:color-mix(in srgb,var(--eye) 8%,var(--card2));color:var(--eye)}
#buildreg .wp-sec.wp-hot .wp-sec-h .li{color:var(--eye)}
/* وسمُ المصدر: نغمةٌ واحدة هادئة، لا شريحةٌ بحجم القيمة التي تصفها */
#buildreg .wp-own{display:inline-block;font-size:10.5px;font-weight:700;line-height:1.5;padding:0 5px;
  border-radius:5px;background:color-mix(in srgb,var(--sev-medium) 13%,#fff);color:var(--sev-medium);
  border:1px solid color-mix(in srgb,var(--sev-medium) 28%,#fff);white-space:nowrap}
#buildreg .wp-sec{margin-top:12px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
#buildreg .wp-sec-h{margin:0;padding:7px 11px;background:var(--card2);border-bottom:1px solid var(--line);
  display:flex;align-items:center;gap:7px}
#buildreg .wp-sec-h .li{width:15px;height:15px}
#buildreg .wp-sec .wp-tbl{margin:0}
/* قيمةٌ واحدة بلا فراغات (`25(3B+G+M+19+RF)`, `NFPA 101 (Legacy Version)`) كانت تدفع الجدول أعرضَ من
   قسمه، و`overflow:hidden` أعلاه يقصّها قصًّا — أي يبتلع آخِرَ سطرٍ في سجلِّ حمايةِ برج. تُلَفُّ الآن
   لَفًّا: الطولُ يزيد ولا يضيع حرف. */
#buildreg .wp-sec .wp-tbl td{padding:6px 11px;overflow-wrap:anywhere}
#buildreg .wp-sec .wp-tbl tr:not(:last-child) td{border-bottom:1px solid var(--line)}

/* A count of ZERO and a count of four must not read alike: on this page 0 cameras means nothing was
   ever registered, which is the gap an operator is here to close. Muted, so the non-zero cells carry
   the ink. */
#buildreg .br-zero{color:var(--mut);font-weight:400}
/* was a hardcoded #CC3D00 inline — the sheet's own note reserves severity encoding to the --sev ramp */
#buildreg .br-vuln{color:var(--sev-high)}

/* Deleting a building deletes its residents, cameras, devices and floor plans. It sat as a bare icon
   button flush against «open», one mis-aimed click away. Held back to a muted outline until hover,
   and separated from the primary action by a rule. */
#buildreg .br-del{color:var(--mut);border-color:var(--line);background:transparent;box-shadow:none;
  margin-inline-start:8px;padding-inline-start:10px;border-inline-start:1px solid var(--line);border-radius:8px}
#buildreg .br-del:hover{color:var(--sev-critical);border-color:color-mix(in srgb,var(--sev-critical) 45%,var(--line));
  background:color-mix(in srgb,var(--sev-critical) 7%,transparent)}

/* `.ag-rec` is the AGENT-RECOMMENDATION row — hardcoded alarm pink (#FFE7DC/#FFE7DC). The
   surroundings list reused it for every building that HAS a snapshot, so the one tower with data
   rendered as an alert while the three with NO data rendered calm: the signal was exactly inverted.
   Neutralised here; the exposure score keeps its own colour via `.tprio`. */
#buildreg .ag-rec{background:var(--card2);border-color:var(--line)}
#buildreg .ag-rec .meta{color:var(--mut)}
.sos-crit{background:#CC3D00;color:#fff;font-weight:800;border-radius:6px;padding:1px 8px;margin-inline-start:6px;font-size:11px}
.sos-flr{display:inline-flex;align-items:center;gap:3px;background:var(--bg2,#F2F2F2);border-radius:6px;padding:1px 7px;font-weight:700;font-size:12px;color:var(--ink)}
.sos-flr .li{width:13px;height:13px}
.sos-ppl{display:inline-flex;align-items:center;gap:3px;background:#FFE7DC;color:#B4560A;border-radius:6px;padding:1px 7px;font-weight:600;font-size:12px}
.sos-ppl .li{width:13px;height:13px}
.sos-tel{display:inline-flex;align-items:center;gap:3px;background:#F2F2F2;color:#1D2C22;border-radius:6px;padding:1px 7px;font-weight:700;font-size:12px;text-decoration:none}
.sos-tel .li{width:13px;height:13px}
/* 🔥 fire gate (login) */
.fire-gate{text-align:center} .fire-gate.hidden{display:none}
.fire-gate .fg-q{font-size:26px;margin:10px 0 4px;color:#CC3D00;font-weight:900;
  display:flex;align-items:center;justify-content:center;gap:10px}
.fire-gate .fg-q .li{width:28px;height:28px;color:#CC3D00}
.fg-btns{display:flex;gap:10px;margin:16px 0 6px}
.fg-yes{flex:2;padding:16px;border:none;border-radius:12px;background:#CC3D00;color:#fff;font-size:17px;font-weight:800;cursor:pointer;box-shadow:0 6px 20px #CC3D0055}
.fg-yes:hover{filter:brightness(1.06)}
.fg-no{flex:1;padding:16px;border:1px solid var(--line,#E4DDD1);border-radius:12px;background:var(--card2,#FFFFFF);color:var(--ink);font-size:16px;font-weight:700;cursor:pointer}
.fg-nomsg{margin-top:10px;font-size:13px;color:#5C6B61} .fg-nomsg a{color:#1E6F9F}
/* secondary path for building staff/residents — skips the civil-defence dispatch question entirely */
.fg-staff{margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.fg-staff a{font-size:12.5px;color:var(--info);text-decoration:none;font-weight:600}
.fg-staff a:hover{text-decoration:underline}
.cam-zoom{display:inline-flex;align-items:center;gap:3px;margin-inline-start:auto}
.cam-zoom .mini{padding:3px 7px;line-height:1;display:inline-flex;align-items:center}
.cam-zlvl{font-size:11px;color:#5C6B61;font-variant-numeric:tabular-nums;min-width:34px;text-align:center}
.camview{overflow:hidden}
.camview img.cam-frame{transition:transform .08s linear;will-change:transform;max-width:100%}

/* Skip link (WCAG 2.4.1 Bypass Blocks). Off-screen until focused, then clearly visible — a keyboard or
   screen-reader user on /sos must be able to reach the rescue button without traversing the header. */
.skip-link{position:absolute;inset-inline-start:-9999px;top:0;z-index:100;background:var(--danger);color:#fff;
  padding:12px 18px;border-radius:0 0 10px 0;font-weight:800;text-decoration:none;font-size:15px}
.skip-link:focus{inset-inline-start:0}
/* Focus must stay visible even where a component sets its own outline:none. 3:1 against both the card
   and the page background, and never conveyed by colour alone — it is a ring, not a tint. */
:where(a,button,[role=button],input,select,textarea,[tabindex]):focus-visible{
  outline:3px solid var(--info);outline-offset:2px;border-radius:6px}

/* Sign-language panel on /sos (English). The gloss is the authored part; the avatar appears only when a
   signer has filled in HamNoSys AND a local CWASA build is configured — see signlang.py. */
.sign-gloss{list-style:decimal;padding-inline-start:22px;margin:8px 0 0}
.sign-gloss li{margin:0 0 10px;line-height:1.5}
.sg-tokens{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:3px}
.sg-t{display:inline-block;background:var(--card2);border:1px solid var(--line);border-radius:6px;
  padding:2px 7px;font-weight:800;font-size:12.5px;letter-spacing:.4px}
.sg-en{display:block;font-size:12.5px;color:var(--mut)}
.sg-ok,.sg-gloss-only{display:inline-block;margin-top:3px;font-size:11px;font-weight:700;
  border-radius:5px;padding:1px 6px}
.sg-ok{background:#1D2C221a;color:#1D2C22}
.sg-gloss-only{background:var(--card2);color:var(--mut)}
.sign-avatar{margin-top:10px}
/* Signer clips — the PRIMARY sign path. A real certified signer, served from this host. */
.sign-videos{display:grid;gap:12px;margin:10px 0 4px}
.sign-videos .sv{margin:0}
.sign-videos video{width:100%;max-height:280px;background:#191C1A;border-radius:12px;border:1px solid var(--line)}
.sign-videos figcaption{font-size:12.5px;color:var(--mut);margin-top:4px;display:flex;gap:7px;align-items:baseline}
.sv-n{flex:0 0 auto;background:var(--brand);color:#fff;border-radius:50%;width:19px;height:19px;
  display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:800}
/* /sos alarm self-test. Present at all times: the alarm was previously only reachable through a live
   fire alert, so nobody could confirm beforehand that they would hear it. */
.sos-audio-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:10px 0 2px}
.sos-sound{display:inline-flex;align-items:center;gap:7px;padding:10px 16px;border-radius:12px;
  border:1.5px solid var(--brand);background:#fff;color:var(--brand);font-weight:800;font-size:14px;cursor:pointer}
.sos-sound:hover{background:var(--brand);color:#fff}
.sos-sound:disabled{opacity:.55;cursor:progress}
.sos-audio{flex:1 1 220px;font-size:12.5px;line-height:1.5}
.sos-audio small{color:var(--mut)}
.sos-audio.ready{color:#1D2C22}
.sos-audio.blocked,.sos-audio.unknown{color:var(--warn)}
/* Honest TTS status. The old code failed mute when a device had no voice for the language. */
.tts-note{margin-top:6px;font-size:12.5px;color:var(--warn);line-height:1.5;max-width:44em}
.tts-note.hidden{display:none}

/* ── scope guard on the incident dossier ──────────────────────────────────────────────────────────
   A commander whose /api/incidents/{id} returns 403 used to keep the PREVIOUS user's dossier on
   screen: the fetch failed, the code returned silently, and every card stayed exactly as rendered —
   building, resident names, apartment numbers, confirmation state. The dashboard honestly said
   "0 incidents" while a full dossier sat underneath it.
   Hiding named elements one by one would rot the moment a new card is added to the section, so this
   hides EVERY child except the explanation. A card added next year is covered without being listed. */
#incident.scope-blocked > *:not(#incBlocked){ display:none !important; }
#incBlocked{ margin:14px 0; border:2px solid #5C6B61; background:#5C6B6111; border-radius:var(--r,12px);
  padding:16px 18px; color:#5C6B61; max-width:52em }
#incBlocked b{ display:flex; align-items:center; gap:9px; font-size:15px; margin-bottom:6px }
#incBlocked .li{ width:18px; height:18px; flex:none }
#incBlocked .meta{ color:#5C6B61; line-height:1.6 }

/* ── خطة الإخلاء — the commander's evacuation plan ────────────────────────────────────────────────
   The gaps card is styled to be READ, not skipped: it sits above the plan and carries a warning edge,
   because a commander who misses "no stairs entered" will read the phases as routes.

   THE TOKEN FALLBACKS ARE GONE (2026-08-16). Every `var(--x,#literal)` in this block could only ever
   reach the literal if :root had failed to load — and :root is in THIS FILE, so it never can. What
   the fallbacks actually did was rot: --warn was darkened #B4560A → #B4560A to pass WCAG AA, while
   the fills beside it stayed hardcoded #B4560A14, so the 4px border and the panel it bordered were
   painting two different hues of "amber". Same rot for --bg2 (#FFFFFF → #FFFFFF) and --mut
   (#5C6B61 → #5C6B61). A fallback for a token defined 2000 lines above is a second, silent copy of
   the palette that stops tracking the first one.

   --fire was that fault one step worse: it is declared NOWHERE in this sheet, so all five uses were
   the bare literal with no token behind them at all — this panel had quietly disconnected itself
   from the severity ramp. The real name is --sev-critical, identical in value today, which makes the
   swap a zero-pixel diff that reconnects it. */
#evacplan .ep-strat{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:8px 0 4px;font-size:15px}
#evacplan .ep-reason{margin:6px 0;padding:10px 12px;background:var(--bg2);border-radius:10px;line-height:1.65}
#evacplan .ep-defer{margin:8px 0;padding:11px 13px;border-inline-start:4px solid var(--warn);
  background:color-mix(in srgb,var(--warn) 8%,transparent);border-radius:10px}
#evacplan .ep-conflict{margin-top:6px;padding:8px 11px;border-inline-start:4px solid var(--sev-critical);
  background:color-mix(in srgb,var(--sev-critical) 7%,transparent);border-radius:9px;font-size:13px}
#evacplan .ep-gaps{border-inline-start:4px solid var(--warn)}
#evacplan .ep-ul{margin:6px 0 0;padding-inline-start:20px;line-height:1.75}
#evacplan .ep-ul li{margin-bottom:4px}
#evacplan .fld{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:700;color:var(--ink2)}
#evacplan .ep-note{margin:8px 0 0;padding:9px 12px;background:color-mix(in srgb,var(--info) 6%,transparent);
  border-inline-start:3px solid var(--info);border-radius:9px;font-size:12.5px;color:var(--ink2);line-height:1.6}
#evacplan .ep-note .li{width:15px;height:15px;vertical-align:-.2em;color:var(--info)}
#evacplan .ep-clamp{margin:8px 0;padding:10px 12px;border-inline-start:4px solid var(--warn);
  background:color-mix(in srgb,var(--warn) 10%,transparent);border-radius:9px;font-size:13px}
#evacplan .ep-cites{margin:7px 0 0;display:flex;flex-wrap:wrap;gap:5px;align-items:center}

/* `.meta` has NO rule anywhere in this sheet. A standalone <div class="meta"> therefore computes to
   14px/--ink — pixel-identical to primary body text — and this one render emits about twelve of
   them, several carrying long Arabic paragraphs. (<small class="meta"> looks right only because the
   global `small` rule is doing the work, which is what hid this for so long.)
   SCOPED, not global: `.meta` appears on every screen in this product, and a global 12px would
   resize thirty panels for the sake of one. */
#evacplan .meta{color:var(--mut);font-size:12px;line-height:1.6}

/* `.row` has exactly one definition in this sheet — `.ai-dec .row` — so every OTHER class="row"
   computes to display:block. Both of this panel's rows were laid out as full-width stacked blocks
   because of it, inline `gap` and `flex-wrap` doing nothing at all.
   SCOPED, emphatically: class="row" appears 31× across seven pages, and arc/command/inspector/i999
   each define their OWN `.row` in a page-local <style> with mutually incompatible rules (space-between
   + top border vs wrap + gap). driver.html and responder.html define none and would change under a
   global rule. There is no single global value that is correct. */
#evacplan .row{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end}

/* A data gap and a triggered constraint are the same SHAPE of statement: a severity, a sentence, and
   the measured fact behind it. Nothing else in this sheet carries a severity edge without also
   carrying another panel's meaning — `.collab-node` belongs to the agent orchestrator, `.rfi-item`
   to the RFI inbox — and coupling a life-safety gaps list to either means a future orchestrator
   change silently restyles it. So: one new primitive, scoped, serving both cards.

   The severity token colours the EDGE and the ICON, never the sentence. --sev-high measures 3.09:1
   on white: enough for a 3px rule (AA non-text is 3:1), nowhere near the 4.5:1 a word needs. That is
   the same measurement that forced --warn from #B4560A to #B4560A. */
#evacplan .ep-row{display:flex;gap:9px;align-items:flex-start;background:var(--card2);
  border:1px solid var(--line);border-inline-start:3px solid var(--gc,var(--line));
  border-radius:9px;padding:8px 11px;margin-top:6px;font-size:12.5px;line-height:1.6}
#evacplan .ep-row>.li{width:15px;height:15px;flex:0 0 auto;margin-top:2px;color:var(--gc,var(--mut))}
#evacplan .ep-row-b{min-width:0;flex:1 1 auto}
#evacplan .ep-row-b>b{color:var(--ink)}
#evacplan .trail-row>div{min-width:0;flex:1 1 auto}

/* `.ag-chip` sizes its icon via `.ag-chip .lucide` — but LI() emits class="li", so every icon inside
   an 11px chip renders at the 18px `.li` default and swamps the label. Scoped here; the same
   one-line fix belongs beside `.ag-chip .lucide` for the other ~60 call sites, as its own change
   with its own screenshot pass. */
#evacplan .ag-chip .li{width:13px;height:13px}

/* ── the grounding badge + الاستدلال console ──────────────────────────────────────────────────────
   Two AI claims, two looks. Green shield = a decision that cites clauses; grey speech = prose over
   measured facts. They must never look interchangeable — that similarity was the defect. */
/* AI Decision Engine card (Thinker) */
.ai-dec .row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.ai-dec-mini{border:1px solid color-mix(in srgb,#1D2C22 28%,transparent);border-radius:10px;padding:8px 10px;background:color-mix(in srgb,#1D2C22 6%,#fff)}
#aiDecisionCard .card-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
#aiDecisionCard .card-h .mini{margin-inline-start:auto}
.ai-badge{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:999px;
  font-size:11.5px;font-weight:700;vertical-align:middle;margin-inline-start:6px;cursor:help}
.ai-badge .li{width:13px;height:13px}
.ai-badge code{background:#191C1A0f;border-radius:5px;padding:0 5px;font-size:11px;font-weight:600}
.ai-badge.g{background:#127A4B1e;color:#1D2C22}
.ai-badge.n{background:#5C6B611a;color:var(--mut,#5C6B61)}
#reason textarea{border:1px solid var(--line,#E4DDD1);border-radius:11px;padding:11px 13px;font:inherit;
  background:var(--card,#fff);color:var(--ink,#191C1A);resize:vertical;line-height:1.6}
/* This is a VERBATIM DUPLICATE of the #evacplan .ep-* block above, and it stays duplicated on
   purpose. #reason is a separate life-safety surface with its own reviewer; unifying the two would
   land every edit made for the evacuation panel on the reasoning console in the same commit — and
   half of them would break it, because renderReason() still emits <span class="pill mut conf-model">
   which the evac panel has stopped emitting. Fourteen lines is a cheap price for keeping two safety
   screens independent. Dedup later as a no-op refactor, with both screens screenshotted before and
   after and nothing else in the diff.
   The stale token fallbacks ARE fixed here, because that is a pure correctness change: --warn was
   darkened for AA and --bg2 moved, so border and fill had drifted to different hues here too. */
#reason .ep-strat{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:8px 0 4px;font-size:15px}
#reason .ep-reason{margin:6px 0;padding:10px 12px;background:var(--bg2);border-radius:10px;line-height:1.65}
#reason .ep-defer{margin:8px 0;padding:11px 13px;border-inline-start:4px solid var(--warn);
  background:color-mix(in srgb,var(--warn) 8%,transparent);border-radius:10px}
#reason .ep-ul{margin:6px 0 0;padding-inline-start:20px;line-height:1.75}
#reason .ep-ul li{margin-bottom:6px}
#reason .card.collapsed .ep-ul{display:none}
#reason .fld{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:700;color:var(--ink2)}
#reason .pill.ok{background:#127A4B1e;color:#1D2C22}
#reason .pill.warn{background:#B4560A22;color:#B4560A}
#reason .pill.mut{background:color-mix(in srgb,var(--mut) 12%,transparent);color:var(--mut)}


/* ── drag-to-reorder in the alert-workflow editor ───────────────────────────────────────────── */
.af-drag{cursor:grab;display:inline-flex;align-items:center;padding:4px 2px;color:#8A968E;
  touch-action:none}          /* touch-action:none — or the browser scrolls instead of dragging */
.af-drag:hover{color:var(--brand,#1E6F9F)}
/* NO pointer-events:none here. The pointer is captured on the drag handle, which lives INSIDE this
   element — disabling pointer events on the ancestor silently kills the capture, so `pointermove`
   never fires and the row appears to drag but never reorders. Hit-testing is not needed: the drop
   position is computed from getBoundingClientRect midpoints, not from what is under the cursor. */
.af-stage.af-dragging{opacity:.9;cursor:grabbing;position:relative;z-index:30;
  box-shadow:0 10px 26px rgba(0,0,0,.18)}
.af-drop{border:2px dashed var(--brand,#1E6F9F);border-radius:12px;height:52px;margin:8px 0;
  background:rgba(14,116,144,.06)}


/* A stand-down notice must not look like an alarm — green, calm, no flash. */
#fireAlertBanner.fa-notice{background:#DFF5EA;border-color:#127A4B;color:#1D2C22;animation:none}
#fireAlertBanner.fa-notice .li{color:#127A4B}
@media (prefers-color-scheme:dark){
  #fireAlertBanner.fa-notice{background:#0E2A1C;border-color:#1D2C22;color:#DFF5EA}
}

/* Assisted-evacuation table on the evacuation-plan screen. The chips wrap because a person may have
   several needs and a clipped need is a need nobody reads. `width` is set on the numeric columns
   only — a blanket width rule in this stylesheet once stretched checkboxes to 261px. */
.ep-assist{width:100%;border-collapse:collapse;margin-top:10px}
.ep-assist th,.ep-assist td{padding:7px 9px;border-bottom:1px solid var(--line,#E4DDD1);text-align:start;vertical-align:top}
.ep-assist th{font-size:12px;color:#5C6B61;font-weight:600}
.ep-assist th:nth-child(1),.ep-assist td:nth-child(1){width:64px}
.ep-assist th:nth-child(2),.ep-assist td:nth-child(2),
.ep-assist th:nth-child(3),.ep-assist td:nth-child(3){width:92px}
.ep-assist td:nth-child(2) b,.ep-assist td:nth-child(3) b{font-variant-numeric:tabular-nums}
.ep-assist .ag-chip{margin:2px 4px 2px 0}

.ucreate{margin-top:12px;border-top:1px solid var(--line,#E4DDD1);padding-top:10px}
.ucreate label{display:flex;flex-direction:column;gap:3px;font-size:12px;color:#5C6B61}
.ucreate input[type=text],.ucreate input[type=password],.ucreate input:not([type]),
.ucreate select{min-width:150px;padding:6px 8px;border:1px solid var(--line,#E4DDD1);border-radius:6px}


/* ⏱️ ساعات المسار — البطاقة التي وضعت `arcCallAfterSeconds` في صفحة الإنذار بدل تبويب القواعد.
   نفس لغة محرّر المراحل تحتها: بطاقات هادئة، والرقم هو العنصر البارز الوحيد. */
.afc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:10px}
.afc{border:1px solid var(--line);border-radius:10px;padding:12px 14px;background:var(--card2)}
.afc-h{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:9px}
.afc-l{font-weight:700;font-size:13.5px;line-height:1.4}
.afc-ov{font-size:11px;color:var(--mut);border:1px solid var(--line);border-radius:999px;padding:1px 7px;white-space:nowrap}
.afc-num{display:flex;align-items:center;gap:8px}
.afc-num input{width:104px;font-size:19px;font-weight:700;text-align:center;padding:7px 8px;
  border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink);
  font-variant-numeric:tabular-nums;font-family:inherit}
.afc-u{font-size:12.5px;color:var(--mut)}
.afc-sw{display:flex;align-items:center;gap:9px;font-size:13.5px;font-weight:600;cursor:pointer}
.afc-sw input{width:17px;height:17px;accent-color:#1D2C22;cursor:pointer}
.afc-e{margin-top:9px;font-size:12px;color:var(--mut);line-height:1.65}
.afc-k{margin-top:7px;font-size:10.5px;color:var(--mut);opacity:.7;letter-spacing:.02em}
.afc-bar{display:flex;align-items:center;gap:12px;margin-top:12px;flex-wrap:wrap}
.afc-msg{font-size:12.5px;color:var(--mut)}

/* ═══ the activation lock — the daily code (server/activation.py) ═══════════════════════════════ */
.login-card.act-gate{width:min(540px,calc(100vw - 32px))}
.act-form{display:flex;gap:10px;margin:18px 0 6px;flex-wrap:wrap;justify-content:center}
.act-input{flex:1 1 240px;min-width:0;padding:14px 12px;font-size:20px;letter-spacing:.14em;text-align:center;
  font-family:ui-monospace,Menlo,Consolas,"Liberation Mono",monospace;text-transform:uppercase;
  border:1px solid var(--line,#E4DDD1);border-radius:12px;background:var(--card2,#FFFFFF);color:var(--ink)}
.act-input:focus{outline:2px solid #1D2C22;outline-offset:1px}
.act-form .fg-yes{flex:0 0 auto;padding:14px 22px;background:#1D2C22;box-shadow:0 6px 20px #1D2C2255}
.act-meta{margin-top:8px;font-size:12px;color:var(--mut)}
.fg-nomsg.err{color:#9E2F00;font-weight:600}
.fg-nomsg.ok{color:#127A4B;font-weight:600}
#st-act{background:#39443C;color:#fff;border-color:#127A4B}
#st-act.warn{background:#9E2F00;color:#fff;border-color:#9E2F00}

/* ═══ سجل المباني — الطريقُ إلى الوراء، والترويسةُ مُجمَّعة، والبياناتُ قبل النماذج (2026-09-09) ═══
   See openBuilding() for the why. Everything here is the console's own vocabulary (card, kpi-row,
   mini-btn, ag-chip, --eye), not a new look. */
#buildreg .br-hdr{padding-top:12px}
.br-crumb{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--mut);margin:0 0 10px}
.br-crumb a{color:var(--eye);text-decoration:none;font-weight:700;display:inline-flex;align-items:center;gap:5px}
.br-crumb a:hover{text-decoration:underline}
.br-crumb .li{width:14px;height:14px;color:var(--eye)}
.br-crumb b{color:var(--ink);font-weight:700}
.br-crumb-sep{opacity:.6}
.br-id{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding-bottom:12px;border-bottom:1px solid var(--line);margin-bottom:12px}
.br-backbtn{padding:8px 12px;font-size:13px;font-weight:700;border-color:var(--eye);color:var(--eye);background:color-mix(in srgb,var(--eye) 8%,#fff);flex:0 0 auto}
.br-backbtn:hover:not([disabled]){background:var(--eye);color:#fff}
.br-backbtn .li{width:16px;height:16px}
/* one vendored arrow, mirrored for a left-to-right reader: "back" points to where the list is */
html[dir=ltr] .br-backbtn .li{transform:scaleX(-1)}
.br-id-main{min-width:0;flex:1 1 240px}
.br-name{font-size:20px;font-weight:800;line-height:1.2;letter-spacing:-.2px;color:var(--ink)}
.br-meta{display:flex;flex-wrap:wrap;gap:4px 14px;color:var(--mut);font-size:12.5px;margin-top:3px}
.br-meta .br-code{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:12px}
.br-actions{display:flex;gap:8px;flex-wrap:wrap;margin-inline-start:auto}
#buildreg .br-contacts{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px;padding:0;background:none;margin:0 0 10px;font-size:12.5px}
.br-ct{display:flex;flex-direction:column;gap:3px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:#fff;min-width:0}
.br-ct-role{font-size:11.5px;color:var(--mut);display:inline-flex;gap:6px;align-items:center}
.br-ct-role .li{width:14px;height:14px;color:var(--mut)}
.br-ct-name{font-size:14px;color:var(--ink)}
.br-ct a{font-size:13px}
.br-ct .ag-chip{align-self:flex-start;margin-top:2px}
.br-ct-act{justify-content:center;align-items:flex-start;border-style:dashed}
.br-kgrp{margin-top:12px}
.br-kgrp-h{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;color:var(--ink2);margin:0 0 8px}
.br-kgrp-h .li{width:15px;height:15px;color:var(--mut)}
.br-kgrp-h .br-src{font-weight:600;background:#F4F4F3;color:var(--mut);border-color:var(--line);margin-inline-start:2px}
.br-kgrp-h .br-src .li{width:12px;height:12px}
.br-add{margin:12px -18px -16px;padding:10px 18px 14px;background:#FAFAF9;border-top:1px solid var(--line);border-radius:0 0 var(--r) var(--r)}
.br-add .br-form{margin:0}
.br-add-l{font-size:11.5px;font-weight:700;color:var(--mut);margin-bottom:6px;display:flex;gap:5px;align-items:center}
.br-add-l .li{width:13px;height:13px}
.br-form-grp{display:flex;flex-wrap:wrap;gap:10px 14px;align-items:flex-start}
.br-fg{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:8px 10px;border:1px dashed var(--line);border-radius:10px;background:#fff}
.br-fg-l{flex-basis:100%;font-size:11px;font-weight:700;color:var(--mut)}
.br-fg-wide{flex:1 1 100%}
.br-fg-act{border:0;padding:0;background:none;align-self:flex-end}
#buildreg tr.br-row{cursor:pointer}
#buildreg tr.br-row:hover td{background:color-mix(in srgb,var(--eye) 6%,#fff)}
#buildreg tr.br-row:focus-visible{outline:2px solid var(--eye);outline-offset:-2px}
#buildreg tr.br-row[hidden]{display:none}
.br-search{padding:6px 10px;border:1px solid var(--line);border-radius:8px;font-size:12.5px;background:#fff;color:var(--ink);min-width:220px;font-family:inherit;font-weight:400}
.br-search:focus-visible{outline:2px solid var(--eye);outline-offset:1px;border-color:var(--eye)}

/* ═══ سجل المباني — لوحة التعديل داخل الصفّ (2026-09-09) — see _brEditPanel() ═══ */
#buildreg tr.br-editrow>td{padding:8px 6px 12px;background:transparent}
.br-edit{background:#F6F9F8;border:1px solid color-mix(in srgb,var(--eye) 34%,var(--line));border-radius:12px;padding:12px 14px}
.br-edit-h{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:700;color:var(--ink);margin-bottom:10px}
.br-edit-h .li{width:14px;height:14px;color:var(--eye)}
.br-edit-f{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:8px 12px;align-items:end}
.br-ef{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--mut);min-width:0}
.br-ef>span:first-child{font-weight:700}
.br-ef input,.br-ef select{width:100%;max-width:none;padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-size:13px;background:#fff;color:var(--ink);font-family:inherit}
.br-ef input:focus-visible,.br-ef select:focus-visible{outline:2px solid var(--eye);outline-offset:1px;border-color:var(--eye)}
.br-ef.wide,.br-eg.wide{grid-column:1/-1}
.br-ef-chk{align-self:end;padding:7px 0;font-size:12.5px}
.br-eg{grid-column:1/-1;display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:8px 12px;align-items:end;padding:8px 10px 10px;border:1px dashed var(--line);border-radius:10px;background:#fff}
.br-eg-l{grid-column:1/-1;font-size:11px;font-weight:700;color:var(--mut)}
.br-eg .br-needs{display:flex;flex-wrap:wrap;gap:6px 12px;padding:4px 0}
.br-edit-a{display:flex;gap:8px;justify-content:flex-end;margin-top:10px}
.br-edit-save{background:var(--eye);color:#fff;border-color:var(--eye)}
.br-edit-save:hover:not([disabled]){background:color-mix(in srgb,var(--eye) 85%,#000);color:#fff;border-color:transparent}

/* ═══ سجل المباني — أقصر (2026-09-09). The header measured 1009px and the FRA profile card 3524px on
   PARKSIDE Tower B: the two KPI groups stacked as full-width rows of 196px tiles, and the profile's
   14 sections ran in a single column because CSS multi-column never engaged inside the tab. The
   header's tiles are a compact variant and the two groups share one row; the profile is a real
   grid of sections with tight rows. Nothing is hidden — the same 83 fields, a third of the height. */
.br-kgrps{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,4fr);gap:12px;align-items:start;margin-top:10px}
@media(max-width:1100px){.br-kgrps{grid-template-columns:1fr}}
.br-kgrp{margin-top:0}
.br-kgrp .kpi-row{grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:8px}
.br-kgrp .kpi{padding:9px 11px;border-radius:10px;gap:8px}
.br-kgrp .kpi .v{font-size:19px;letter-spacing:-.3px}
.br-kgrp .kpi .k{font-size:11px;line-height:1.25}
.br-kgrp .kpi-tx{padding:0}
#buildreg .wp-grid{columns:auto;column-gap:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:10px;align-items:start}
#buildreg .wp-grid .wp-sec{margin:0;border:1px solid var(--line);border-radius:10px;padding:8px 10px;background:#fff}
#buildreg .wp-sec-h{display:flex;align-items:center;gap:6px;margin:0 0 4px}
#buildreg .wp-tbl td{padding:3px 6px;font-size:12px;line-height:1.35}
#buildreg .wp-tbl .wp-f{width:46%}

/* ═══ سلامة أجهزة الحريق (2026-09-09) — see loadFiresafety() ═══ */
#firesafety .fs-grp{font-size:12px;font-weight:700;color:var(--ink2);margin:6px 0 8px}
#firesafety .fs-grp+.kpi-row{margin-bottom:12px}
#firesafety .kpi.fs-live .v{color:var(--sev-critical)}
#firesafety .card-h .ag-chip{margin-inline-start:6px}
#firesafety .card-h>small.meta{font-family:inherit;font-size:12px;text-transform:none;letter-spacing:0;font-weight:400}
#firesafety .fs-scroll{overflow:auto;max-height:64vh}
#firesafety .utable td{vertical-align:top}
#firesafety .ag-chip .li{width:13px;height:13px}
#firesafety .fs-demo{font-size:10px;padding:1px 7px;vertical-align:middle}
#firesafety .fs-nofire{color:var(--sev-low);font-weight:700;display:inline-flex;gap:5px;align-items:center;white-space:nowrap}
#firesafety .fs-nofire .li{width:14px;height:14px}
#firesafety .fs-coord{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:11.5px;color:var(--mut);direction:ltr;text-align:start;white-space:nowrap}
#firesafety .fs-when{font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12.5px}
#firesafety .fs-empty{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px;text-align:center;color:var(--ink);border:1px dashed var(--line);border-radius:12px;background:#fff}
#firesafety .fs-empty .li{width:22px;height:22px;color:var(--sev-low)}
#firesafety .fs-empty small{max-width:56ch}

/* ═══ ملف الحادث — أقصر في الرأس، مقروء في المفكّر، مرتَّب في المجيب (2026-09-09) ═══════════════
   See TOK/tokL in app.js for the wording, and the incident section comments for the layout. */
/* the offline dark tiles read light; the class rides on the tile layer so a satellite layer is untouched */
.leaflet-layer.light-tiles{filter:invert(1) hue-rotate(180deg) saturate(.55) brightness(1.03) contrast(.95)}
/* ── the header: five stacked bands become two compact rows and a strip ── */
#incident .inc-head{margin-bottom:6px}
#incident #incDisposition{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:12px;margin:0 0 6px}
#incident #incConfirmState{display:flex;flex-wrap:wrap;gap:8px;align-items:stretch;margin:0 0 8px}
#incident #incConfirmState>.vpipe{flex:1 1 380px;margin:0;padding:6px 10px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
#incident #incConfirmState>.vpipe .vsteps{margin:0}
#incident #incConfirmState>.card{flex:1 1 320px;margin:0;padding:8px 12px}
#incident #incConfirmState>.card .card-h{margin:0 0 4px;padding:0;border:0;font-size:13px}
#incident #incConfirmState>.card .meta{font-size:12px}
/* the tab bar follows the reader down a long tab, as the registry's does */
#incident .inc-tabs{position:sticky;top:var(--hdr-h);z-index:25;background:var(--bg);padding:6px 0;margin:0 0 10px}
/* the Auto-Triage packet: four facts and the proposed action on one strip, not a card of tiles */
#triagePacket{padding:10px 14px 8px}
#triagePacket .card-h{margin:0 0 6px;padding:0 0 6px;font-size:13px;justify-content:flex-start;gap:6px}
#triagePacket .ag-grid{display:flex;flex-wrap:wrap;gap:6px 8px}
#triagePacket .ag-kv{display:inline-flex;align-items:baseline;gap:6px;padding:4px 10px;font-size:12px;border-radius:999px}
#triagePacket .ag-kv b{display:inline;font-size:13px}
#triagePacket .ag-h{margin:6px 0 4px;font-size:12px}
#triagePacket .ag-rec{padding:6px 10px;font-size:12.5px}
#triagePacket>.meta{font-size:11.5px;margin-top:4px}
/* ── the Thinker: a two-column grid of readable packets ── */
#incident .flowsec.thinker.active{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:start}
#incident .flowsec.thinker>.flowtag,#incident .flowsec.thinker>.ov-tier,#incident .flowsec.thinker>.grid.four,
#incident .flowsec.thinker>#aiDecisionCard,#incident .flowsec.thinker>#fraCard{grid-column:1/-1}
#incident .flowsec.thinker>.card{margin:0}
@media(max-width:1100px){#incident .flowsec.thinker.active{grid-template-columns:1fr}}
.eintel-q{display:grid;grid-template-columns:170px minmax(0,1fr);gap:2px 12px;padding:7px 0;border-top:1px solid var(--line);align-items:start}
.eintel-q:first-of-type{border-top:0}
.eintel-qh{font-size:12px;font-weight:700;color:var(--mut);padding-top:2px}
.eintel-qb{font-size:12.5px;line-height:1.6;min-width:0;overflow-wrap:anywhere}
.eintel-qb .meta{font-size:11.5px;line-height:1.5}
.eintel-qb ul{margin:4px 0 0;padding-inline-start:18px}
@media(max-width:700px){.eintel-q{grid-template-columns:1fr}}
.ai-dec .doms{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:6px;margin-top:8px}
.ag-dom{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:6px 10px;border-radius:8px;
  border:1px solid color-mix(in srgb,var(--dc) 35%,var(--line));background:color-mix(in srgb,var(--dc) 6%,#fff);font-size:12px}
.ag-dom .k{color:var(--mut)}.ag-dom b{color:var(--dc);text-align:end}
.tok{font-weight:600}
.tok.raw{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:11.5px;color:var(--mut);font-weight:500}
.ag-decision{font-size:13px}
/* every dossier card header reads icon · title from the start; a badge, note or button still goes
   to the far end through the .card-h>small/.meta/button rules above. Without this, a collapsible
   card with nothing trailing spread chevron · icon · title across the whole width. */
#incident .card-h{justify-content:flex-start}
/* ── the Responder: aligned pairs, a bounded brief, a compact form and trail ── */
#incident .flowsec.responder .grid.fit{align-items:start}
#incident .flowsec.responder .brief{max-height:240px;overflow:auto}
#incRepCard .card-h{flex-wrap:wrap;gap:6px;justify-content:flex-start}
#incRepCard .card-h>span{flex:0 1 auto}
#incRepCard .card-h>button{flex:0 0 auto;white-space:nowrap;margin-inline-start:0}
#incRepCard .card-h>button:first-of-type{margin-inline-start:auto}
/* the SITREP form: label | control pairs, two to a row, the resource chips and the notes full width */
.sitrep-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 16px;align-items:center}
.sitrep-form .sr-row{display:grid;grid-template-columns:88px minmax(0,1fr);gap:8px;align-items:center;margin:0}
.sitrep-form .sr-row>label{font-size:12px;color:var(--mut)}
.sitrep-form .sr-row>select,.sitrep-form .sr-row>input{width:100%;min-width:0}
.sitrep-form .sr-row:has(.sr-need),.sitrep-form>input,.sitrep-form>textarea,.sitrep-form>button{grid-column:1/-1}
.sitrep-form>button{justify-self:start}
.sitrep-form .sr-need{gap:6px 12px}
@media(max-width:800px){.sitrep-form{grid-template-columns:1fr}}
.trail-row{display:flex;gap:8px;align-items:flex-start;padding:6px 9px;border:1px solid var(--line);border-radius:8px;font-size:12.5px;background:#fff}
.trail-row .trail-ic{flex:0 0 auto;margin-top:2px}
.trail-row .trail-body{min-width:0}
.trail-row small.meta{font-size:11px}
/* ── the Eye and Notify lists ── */
#censusRoster .cr-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:6px}
#censusRoster .cr-grid .sos-row{margin:0;font-size:12.5px}
/* the location facts: two columns of short rows; the hazard line, the AI confirmation, the section
   headings (inline font-weight:800 rows), notes and the weather row keep the full width */
#inc_context{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 8px;align-items:stretch}
#inc_context>.ctx-row{margin:0;font-size:12.5px;line-height:1.5}
#inc_context>.ctx-row.hazard,#inc_context>.ai-confirm,#inc_context>.meta,#inc_context>.ctx-row:last-child,
#inc_context>.ctx-row[style*="font-weight"]{grid-column:1/-1}
#inc_context>.ctx-row[style*="font-weight"]{border:0;background:none;padding:6px 2px 0;font-size:12px;color:var(--ink2)}
@media(max-width:1100px){#inc_context{grid-template-columns:1fr}}
/* an affected building: name and counts on the left, its floor chips on the right, the action rows under */
#regImpact .reg-hit{padding:8px 10px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:3px 12px;align-items:center}
#regImpact .reg-hit-h,#regImpact .reg-hit-k{grid-column:1}
#regImpact .reg-hit-f{grid-column:2;grid-row:1/3;display:flex;flex-wrap:wrap;gap:4px;justify-content:flex-end;max-width:300px}
#regImpact .reg-hit>.meta,#regImpact .reg-hit-a,#regImpact .nb-order,#regImpact .reg-msg{grid-column:1/-1}
#regImpact .reg-hit-a{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
#regImpact .reg-hit-a .mini-btn,#regImpact .nb-btns .mini-btn{font-size:11.5px}
#regImpact .nb-order{margin-top:6px;padding-top:6px;border-top:1px dashed var(--line)}
#regImpact .nb-h{display:flex;align-items:center;gap:6px;font-size:12px;margin-bottom:4px}
#regImpact .nb-btns{display:flex;flex-wrap:wrap;gap:6px}
#regImpact .reg-msg:empty,#regImpact .nb-out:empty{display:none}
#notifStatus .ag-row{padding:6px 10px;font-size:12.5px}
#notifStatus .ag-row .meta{font-size:11.5px}

/* ═══ a nav chip the account can see but cannot use (2026-09-10) — see markUnusableNav() ═══════════
   Greyed, a lock beside the label, the requirement in the tooltip; inside a dropdown the label
   «ليس لديك صلاحية» is written out because there is room for it there. */
.topbar .chip.gear.perm-off{opacity:.45;cursor:not-allowed;color:var(--ink2)}
.topbar .chip.gear.perm-off:hover{background:transparent;color:var(--ink2);border-color:transparent}
.topbar .chip.gear.perm-off .perm-lock{display:inline-flex;margin-inline-start:4px}
.topbar .chip.gear.perm-off .perm-lock .li{width:12px;height:12px}
.nav-group-menu .chip.gear.perm-off{flex-wrap:wrap}
.nav-group-menu .chip.gear.perm-off .perm-lbl{flex-basis:100%;font-size:10.5px;padding-inline-start:26px;margin-top:-2px;opacity:.9}
#permToast{position:fixed;inset-inline-start:50%;bottom:26px;transform:translate(-50%,12px);z-index:400;display:inline-flex;align-items:center;gap:8px;
  padding:9px 14px;border-radius:999px;background:var(--ink);color:#fff;font-size:12.5px;box-shadow:0 8px 24px rgba(0,0,0,.22);opacity:0;pointer-events:none;
  transition:opacity .18s,transform .18s}
html[dir=rtl] #permToast{transform:translate(50%,12px)}
#permToast.show{opacity:1;transform:translate(-50%,0)}
html[dir=rtl] #permToast.show{transform:translate(50%,0)}
#permToast .li{width:14px;height:14px}
@media(prefers-reduced-motion:reduce){#permToast{transition:none}}

/* ═══ الإدارة › الأشخاص والوصول (2026-09-10) — see PP / renderUsers / renderAudit / renderDevices ═══ */
#admin .pp-kpis{margin-bottom:12px;grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:900px){#admin .pp-kpis{grid-template-columns:repeat(2,1fr)}}
#admin .pp-kpis .kpi .v small{font-size:14px;color:var(--mut);font-weight:600}
#admin .pp-kpis .kpi .k small.meta{font-size:11px;text-transform:none;letter-spacing:0}
#admin .pp-grid{grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);align-items:start}
@media(max-width:1100px){#admin .pp-grid{grid-template-columns:1fr}}
#admin .pp-users .card-h,#admin .pp-audit .card-h,#admin .pp-devices .card-h{gap:8px}
#admin .card-h>small.meta#usersCount,#admin .card-h>small.meta#auditCount{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:11.5px;text-transform:none;letter-spacing:0}
#admin .pp-users #nuToggle{margin-inline-start:auto}
#admin .ucreate.hidden{display:none}
#admin .ucreate{margin:0 0 12px;border:1px dashed var(--line);border-top:1px dashed var(--line);border-radius:10px;padding:10px 12px;background:var(--card2,#FAFAF9)}
/* the toolbar: a search box and chips that double as the filter */
.pp-tools{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:10px}
.pp-tools input[type=search]{flex:1 1 220px;min-width:180px;padding:7px 10px;border:1px solid var(--line);border-radius:9px;font:inherit;font-size:12.5px;background:#fff}
.pp-chips{display:flex;flex-wrap:wrap;gap:6px}
.pp-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1px solid var(--line);border-radius:999px;background:#fff;font:inherit;font-size:12px;font-weight:600;color:var(--ink2);cursor:pointer}
.pp-chip .n{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:10.5px;background:var(--card2,#F1F3F2);border-radius:999px;padding:1px 6px;color:var(--mut)}
.pp-chip:hover{border-color:var(--brand,#127A4B)}
.pp-chip.on{background:var(--ink);border-color:var(--ink);color:#fff}.pp-chip.on .n{background:#ffffff33;color:#fff}
.pp-chip .li{width:12px;height:12px}
/* the roster */
.pp-table td,.pp-table th{white-space:nowrap}
.pp-table td.num,.pp-table th.num{text-align:end;font-variant-numeric:tabular-nums}
.pp-table .pp-who b{display:block;font-size:13px}
.pp-table .pp-who .un{display:block;font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:11px;color:var(--mut)}
.pp-table .pp-perms{display:inline-block;min-width:24px;text-align:center;border:1px solid var(--line);border-radius:999px;padding:1px 6px;font-size:11.5px;cursor:help}
.pp-table .pp-last{font-variant-numeric:tabular-nums;font-size:12px}
.pp-table .pp-dev a{color:var(--ink);text-decoration:none;display:inline-flex;align-items:center;gap:4px}
.pp-table .pp-dev a:hover{color:var(--brand,#127A4B)}
.pp-table .pp-dev .li{width:13px;height:13px}
.pp-table .pp-dev .ok{color:#127A4B}
.pp-table tr.off td{opacity:.55}
.pp-more{display:block;margin:10px auto 2px}
#admin .pp-users .fs-empty{margin-top:4px}
/* the audit log: icon · what happened (and to what) · who · when */
/* outranks `#admin .tabpanel[data-admtab="people"] .auditlog` above, which stretched the log to the
   roster's full height; here the log scrolls inside a bounded box instead */
#admin .tabpanel[data-admtab="people"] .pp-audit .auditlog{max-height:640px;min-height:0;flex:0 0 auto;padding:2px 8px}
#admin .pp-audit .auditlog .a{display:grid;grid-template-columns:18px minmax(0,1fr) auto auto;gap:2px 8px;align-items:start;padding:6px 0;font-size:12px}
#admin .pp-audit .auditlog .a .ic{margin-top:1px;color:var(--mut)}#admin .pp-audit .auditlog .a .ic .li{width:14px;height:14px}
#admin .pp-audit .auditlog .a.ok .ic{color:#127A4B}#admin .pp-audit .auditlog .a.caution .ic{color:#B4560A}#admin .pp-audit .auditlog .a.refuted .ic{color:#9E2F00}
#admin .pp-audit .auditlog .a .body{min-width:0}
#admin .pp-audit .auditlog .a .body b{font-weight:600;color:var(--ink)}
#admin .pp-audit .auditlog .a .body b.raw{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-weight:500;font-size:11.5px}
#admin .pp-audit .auditlog .a .body .n{display:inline-block;margin-inline-start:6px;font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:10.5px;background:var(--card2,#F1F3F2);border-radius:999px;padding:0 6px;color:var(--mut)}
#admin .pp-audit .auditlog .a .body small.meta{display:block;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#admin .pp-audit .auditlog .a .who{font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:11px;color:var(--ink2);padding-top:2px}
#admin .pp-audit .auditlog .a .when{font-variant-numeric:tabular-nums;font-size:11px;color:var(--mut);padding-top:2px;white-space:nowrap}
/* devices by account */
.pp-cov{margin-bottom:10px}
.pd-list{display:flex;flex-direction:column;gap:6px}
.pd-acc{border:1px solid var(--line);border-radius:10px;background:#fff;overflow:hidden}
.pd-acc.open{border-color:var(--brand,#127A4B)}
.pd-head{display:grid;grid-template-columns:18px minmax(0,1fr) auto minmax(0,1.2fr) auto;gap:10px;align-items:center;width:100%;padding:8px 12px;border:0;background:transparent;font:inherit;text-align:start;cursor:pointer;color:var(--ink)}
.pd-head:hover{background:var(--card2,#F7F8F7)}
.pd-head .chev .li{width:14px;height:14px;color:var(--mut);transition:transform .15s}
.pd-acc.open .pd-head .chev .li{transform:rotate(180deg)}
.pd-head .who b{display:block;font-size:13px}.pd-head .who .un{display:block;font-family:var(--msj-mono,ui-monospace,Menlo,Consolas,monospace);font-size:11px;color:var(--mut)}
.pd-head .cnt{display:inline-flex;align-items:center;gap:4px;font-weight:700;font-variant-numeric:tabular-nums}.pd-head .cnt .li{width:13px;height:13px;color:var(--mut)}
.pd-head .sum{font-size:11.5px;display:flex;flex-wrap:wrap;gap:2px 6px}
.pd-head .last{font-size:11px;white-space:nowrap}
.pd-body{border-top:1px solid var(--line);padding:4px 10px 8px;background:var(--card2,#FAFAF9)}
.pd-table td,.pd-table th{font-size:12px;padding:6px 8px}
/* inside an account's group the account column repeats the header; the two action buttons sit
   on one line instead of stacking into a 100px row */
.pd-table td:nth-child(2),.pd-table th:nth-child(2){display:none}
.pd-table td:last-child{white-space:nowrap;text-align:end}
.pd-table .mini.agbtn{display:inline-flex;padding:3px 9px;font-size:11.5px;margin-inline-start:4px;vertical-align:middle}
@media(max-width:900px){.pd-head{grid-template-columns:18px minmax(0,1fr) auto}.pd-head .sum,.pd-head .last{display:none}}
