@import url("../shared/tokens.css");
/* Chainlabs Ad-Hoc Ops Console - demo SPA styles.
   Updated: 2026-09-17 21:46 - selected grid rows and concise Shift-click hints
   for the shared bulk editor.
   Updated: 2026-09-16 09:30 - kanban card name row wraps instead of squeezing the
   name to one syllable per line; the header's green role chip is gone.
   Updated: 2026-09-16 00:30 - ViewGrid Sheets mode: fixed row height, ellipsis
   cells, resize grips, chip cell + popover for multi-selects.
   Updated: 2026-09-15 23:50 - stat strip replaces the .mc tile grid on every
   tab; header controls on one 34px height; Live pill merged into Refresh.
   Updated: 2026-09-04 13:10 - contrast: --muted and --dim both failed WCAG AA
   as body text. Measured on the real backgrounds: light --muted 3.02:1 and
   --dim 1.91:1 against bg-soft (AA needs 4.5). Both are used for every KPI
   sub-line, table caption and chart axis label, which is why the UI read as
   washed out. Re-solved keeping the same hue, darkening/lightening only until
   the worst background passes: light --muted #878F9C -> #676F7D (4.56), light
   --dim #AEB5C0 -> #657082 (4.51), dark --dim #586071 -> #7E879A (4.57). Dark
   --muted already passed at 4.60 and is unchanged.
   Updated: 2026-09-03 20:10 - MOBILE LAYER appended at the end of the file:
   every app surface was measured overflowing its viewport on a 390px phone
   (spend +473px, console +494px, entitydist +419px) because .app-hdr is a
   nowrap flex row whose two children are both flex:0 0 auto. The layer lets
   the header shrink and wrap, converts the 220px sidenav to a top bar,
   un-sticks the toolbar, raises touch targets to 44px and makes drawers and
   modals full-bleed. Additions only - no existing rule was edited.
   Updated: 2026-09-03 01:10 - unsaved-changes panel row actions (.pend-acts /
   .pend-discard) so every row carries a button. Additions only, console-scoped.
   Updated: 2026-09-03 00:20 - unsaved-changes panel: the row card (.pend-row)
   and the overtaken-edit warning (.pend-row-danger / .pend-warn /
   .pend-overwrite). Additions only, console-scoped.
   Updated: 2026-09-02 22:00 - per-tab date-basis note (.tab-datenote), the
   merged PM sort control (.sort-dir, .pm-ctrl-sep) and per-column header menus
   (.colmenu*), plans/CONSOLE_TIME_AND_COLUMN_FILTERS.md. Both extend the
   existing .cfdd dropdown system rather than a parallel one, so they inherit
   its dark-theme colours. Additions only, console-scoped.
   Updated: 2026-09-02 21:00 - Reporting tab collapsible sections (.rep-sect*),
   plans/REPORTING_TAB_ONE_FILTER.md. Additions only, console-scoped.
   Updated: 2026-09-02 19:30 - complete-period navigation on Progress: the
   back / forward stepper (.prog-nav / .prog-step / .prog-cur), the custom
   date inputs (.prog-custom / .prog-date) and the highlighted current row
   (.prog-row-cur), plus their .pf-* twins for the client portal.
   Updated: 2026-09-02 18:10 - like-for-like progress presentation: the
   in-progress pill (.prog-pill), the comparison-basis line (.prog-basis), the
   previous-period context line (.prog-ctx) and the dashed in-progress tail on
   a sparkline (.spark-line-partial / .spark-dot-partial).
   Updated: 2026-09-02 17:00 - portal Reports "Progress" block (.pf-prog-*),
   additions only, theme-independent (plans/REPORT_TAB_PROGRESS.md PR 3).
   Updated: 2026-09-02 16:30 - Reporting "Progress" section (.prog-*) and the
   console presentation mode (body.present, @media print) - additions only,
   console-scoped, zero portal-visible diff (plans/REPORT_TAB_PROGRESS.md).
   Updated: 2026-09-01 10:25 - work-log timer widget redesign (.wl-timer):
   clock as hero at 2.1rem, exactly one primary button at a time, Client and
   Project demoted to a context row. Replaces 11 inline style attributes.
   Updated: 2026-09-01 10:05 - tracked-time row (.wl-tracked) in the
   end-of-day work-log draft.
   Updated: 2026-09-01 09:45 - running-timer dock (.wl-dock). Bottom-left,
   only while a timer runs, z-index 54 so it sits below the .wl-prompt chip.
   Updated: 2026-09-01 09:20 - work-log "start tracking?" chip (.wl-prompt).
   Bottom-left, once per browser session, dismissible, never a modal - it
   appears while the operator is mid-edit.
   Updated: 2026-08-31 18:20 - header band cleanup (Mally: "the sign in mally
   passkey sign out thing should be on the top tab too"). AuthControl moved from
   the toolbar's .tb-actions into #hdr-slot, behind a new .hdr-sep hairline that
   splits the header into data/actions and account groups. The unsaved-writes
   chip moved there too - it is a status alert, not a filter, and it was leading
   the filter row. New .hdr-pending, plus one shared 30px control height across
   the header band so nothing steps.
   Brand tokens mirror docs/adhoc-dashboard/styles.css.
   Updated: 2026-08-31 12:05 - fix: the "N unsaved changes" panel rendered as a
   clipped card floating over the board with no full-page backdrop. Same class
   of bug as the 02:05 entry below, different trigger: .toolbar's
   `backdrop-filter` made it the containing block for the modal's fixed
   overlay, which was nested inside the toolbar. The overlay is now rendered at
   the top-level modal layer (app.js); the .toolbar rule carries a comment so
   it is not reintroduced.
   Updated: 2026-08-28 02:05 - fix: the "?" button appeared to do nothing.
   Root-caused in a real browser, not guessed: secfade's `animation-fill-mode:
   both` on #main.enter left #main with the identity transform matrix forever,
   making it the containing block for every position:fixed descendant. Every
   .modal-overlay in the console is inside #main, so they were positioned and
   sized against #main's full scroll height rather than the viewport - on a
   6000px page the onboarding modal mounted 3350px below the fold. Changed to
   `backwards` on both secfade consumers; identical appearance, no trap. See
   the comment at the rule for the full mechanism.
   Updated: 2026-08-28 01:30 - Round-2 correctness pass PR 7
   (panel-size-and-nav): compact is now a real toggle target (base .drawer
   width, unchanged at 560px) instead of just the pre-design-pass leftover
   size, and gets the same entrance slide .drawer-wide already had. New
   .drawer-hd-tools/.drawer-nav/.drawer-nav-ct for the size toggle +
   prev/next stepper beside the close button.
   Updated: 2026-08-28 01:10 - Round-2 correctness pass PR 6 (pm-sort-filter):
   new .pm-sort-arrow and .pm-filterbar rules for the PM board's sort
   direction arrow and the new Status/Tracer/Client/Priority/Country filter
   bar, matching .pm-sortbar's existing layout rhythm.
   Updated: 2026-08-28 00:50 - Round-2 correctness pass PR 5 (toolbar-realign):
   new .hdr-slot rule for the header's NotifBell + portal-links select, moved
   out of the toolbar (#topnav-slot's cross-root render pattern, applied to
   the header).
   Updated: 2026-08-28 00:35 - Round-2 correctness pass PR 4
   (sidebar-flat-order): deleted the now-dead .navgroup/.navgroup-lbl rules -
   the sidebar is a flat NAV_ORDER list now, no group headers.
   Updated: 2026-08-28 00:20 - Round-2 correctness pass PR 3
   (unsaved-modal-fix): new .modal-wide class replacing PendingChangesModal's
   dead inline max-width, now paired with the correct .modal-overlay class
   (was the unstyled, undefined .modal-bg).
   Updated: 2026-08-27 23:58 - Round-2 correctness pass PR 2
   (save-indicator-states): new .card-sync class (blue, no alarm) for the
   card's mid-retry write state, split out from the existing red ⚠
   error-only indicator.
   Updated: 2026-08-27 23:45 - Round-2 correctness pass PR 1 (sheet-naming-
   truth): .cname's flex children get min-width:0 so a long entity name can
   shrink instead of bleeding past the card in a narrow kanban column;
   .entity-ref gets its first ever CSS rule (was completely unstyled); .card
   .p pills get max-width/ellipsis so a long pill label truncates instead of
   overflowing. .card has zero portal usage (grep confirmed) - scoped
   body:not(.portal) anyway per this pass's convention.
   Updated: 2026-08-27 23:05 - UX design pass PR 7 (startup-and-transitions,
   plan sunny-munching-pascal) - final PR of the console UX/UI design pass.
   Loader entrance stagger (.cl-edges/.cl-nodes/.cl-labels) compressed from a
   1.36s max delay down to 0.4s - same durations/easing/keyframes, only the
   delay values scaled, so a normal ~400ms load no longer cuts the graph off
   mid-draw. New .loading.done / #main.enter (the 600ms-floor+fade handled
   in app.js's revealMain()) and .secpane/secfade (the section-switch
   entrance) share one keyframe. .authgate-card gained a > * + * rhythm rule
   and .authgate-detail (the collapsed diagnostic <details>) now that
   SignInGate uses this markup instead of an all-inline layout. client.html
   reuses id="loading"/id="main" for its own boot sequence but never adds a
   "done"/"enter" class (grep confirms) - scoped body:not(.portal) anyway
   for defense-in-depth, matching this whole pass's convention.
   Updated: 2026-08-27 22:30 - UX design pass PR 6 (controls-consolidation,
   plan sunny-munching-pascal): one control spec appended for
   .btn/.btn-sec/.btn-ghost/.iconbtn (height/radius/gap/transition), one
   hover (filter:brightness(.95)), one disabled (opacity:.55), one focus
   ring for the ~20 interactive classes the audit found with none. Kanban
   card gets a dragging state (.card.dragging, .col.drag-over .col-body)
   copied from EntityDistributionView's .cdb-ecard pattern. Every rule
   body:not(.portal)-scoped - .btn/.btn-sec/.btn-ghost/.iconbtn/.ein are
   heavily used in the client portal (confirmed by grep); the existing
   conflicting hover/focus rules are left in place, never deleted (shared
   file, portal safety) - these are console-scoped winners appended after.
   Updated: 2026-08-27 22:00 - UX design pass PR 5 (case-panel-interior, plan
   sunny-munching-pascal): .cap (the drawer's repeated micro-caption inline
   style, now one class), .ibox + 4 tone variants (amber/red/blue/orange,
   mapped onto the existing --*-soft/-line pairs), .tabpane > * + * for one
   vertical rhythm per tab, .drawer-url. Label/value hierarchy un-inverted:
   .field .fl (the label) was louder - uppercase, letter-spaced - than .fv
   (the value); labels now drop the shout and values gain weight so the eye
   lands on the value first. All new classes or body:not(.portal)-scoped;
   .field has zero portal usage (confirmed earlier in this pass).
   Updated: 2026-08-27 21:15 - UX design pass PR 4 (case-panel-shell, plan
   sunny-munching-pascal, D2): .drawer.drawer-wide widens the entity panel to
   min(1100px,72vw) (was 560px) and gains the same pffade/pfslide entrance
   the client portal's own drawer already had - the console's primary
   surface was the only unanimated modal in the app. New .drawer-hd-sel
   (compact pill selects for the header's moved-up Status/Priority), .ptabs/
   .ptab/.ptab-dot (the 5-tab strip, sticky under the header). `.card .crow`
   widened to `.card .crow, .drawer-hd .crow` - the drawer header never had
   .crow styled, so its pills collapsed onto the title with no gap; portal
   has no .crow at all (grep confirms), so this is zero-risk there. All new
   rules scoped body:not(.portal) except the .crow widening (verified
   portal-safe) and .ptabs/.ptab (new classes, no portal collision possible).
   Updated: 2026-08-27 20:05 - UX design pass PR 3 (screen-fit, plan
   sunny-munching-pascal): .shell uncapped (max-width:none, flex:1 1 auto) to
   fill the sidebar-adjacent #app instead of leaving >=240px dead gutter on
   wide monitors. Kanban board (not swimlanes) rewritten: no more
   scroll-snap fighting drag, align-items:stretch for even column heights,
   height locked to a documented `calc(100vh - var(--hdr-h) - 148px)`
   replacing the wrong 230px constant, .col-hd position:static (its old
   "sticky" had no scrolling ancestor to stick to). D7: 4 TERMINAL columns
   collapse to a 44px .col-rail by default (still a live drop target) via
   new .col-rail/.col-collapse rules. 3 new breakpoints (1440/1280/1024,
   narrowing the column floor + shell gutter) - the console had only 3 above
   640px vs the portal's 7. PM chrome rhythm unified onto the --sp-* scale
   (toolbar/subbar/tabs/sortbar/metrics margins); .drawer-body's 3rem bottom
   pad (a leftover Ask-AI FAB clearance) reduced to --sp-10. All new rules
   scoped body:not(.portal) - zero portal-visible diff (grep confirms no
   portal usage of .board/.col/.drawer-body/.rep-note/.metrics).
   Updated: 2026-08-27 19:10 - UX design pass PR 2 (sidebar-nav, plan
   sunny-munching-pascal, D3+D4): left sidebar layout (.sidenav, 220px, 100vh
   sticky, own scroll) replacing the horizontal nav that used to wrap inside
   .app-hdr; collapse rail via html[data-nav="collapsed"] (56px, icons only);
   header/toolbar seam fix now that .app-hdr never wraps (flex-wrap:nowrap,
   min-height:var(--hdr-h), .toolbar top locked to var(--hdr-h) instead of a
   hardcoded 60px - kills the 4px slit + the ~1100-640px under-slide band).
   #app only becomes a flex row when a .sidenav child is actually present
   (`:has(> .sidenav)`) - entitydist.html shares this stylesheet, also has
   #app at its root, but kept its old layout in this PR and must not be
   affected. Phone breakpoint (<=640px): sidebar collapses to a static full-
   width strip, its link rows and foot controls hidden in favour of the
   existing .topnav-mobile dropdown. All rules scoped body:not(.portal) or
   new .sidenav-prefixed selectors - zero portal-visible diff (client.html's
   body carries class="portal"; no portal usage of #app/.app-hdr/.toolbar
   found on grep).
   Updated: 2026-08-27 18:20 - UX design pass PR 1 (design-tokens-foundation,
   plan sunny-munching-pascal): new rhythm/control tokens (--sp-10/11/12,
   --lh-tight/body/prose, --ctl-h, --r-ctl, --hdr-h); D6 readability remap of
   --fs-1..6 on body:not(.portal) (console text floor 10.4px -> 11px); .sect-h
   restyled larger/sentence-case so headers read bigger than the body text
   they introduce; .grid2 > .field margin-bottom:0 kills the 1.7rem double
   whitespace gap (grid gap + field margin stacking); body line-height, h2,
   and .field .fv leading fixed; 7 more dark-mode orange-filled controls
   corrected to dark ink. Skipped the #64748b hardcode -> var(--muted) swap
   from the plan: all 4 hits are portal-only classes (.pf-fill/.pf-pill/
   .pf-funnel-seg/.pf-leg-sw, client.js only) with no console usage, so
   touching them would be a portal-visible change for zero console benefit -
   left as-is per the portal-safety gate. All additions here are either new
   token names (never edits to existing :root values) or scoped
   body:not(.portal) / new selectors - zero portal-visible diff.
   Updated: 2026-08-27 17:05 - Console PR 5: .qcchk.ok (the field-presence QC
   fallback) is no longer identical to .qcchk-ok (a real on-chain verified
   check) - now a distinct blue instead of green, so the two can't be
   visually confused. See docs/CLAUDE.md plan sunny-munching-pascal PR 5.
   Updated: 2026-08-27 13:10 - Console PR 1a: removed .viewas-banner/.vab-lead/
   .vab-toggle (View-as-tracer mode retired) and the .footer-note FAB-clearance
   padding hack (Ask AI FAB removed). See docs/CLAUDE.md plan
   sunny-munching-pascal PR 1a.
   Updated: 2026-08-26 01:37 - PR3 console audit dead-control removal: dropped
   .op-card/.op-grid/.op-l/.op-desc/.op-run (the Admin "Operate the system"
   panel that dispatched six now-deleted GitHub Actions workflows was removed
   from app.js). Kept .op-msg - still used by the Retool-import and
   scoped-access admin tools.
   Updated: 2026-07-21 12:15 - fix(portal-ux): (1) client logo tile is ALWAYS white
   in both themes - client branding never changes with theme (a var(--card) tile
   went dark in dark mode and swallowed dark logo artwork). (2) .pf-form-wide now
   margin:0 auto - the New-entity-request / Batch-import card was pinned hard left
   inside the 1180px shell, leaving a dead right half. (3) .pf-loadgrid-1 lets a
   lone load panel span the full row instead of a half-empty 2-col grid.
   Updated: 2026-07-16 12:40 - polish pass (make-interfaces-feel-better): disabled
   states on the main buttons, explicit transition properties (no `transition:all`),
   larger tap targets on .x / .miniassign, -moz-osx font smoothing, tabular-nums on
   stat values, .card radius pinned to the --r token, and heading text-wrap:balance.
   Shared with the client portal - every change here is visually neutral on it. */

/* Respect OS "reduce motion" preference: near-disable animation/transition for
   users with vestibular sensitivity. !important so it wins regardless of order. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Design tokens now live in docs/shared/tokens.css, imported at the top of this
   file, so the MTT console reads the same scale rather than its own 13-colour
   palette. The :root and :root[data-theme="dark"] blocks that stood here were
   moved there verbatim - same names, same values, no visual change to this
   console. Change a token there and both surfaces move together.
   The per-client brand boot (client.js setProperty on --orange*) still wins:
   it writes inline styles on the root element, which beat any stylesheet. */
/* Console design pass (PR 1) - D6 "more readable" density: 74% of console
   text sat at 10.4-11.5px. CSS custom properties cascade, so re-declaring the
   low steps here on body:not(.portal) moves every one of the 127+ usage sites
   at once, no markup edits. Portal keeps the exact :root values above.
   ≈11 / 11.9 / 12.25 / 12.6 / 13.3 / 14px (steps 7-12 unchanged). */
body:not(.portal) {
  --fs-1:.79rem; --fs-2:.85rem; --fs-3:.875rem; --fs-4:.9rem; --fs-5:.95rem; --fs-6:1rem;
  line-height:var(--lh-body);
}
body:not(.portal) h2 { font-size:var(--fs-9); }
body:not(.portal) .field .fv { line-height:var(--lh-prose); }
* { box-sizing:border-box; }
html,body { margin:0; padding:0; background:var(--bg-soft); color:var(--text);
  font-family:var(--sans); font-size:14px; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; }
.hidden { display:none !important; }
.shell { max-width:1680px; margin:0 auto; padding:0 1rem 2rem; }
/* UX design pass PR 3 (screen-fit): on a wide monitor the 1680px cap left
   >=240px of dead gutter on both sides while the kanban board (9 x 290px
   cols) needed ~2,688px and scrolled horizontally regardless. Un-cap the
   shell and let it flex to fill #app (pairs with PR 2's flex layout) so the
   board actually gets the width it needs. */
body:not(.portal) .shell { max-width:none; padding:0 var(--sp-10) var(--sp-11); min-width:0; flex:1 1 auto; }
a { color:var(--orange); text-decoration:none; }
code { font-family:var(--mono); font-size:.82em; background:var(--bg-section);
  padding:1px 5px; border-radius:5px; border:1px solid var(--border); }
/* Headings balance their wrapping so a long title never drops one lonely word. */
h1, h2, h3, .sect-h, .col-hd .ct, .swim-name { text-wrap:balance; }

/* Header - part of the single frozen top pane (header + nav + toolbar) */
.app-hdr { display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-8); flex-wrap:wrap; padding:.75rem 0 .7rem; position:sticky; top:0;
  background:var(--bg-soft); z-index:40; border-bottom:1px solid var(--border); }
.app-hdr-title { flex:0 0 auto; }
.app-hdr-right { flex:0 0 auto; }
.viewas { background:var(--card); border:1px solid var(--border); color:var(--text);
  border-radius:8px; padding:.4rem .55rem; font-size:var(--fs-3); font-family:var(--sans); cursor:pointer; }
.viewas:hover { border-color:var(--orange-line); color:var(--orange); }
.mode-pill { cursor:pointer; font-family:var(--sans); }
.mode-pill:hover { filter:brightness(1.05); }
.app-hdr-title { display:flex; align-items:center; gap:var(--sp-6); }
.logo { display:grid; place-items:center; width:34px; height:34px; border-radius:8px;
  background:var(--orange); color:#fff; font-weight:700; font-size:var(--fs-9); }
.app-hdr h1 { font-size:var(--fs-9); margin:0; color:var(--text-strong); font-weight:700; }
.app-hdr h1 .accent { color:var(--orange); }
.meta { font-size:var(--fs-2); color:var(--muted); margin-top:1px; }
.app-hdr-right { display:flex; align-items:center; gap:var(--sp-4); }
/* Round-2 correctness pass, PR 5 (toolbar-realign): NotifBell + the portal
   links select render into here now (moved out of the toolbar), mirroring
   #topnav-slot's cross-root render. Its children (.notif-bell, .tb-iconsel)
   carry their own sizing - this just keeps them inline with Live/Refresh. */
/* The title block is what shrinks when the header runs out of room - the
   account controls on the right must never be the thing that gets clipped. */
body:not(.portal) .app-hdr-title { min-width:0; }
body:not(.portal) .app-hdr-title h1, body:not(.portal) .app-hdr-title .meta {
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
body:not(.portal) .app-hdr-right { flex:0 0 auto; }
body:not(.portal) #live-indicator { max-width:22ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* One-line description under a KPI figure (Mally: "can we hve a small
   description to understand the figures being presented"). Muted and small so
   the number still leads the tile. */
body:not(.portal) .mc .mnote { margin-top:.25rem; font-size:var(--fs-1); line-height:1.35;
  color:var(--muted); font-weight:400; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
body:not(.portal) .hdr-slot { display:flex; align-items:center; gap:var(--sp-3); flex-wrap:nowrap; }
/* Account cluster sits behind a hairline so the header reads as two groups -
   data/actions on the left of it, "who am I" on the right - rather than one
   undifferentiated row of six controls. */
body:not(.portal) .hdr-sep { width:1px; height:20px; background:var(--border); flex:0 0 auto; margin:0 var(--sp-2); }
/* The unsaved-writes chip moved out of the FILTER row into the header: it is a
   status alert, not a filter, and leading the filter bar with a red pill made
   the filters look broken. Sits next to the bell, where alerts already live. */
body:not(.portal) .hdr-pending {
  display:inline-flex; align-items:center; gap:.3rem; height:34px; padding:0 .55rem;
  border-radius:8px; border:1px solid var(--red-line); background:var(--red-soft);
  color:var(--red); font:inherit; font-size:var(--fs-2); font-weight:600; cursor:pointer;
  white-space:nowrap; }
body:not(.portal) .hdr-pending:hover { filter:brightness(.97); }
/* One height for every control in the header band, so the pills, buttons,
   select and auth chip line up on a single baseline instead of stepping. */
body:not(.portal) .app-hdr-right .btn-ghost,
body:not(.portal) .app-hdr-right .viewas,
body:not(.portal) .hdr-slot .authchip { height:34px; }
body:not(.portal) .hdr-slot .authchip { display:inline-flex; align-items:center; gap:.35rem; }
/* Below the widest desktop the account cluster is what gives: the email text
   and the separator go, leaving the key + sign-out icons, which stay reachable. */
@media (max-width: 1200px) {
  body:not(.portal) .hdr-slot .authemail, body:not(.portal) .hdr-sep { display:none; }
}
.btn-ghost { background:var(--card); border:1px solid var(--border); color:var(--text);
  border-radius:8px; padding:.35rem .6rem; cursor:pointer; font-size:var(--fs-6); }
.btn-ghost:hover { border-color:var(--orange-line); color:var(--orange); }

/* Chips / pills */
.p { display:inline-block; font-size:var(--fs-1); font-weight:600; padding:2px 8px;
  border-radius:999px; border:1px solid var(--border); white-space:nowrap; line-height:1.5; }
.p-orange { background:var(--orange-soft); border-color:var(--orange-line); color:var(--orange); }
.p-green { background:var(--green-soft); border-color:var(--green-line); color:var(--green); }
.p-red { background:var(--red-soft); border-color:var(--red-line); color:var(--red); }
.p-blue { background:var(--blue-soft); border-color:var(--blue-line); color:var(--blue); }
.p-amber { background:var(--amber-soft); border-color:var(--amber-line); color:var(--amber); }
.p-grey { background:var(--bg-section); color:var(--muted); }
.text-red { color:var(--red); }
.muted { color:var(--muted); }

.loading { padding:3rem 1rem; text-align:center; }
body:not(.portal) .loading { transition:opacity var(--t-slow) var(--ease); }
/* UX design pass PR 7 (startup-and-transitions): loader->app and section
   switching were both a single-frame unmount/remount with no transition.
   One shared entrance keyframe now covers the loader's exit (#main.enter,
   600ms floor + 250ms fade handled in app.js's revealMain()) and every
   section switch (.secpane, keyed by section so it replays each time). The
   global prefers-reduced-motion block at the top of this file already
   collapses both to near-instant - no separate guard needed here. */
/* client.html reuses id="loading"/id="main" for its own boot sequence, but
   client.js never adds a "done"/"enter" class (grep confirms), so these are
   dormant there - scoped anyway for defense-in-depth, matching this whole
   pass's portal-safety convention. */
body:not(.portal) .loading.done { opacity:0; pointer-events:none; }
@keyframes secfade { from { opacity:0; transform:translateY(4px); } to { opacity:1; transform:none; } }
/* fill-mode is `backwards`, NEVER `both`/`forwards`, because secfade animates
   `transform`. A forwards fill keeps the final keyframe applied indefinitely
   after the animation ends, and an ANIMATED `transform:none` computes to the
   identity matrix `matrix(1,0,0,1,0,0)` - which is still a transform, not the
   `none` keyword. Any non-none transform makes the element a containing block
   for every position:fixed descendant. #main.enter is added once on reveal and
   never removed, so with `both` it trapped every .modal-overlay in the console
   permanently: they sized and positioned against #main's full scroll height
   instead of the viewport. Measured in Chromium on a 6000px-tall page: the "?"
   onboarding modal mounted at top:3350px (entirely below the fold - the button
   looked dead), and the Cmd+K palette overlay was 6921px tall instead of 900.
   `backwards` still fills the FROM keyframe before the animation starts (so
   there is no flash), and secfade's `to` state is identical to the element's
   natural style, so the finished appearance is unchanged. */
body:not(.portal) #main.enter { animation:secfade var(--t-slow) var(--ease) backwards; }
.secpane { animation:secfade .18s var(--ease) backwards; }

/* Toolbar */
.toolbar { display:flex; flex-wrap:wrap; gap:var(--sp-4); align-items:center;
  padding:.6rem 0; position:sticky; top:60px; background:var(--bg-soft); z-index:20;
  border-bottom:1px solid var(--border); margin-bottom:.4rem; }
.toolbar input[type="search"], .toolbar select {
  background:var(--card); border:1px solid var(--border); color:var(--text);
  border-radius:8px; padding:.4rem .6rem; font-size:var(--fs-3); font-family:var(--sans); }
.toolbar input[type="search"] { min-width:220px; }
.btn { background:var(--orange); color:#fff; border:none; border-radius:8px;
  padding:.45rem .8rem; font-weight:600; font-size:var(--fs-3); cursor:pointer; }
.btn:hover { filter:brightness(.95); }
.spacer { flex:1; }

/* Metrics strip */
.metrics { display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
  gap:var(--sp-5); margin:.4rem 0 1rem; }
.mc { background:var(--card); border:1px solid var(--border); border-radius:var(--r);
  padding:.7rem .9rem; box-shadow:var(--shadow-sm); }
.mc .ml { font-size:var(--fs-1); color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
.mc .mv { font-size:var(--fs-11); font-weight:700; color:var(--text-strong); font-family:var(--mono); }
.mc.alert .mv { color:var(--red); }

/* Kanban */
.board { display:flex; gap:var(--sp-6); overflow-x:auto; padding-bottom:1rem; align-items:flex-start;
  scroll-snap-type:x proximity; }
.col { flex:0 0 290px; scroll-snap-align:start; background:var(--bg-section); border:1px solid var(--border);
  border-radius:var(--rl); display:flex; flex-direction:column; max-height:calc(100vh - 230px); }
.col.drag-over { border-color:var(--orange); box-shadow:0 0 0 2px var(--orange-line); }
/* UX design pass PR 6 (controls-consolidation): the kanban card never had a
   dragging state (no lift/opacity/placeholder feel) while the secondary
   entity-distribution board's .cdb-ecard already did - copy that pattern.
   Class toggled directly in app.js's onDragStart/onDragEnd (classList, not
   React state - no re-render needed for a purely visual drag cue). */
.card.dragging { opacity:.45; cursor:grabbing; }
.col.drag-over .col-body { background:var(--orange-soft); }
.col-hd { display:flex; align-items:center; justify-content:space-between;
  padding:.6rem .75rem; border-bottom:1px solid var(--border); position:sticky; top:0;
  background:var(--bg-section); border-radius:var(--rl) var(--rl) 0 0; }
.col-hd .ct { font-weight:700; font-size:var(--fs-3); color:var(--text-strong); display:flex; gap:var(--sp-3); align-items:center; }
.col-hd .cn { font-family:var(--mono); font-size:var(--fs-1); color:var(--muted); }
.col-hd .cn.over { color:var(--red); font-weight:700; }
.col-body { overflow-y:auto; padding:.5rem; display:flex; flex-direction:column; gap:var(--sp-4); }
/* UX design pass PR 3 (screen-fit): the plain kanban board (not swimlanes -
   .board-swim keeps its own natural-height rows) needed ~2,688px for 9
   fixed-290px columns against ~1,648px usable, forcing a permanent
   horizontal scrollbar that fought scroll-snap-type on drag, plus ragged
   column heights (align-items:flex-start) and an inert sticky .col-hd (the
   scroll container was .col-body, not .board, so "sticky" never had
   anything to stick to). D7's rail-collapse (4 TERMINAL columns -> 44px)
   does the rest of the width work; this fixes the columns that stay full. */
body:not(.portal) .board:not(.board-swim) { scroll-snap-type:none; align-items:stretch;
  height:calc(100vh - var(--hdr-h) - 148px); padding-bottom:var(--sp-4); }
body:not(.portal) .board:not(.board-swim) .col { flex:1 1 260px; min-width:248px;
  scroll-snap-align:unset; max-height:100%; }
body:not(.portal) .board:not(.board-swim) .col-hd { position:static; }
body:not(.portal) .board:not(.board-swim) .col-body { flex:1 1 auto; min-height:0; }
/* D7: the 4 TERMINAL columns collapse to a slim rail by default (click to
   expand) so the 5 active columns get the room the fixed 290px width used
   to eat. Still a valid drop target (Column keeps the same onDragOver/
   onDrop handlers) - .drag-over highlights it exactly like a full column. */
.col-rail { flex:0 0 44px; min-width:44px; max-width:44px; cursor:pointer;
  align-items:center; padding:var(--sp-4) 0; gap:var(--sp-3); }
.col-rail .col-rail-n { font-family:var(--mono); font-size:var(--fs-1); color:var(--muted);
  font-weight:700; }
.col-rail .col-rail-t { display:flex; flex-direction:column; align-items:center; gap:var(--sp-2);
  writing-mode:vertical-rl; text-orientation:mixed; }
.col-rail .col-rail-t .ct { writing-mode:horizontal-tb; }
.col-rail:hover { border-color:var(--orange-line); }
.col-collapse { background:none; border:none; color:var(--muted); cursor:pointer; padding:2px;
  border-radius:6px; display:inline-flex; margin-left:var(--sp-2); }
.col-collapse:hover { color:var(--orange); background:var(--bg-soft); }
.col-collapse .ic { transform:rotate(-90deg); }

/* PM: metrics strip + swimlanes */
.pm-metrics { margin:.2rem 0 1rem; }
.pm-swimby { display:inline-flex; align-items:center; gap:var(--sp-3); margin-left:.6rem; font-size:var(--fs-1); color:var(--muted); }
.pm-sortbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .25rem;
  padding: .55rem 1rem .3rem;
  font-size: .78rem;
  color: var(--muted);
}
.pm-sortbar .chipbtn { font-size: .76rem; }
/* Round-2 correctness pass, PR 6 (pm-sort-filter): the arrow on the active
   sort chip, and the new filter bar row - same layout rhythm as
   .pm-sortbar right above it, just below it in the stack. */
.pm-sort-arrow { margin-left:.25rem; font-weight:700; }
.pm-filterbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .4rem;
  padding: 0 1rem .55rem;
  font-size: .78rem;
  color: var(--muted);
}
.swimlane { margin-bottom:1.1rem; border:1px solid var(--border); border-radius:var(--rl); background:var(--bg-section); overflow:hidden; }
.swim-h { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-5);
  padding:.55rem .85rem; background:var(--card); border-bottom:1px solid var(--border); }
.swim-name { font-weight:700; color:var(--text-strong); font-size:var(--fs-5); }
.board-swim { padding:.7rem; }
.board-swim .col { flex:0 0 230px; max-height:none; }
.board-swim .col-body { max-height:300px; }
.card { background:var(--card); border:1px solid var(--border); border-left:3px solid var(--dim);
  border-radius:var(--r); padding:.55rem .65rem; cursor:pointer; box-shadow:var(--shadow-sm); }
.card:hover { border-color:var(--orange-line); }
.card[draggable="true"]:active { cursor:grabbing; }
.card .cname { font-weight:600; color:var(--text-strong); font-size:var(--fs-4); line-height:1.25;
  display:flex; justify-content:space-between; gap:var(--sp-3); }
/* UX design pass PR 4 (case-panel-shell): the drawer header never had .crow
   styled - only .card .crow existed - so header pills collapsed onto the
   title baseline with no gap. Portal has no .crow at all (grep confirms),
   so widening this selector is zero-risk there. */
.card .crow, .drawer-hd .crow { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin-top:.4rem; align-items:center; }
.card .cmeta { font-size:var(--fs-1); color:var(--muted); margin-top:.35rem; display:flex; gap:var(--sp-4); flex-wrap:wrap; }
/* Round 2 correctness pass, PR 1 (sheet-naming-truth): .cname is a flex row
   with no min-width:0 on its children, so a long entity name refused to
   shrink and bled past the card in a narrow kanban column. .entity-ref had
   NO css rule anywhere (grep confirmed) and inherited .cname's full weight/
   size, reading as part of the name instead of a small reference chip. .card
   has zero portal usage (grep confirmed) - scoped anyway per this pass's
   convention. */
/* 2026-09-16: the name row carried up to THREE rigid (flex:0 0 auto) chips -
   the reference, "Requested Nx (by name)" and the save dot - while the name
   itself could break ANYWHERE, so on a 248px column the name was squeezed to
   two or three characters and wrapped one syllable per line ("Aera / rium /
   chai / n"). Now the row wraps: the name keeps at least 60% of the width and
   breaks only between words; a chip that does not fit drops under it and
   truncates with an ellipsis instead of stealing the name's space. */
body:not(.portal) .card .cname { min-width:0; flex-wrap:wrap; row-gap:var(--sp-1); }
body:not(.portal) .card .cname > span:first-child { flex:1 1 auto; min-width:60%; overflow-wrap:break-word; }
body:not(.portal) .card .entity-ref { flex:0 1 auto; min-width:0; max-width:100%; white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; font-size:var(--fs-1); font-family:var(--mono); color:var(--muted); font-weight:400; }
body:not(.portal) .card .p { max-width:100%; overflow:hidden; text-overflow:ellipsis; }
/* Round 2 correctness pass, PR 2 (save-indicator-states): the card's write
   indicator was a single red ⚠ for ANY pending row, so a write 3s into its
   normal [3s,8s,20s,45s,90s] retry ladder read as "failing" instead of
   "saving". .card-sync is the new mid-retry state - blue, no alarm; the red
   ⚠ is now reserved for retries actually exhausted. */
body:not(.portal) .card-sync { color:var(--blue); font-weight:700; }
.miniassign { position:relative; background:var(--bg-section); border:1px dashed var(--border-strong); color:var(--muted);
  border-radius:999px; padding:2px 8px; font-size:var(--fs-1); cursor:pointer; font-family:var(--sans); }
.miniassign::before { content:""; position:absolute; inset:-8px; } /* bigger tap target, no layout shift */
.miniassign:hover { color:var(--orange); border-color:var(--orange-line); }
.card.sla-breach { border-left-color:var(--red); }
.card.sla-warn { border-left-color:var(--amber); }
.card.sla-ok { border-left-color:var(--green); }
.showmore { text-align:center; font-size:var(--fs-1); color:var(--muted); padding:.4rem; }

/* Client stripe colors */
.cl-chainalysis-dr { color:var(--blue); }
.cl-chainalysis-ah { color:var(--teal); }
.cl-elliptic { color:var(--purple); }
.cl-crystal { color:var(--amber); }
.cl-podproza { color:var(--red); }

/* Drawer (case file) */
.drawer-overlay { position:fixed; inset:0; background:rgba(0,0,0,.4); z-index:50; display:flex; justify-content:flex-end; }
.drawer { width:min(560px,94vw); background:var(--bg); height:100%; overflow-y:auto;
  box-shadow:var(--shadow-md); border-left:1px solid var(--border); }
.drawer-hd { position:sticky; top:0; background:var(--bg); border-bottom:1px solid var(--border);
  padding:1rem 1.1rem; display:flex; justify-content:space-between; align-items:flex-start; gap:var(--sp-8); z-index:2; }
.drawer-hd h2 { margin:0 0 .25rem; font-size:var(--fs-8); color:var(--text-strong); }
.drawer-body { padding:1rem 1.1rem 3rem; }
.field { margin-bottom:.85rem; }
.field .fl { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.04em; color:var(--muted); margin-bottom:.15rem; }
.field .fv { font-size:var(--fs-4); color:var(--text-strong); white-space:pre-wrap; word-break:break-word; }
/* UX design pass PR 4 (case-panel-shell, D2): the entity drawer is the
   console's primary surface - 560px (~506px usable), no entrance animation
   (every OTHER modal in the app has one), Escape didn't close it, and a
   click-drag from inside the panel to the overlay could fire the close and
   lose an edit. Widened + given the same entrance motion as the client
   portal's own drawer (pffade/pfslide, defined above at the `.pf-drawer-wrap`
   rule) and close is now armed on mousedown target===overlay (app.js), so a
   drag that starts inside the panel and releases over the overlay no longer
   closes it. */
body:not(.portal) .drawer-overlay { animation:pffade var(--t-fast) var(--ease); }
/* Round-2 correctness pass, PR 7 (panel-size-and-nav): the entrance slide
   used to be wide-only. Compact (the base .drawer width, 560px) is now a
   real toggle target, not just the pre-design-pass leftover width - give
   it the same motion. */
body:not(.portal) .drawer { animation:pfslide var(--t-slow) var(--ease); }
body:not(.portal) .drawer.drawer-wide { width:min(1100px,72vw); }
@media (max-width:900px) { body:not(.portal) .drawer.drawer-wide { width:94vw; } }
/* Status/priority moved up into the header (D2) - compact inline selects
   inside the .crow pill row instead of full-width .field blocks. */
/* Round-2 correctness pass, PR 7 (panel-size-and-nav): the size toggle +
   prev/next stepper live beside the existing close (x) button. */
.drawer-hd-tools { display:flex; align-items:center; gap:var(--sp-3); flex:0 0 auto; }
.drawer-nav { display:flex; align-items:center; gap:.3rem; }
.drawer-nav-ct { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; }
.drawer-hd-sel { height:26px; padding:0 1.6rem 0 .5rem; font-size:var(--fs-1); font-weight:600;
  border-radius:999px; background:var(--bg-section); border:1px solid var(--border-strong);
  color:var(--text-strong); }
/* Tab strip (D2+D8): sticky under the header + PendingBadge, underline-style
   active indicator matching the sidebar's left-bar language but horizontal. */
.ptabs { display:flex; gap:var(--sp-2); padding:0 1.1rem; border-bottom:1px solid var(--border);
  position:sticky; top:0; background:var(--bg); z-index:2; overflow-x:auto; }
.ptab { position:relative; min-height:var(--ctl-h); padding:0 var(--sp-5); background:none; border:none;
  border-bottom:2px solid transparent; color:var(--muted); font-size:var(--fs-4); font-weight:600;
  font-family:var(--sans); cursor:pointer; white-space:nowrap; display:inline-flex; align-items:center; gap:var(--sp-2); }
.ptab:hover { color:var(--text-strong); }
.ptab.on { color:var(--orange); border-bottom-color:var(--orange); }
.ptab-dot { width:6px; height:6px; border-radius:50%; background:var(--red); display:inline-block; }
/* With the tab strip now the one sticky row under the header, the header
   itself no longer needs its own sticky (it also carried leftover z-index
   layering meant for the old single-scroll body). */
.drawer-wide .drawer-hd { position:static; }
/* UX design pass PR 5 (case-panel-interior): one vertical rhythm per tab
   instead of each block carrying its own ad-hoc margin. */
.tabpane > * + * { margin-top:var(--sp-6); }
/* .cap replaces the drawer's repeated micro-caption inline style (the same
   "font-weight:400; font-size:.72rem;" span, 8x) with one class. */
.cap { font-size:var(--fs-2); color:var(--muted); font-weight:400; line-height:var(--lh-body); }
/* .ibox replaces the drawer's hand-rolled bordered callout boxes - a
   title + content panel, tone mapped onto the existing --*-soft/-line
   token pairs so it never introduces a new color. */
.ibox { margin-top:.4rem; padding:.5rem .7rem; border-radius:6px; border:1px solid var(--border); background:var(--bg-section); }
.ibox-title { font-size:var(--fs-2); color:var(--muted); margin-bottom:.3rem; }
.ibox-amber { border-color:var(--amber-line); background:var(--amber-soft); }
.ibox-red { border-color:var(--red-line); background:var(--red-soft); }
.ibox-blue { border-color:var(--blue-line); background:var(--blue-soft); }
.ibox-orange { border-color:var(--orange-line); background:var(--orange-soft); }
/* Label/value hierarchy was inverted: .fl (the label) was louder - uppercase,
   letter-spaced - than .fv (the value) it introduces. Un-invert: labels drop
   the shout, values gain weight, so the eye lands on the value first. */
body:not(.portal) .field .fl { font-size:var(--fs-2); text-transform:none; letter-spacing:0; font-weight:500; }
body:not(.portal) .field .fv { font-weight:500; }
.drawer-url { margin-top:.25rem; font-size:var(--fs-2); }
.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-7); }
.sect-h { font-size:var(--fs-1); font-weight:700; text-transform:uppercase; letter-spacing:.05em;
  color:var(--orange); margin:1.3rem 0 .6rem; border-bottom:1px solid var(--border); padding-bottom:.3rem; }
/* Console design pass (PR 1): .grid2's own column gap plus .field's bottom
   margin were double-stacking into a 1.7rem row gap vs a .85rem column gap -
   the single most visible "random whitespace" bug in the drawer. .grid2 has
   no portal usage, so this is unscoped. */
.grid2 > .field { margin-bottom:0; }
/* Section headers were the same size as field labels and smaller than the
   body text they introduce - flip that: bigger, sentence case, ink-strong.
   Scoped to the console; the portal keeps its own heading treatment. */
body:not(.portal) .sect-h { font-size:var(--fs-6); text-transform:none; letter-spacing:0;
  color:var(--text-strong); margin:var(--sp-11) 0 var(--sp-5); line-height:var(--lh-tight); }
.qcgrid { display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-3) .8rem; margin-bottom:.4rem; }
.qcitem { display:flex; align-items:center; gap:var(--sp-3); font-size:var(--fs-3); color:var(--text); cursor:pointer; }
.evrow { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); font-size:var(--fs-3); padding:.2rem 0; word-break:break-all; }
.evadd { margin-top:.4rem; }
.trace-row { border:1px solid var(--border); border-radius:8px; padding:.5rem .6rem; margin-bottom:.5rem; background:var(--card2); }
.trace-row .tt { display:flex; justify-content:space-between; font-size:var(--fs-3); font-weight:600; color:var(--text-strong); }
.trace-row .td { font-size:var(--fs-1); color:var(--muted); margin-top:.25rem; display:flex; gap:var(--sp-5); flex-wrap:wrap; }
.activity-summary { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); border:1px solid var(--border); border-radius:10px; overflow:hidden; margin-bottom:.65rem; background:var(--card2); }
.activity-summary > div { display:flex; flex-direction:column; gap:.16rem; min-width:0; padding:.55rem .65rem; border-bottom:1px solid var(--border); }
.activity-summary > div:nth-child(odd) { border-right:1px solid var(--border); }
.activity-summary > div:nth-last-child(-n+2) { border-bottom:0; }
.activity-summary span { color:var(--muted); font-size:var(--fs-1); }
.activity-summary b { color:var(--text-strong); font-size:var(--fs-3); overflow-wrap:anywhere; }
.activity-tenure { margin:0 0 .6rem; color:var(--muted); font-size:var(--fs-2); }
.activity-ledger { position:relative; padding-left:1rem; }
.activity-ledger::before { content:""; position:absolute; left:.28rem; top:.75rem; bottom:.75rem; width:1px; background:var(--border); }
.activity-event { position:relative; margin-bottom:.55rem; padding:.58rem .65rem; border:1px solid var(--border); border-radius:8px; background:var(--card2); }
.activity-event::before { content:""; position:absolute; left:-.94rem; top:.78rem; width:.46rem; height:.46rem; border-radius:50%; border:2px solid var(--bg); background:var(--muted); }
.activity-event.request::before { background:var(--accent); }
.activity-event.assignment { border-left:3px solid var(--accent); }
.activity-event.assignment::before { background:var(--accent); }
.activity-event-head { display:flex; align-items:flex-start; justify-content:space-between; gap:.75rem; color:var(--text-strong); font-size:var(--fs-3); }
.activity-event-head time { flex:none; color:var(--muted); font-size:var(--fs-1); font-weight:400; }
.activity-change { display:flex; align-items:center; flex-wrap:wrap; gap:.35rem; margin-top:.28rem; color:var(--text); font-size:var(--fs-2); overflow-wrap:anywhere; }
.activity-change i { color:var(--muted); font-style:normal; }
.activity-attribution { margin-top:.2rem; color:var(--muted); font-size:var(--fs-1); overflow-wrap:anywhere; }
.activity-empty { padding:.75rem; border:1px dashed var(--border); border-radius:8px; color:var(--muted); font-size:var(--fs-2); }
.reason-modal { width:min(620px,calc(100vw - 2rem)); }
.reason-client-warning { display:flex; gap:.6rem; align-items:flex-start; margin-bottom:.7rem; padding:.65rem .75rem; border-left:3px solid var(--accent); background:var(--bg-section); color:var(--text); font-size:var(--fs-2); line-height:1.45; }
.reason-client-warning b { flex:none; color:var(--text-strong); }
.reason-template { margin-top:.65rem; }
.reason-help { display:block; margin-top:.25rem; color:var(--muted); font-size:var(--fs-1); }
.reason-draft-row { display:flex; align-items:center; gap:.55rem; flex-wrap:wrap; margin-top:.7rem; }
.reason-draft-row span { color:var(--muted); font-size:var(--fs-1); }
.reason-draft-error { margin-top:.4rem; color:var(--red); font-size:var(--fs-2); }
.reason-save-hint { margin-right:auto; color:var(--red); font-size:var(--fs-1); }
@media (max-width:520px) {
  .activity-summary { grid-template-columns:1fr; }
  .activity-summary > div:nth-child(odd) { border-right:0; }
  .activity-summary > div:nth-last-child(2) { border-bottom:1px solid var(--border); }
  .activity-event-head { flex-direction:column; gap:.12rem; }
}
.x { background:none; border:none; font-size:var(--fs-10); color:var(--muted); cursor:pointer; line-height:1; padding:.35rem; margin:-.35rem; border-radius:8px; }

/* Modal (intake) */
.modal-overlay { position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:60; display:grid; place-items:center; }
.modal { background:var(--bg); border-radius:var(--rl); width:min(560px,94vw); max-height:92vh; overflow-y:auto;
  box-shadow:var(--shadow-md); border:1px solid var(--border); }
/* Round 2 correctness pass, PR 3 (unsaved-modal-fix): PendingChangesModal's
   dead inline style="max-width:40rem" never overrode .modal's own width -
   this is that width, as a real class. */
body:not(.portal) .modal.modal-wide { width:min(40rem,94vw); }
.modal-hd { padding:1rem 1.1rem; border-bottom:1px solid var(--border); display:flex; justify-content:space-between; align-items:center; }
.modal-hd h2 { margin:0; font-size:var(--fs-7); color:var(--text-strong); }
.modal-body { padding:1rem 1.1rem; }
.modal-foot { padding:.8rem 1.1rem; border-top:1px solid var(--border); display:flex; justify-content:flex-end; gap:var(--sp-4); }
label.fld { display:block; margin-bottom:.7rem; }
label.fld .lt { font-size:var(--fs-1); color:var(--muted); margin-bottom:.2rem; display:block; }
label.fld input, label.fld select, label.fld textarea {
  width:100%; background:var(--card); border:1px solid var(--border); color:var(--text-strong);
  border-radius:8px; padding:.45rem .6rem; font-size:var(--fs-4); font-family:var(--sans); }
.footer-note { font-size:var(--fs-1); color:var(--muted); border-top:1px solid var(--border); margin-top:1.5rem; padding-top:.8rem; }
.btn-sec { background:var(--card); border:1px solid var(--border); color:var(--text); border-radius:8px; padding:.45rem .8rem; cursor:pointer; font-size:var(--fs-3); }
.ein { width:100%; background:var(--card); border:1px solid var(--border); color:var(--text-strong);
  border-radius:8px; padding:.4rem .55rem; font-size:var(--fs-4); font-family:var(--sans); }
.ein:focus { outline:none; border-color:var(--orange-line); }
.cellin { width:100%; min-width:80px; background:transparent; border:1px solid transparent; color:var(--text-strong);
  border-radius:6px; padding:.2rem .35rem; font-size:var(--fs-3); font-family:var(--sans); }
.cellin:hover { border-color:var(--border); background:var(--card); }
.cellin:focus { outline:none; border-color:var(--orange-line); background:var(--card); }

/* Reporting (embedded dashboard) */
.reporting { display:flex; flex-direction:column; }
.rep-note { font-size:var(--fs-2); color:var(--muted); margin:.2rem 0 .5rem; }
.dash-frame { width:100%; height:calc(100vh - 200px); min-height:600px; border:1px solid var(--border);
  border-radius:var(--rl); background:var(--bg); }

/* Top nav (primary sections) */
/* Nav now lives inline in the header (slot #topnav-slot) to free the page. */
.topnav { flex:1 1 auto; min-width:0; display:flex; align-items:center; }
.topnav-inner { display:flex; align-items:center; gap:var(--sp-1); overflow-x:auto; max-width:100%;
  scrollbar-width:thin; }
.topnav-inner::-webkit-scrollbar { height:5px; }
.navlink { background:none; border:none; color:var(--text); padding:.4rem .7rem; cursor:pointer;
  font-size:var(--fs-4); font-weight:600; font-family:var(--sans); border-radius:7px; border-bottom:2px solid transparent;
  white-space:nowrap; }
.navlink:hover { color:var(--orange); }
.navlink.on { color:var(--orange); border-bottom-color:var(--orange); background:var(--card); }

/* Sub bar (within a section) */
.subbar { display:flex; gap:var(--sp-3); align-items:center; margin:.2rem 0 1rem; }

/* Tabs */
.tabs { display:flex; gap:var(--sp-3); margin:.2rem 0 1rem; border-bottom:1px solid var(--border); }
.tab { background:none; border:none; border-bottom:2px solid transparent; color:var(--muted);
  padding:.5rem .9rem; cursor:pointer; font-size:var(--fs-4); font-weight:600; font-family:var(--sans); }
.tab:hover { color:var(--text-strong); }
.tab.on { color:var(--orange); border-bottom-color:var(--orange); }

/* Table view */
.tablewrap { overflow-x:auto; }
table.dt { width:100%; border-collapse:collapse; font-size:var(--fs-3); }
table.dt th { text-align:left; padding:.5rem .6rem; border-bottom:1px solid var(--border-strong);
  color:var(--muted); font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.03em; cursor:pointer; white-space:nowrap; }
table.dt th:hover { color:var(--orange); }
table.dt td { padding:.45rem .6rem; border-bottom:1px solid var(--divider); color:var(--text); }
/* ---- Sheets mode (2026-09-16): one line per row, one height, widths you
   set (Mally: "single line rows just like google sheets one height
   customisable widths"). Full text on hover. The multi-select editor moved
   OUT of the cell into a popover - mounting it inline is what made these
   rows 90-130px tall. ---- */
body:not(.portal) table.dt.sheet { table-layout:fixed; }
body:not(.portal) table.dt.sheet td { height:32px; padding:0 .6rem; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; vertical-align:middle; }
body:not(.portal) table.dt.sheet.comfortable td { height:44px; }
body:not(.portal) table.dt.sheet th { position:relative; overflow:hidden; white-space:nowrap; padding-right:14px; }
body:not(.portal) .th-grip { position:absolute; top:0; right:0; width:9px; height:100%; cursor:col-resize; }
body:not(.portal) .th-grip:hover { background:var(--orange-soft); box-shadow:inset -2px 0 0 var(--orange); }
body:not(.portal) table.dt.sheet .cellin { height:26px; padding:0 .35rem; }
body:not(.portal) .mcell { position:relative; display:block; max-width:100%; }
body:not(.portal) .mcell-btn { display:inline-flex; align-items:center; gap:.3rem; max-width:100%; height:26px;
  padding:0 .35rem; border:1px solid transparent; border-radius:6px; background:transparent; font:inherit;
  color:var(--text); cursor:pointer; white-space:nowrap; overflow:hidden; }
body:not(.portal) .mcell-btn:hover, body:not(.portal) .mcell-btn:active { border-color:var(--border); background:var(--card); }
body:not(.portal) .mcell-chip { display:inline-block; padding:1px 7px; border-radius:6px; background:var(--orange-soft);
  color:var(--orange); border:1px solid var(--orange-line); font-size:var(--fs-1); font-weight:600;
  max-width:14ch; overflow:hidden; text-overflow:ellipsis; }
body:not(.portal) .mcell-more, body:not(.portal) .mcell-add { font-size:var(--fs-1); color:var(--muted); }
body:not(.portal) .mcell-pop { position:absolute; z-index:60; top:calc(100% + 4px); left:0; min-width:22rem;
  max-width:32rem; background:var(--card); border:1px solid var(--border-strong); border-radius:var(--r);
  box-shadow:var(--shadow-md); padding:var(--sp-5); white-space:normal; }
table.dt td.strong { color:var(--text-strong); font-weight:600; }
table.dt tr { cursor:pointer; }
table.dt tbody tr:hover { background:var(--bg-section); }
body:not(.portal) table.dt.sheet tbody tr.is-selected,
body:not(.portal) table.dt.sheet tbody tr.is-selected:hover { background:var(--orange-soft); }
body:not(.portal) table.dt.sheet tbody tr.is-selected .sel-td { box-shadow:inset 3px 0 0 var(--orange); }

/* Tracers view */
.tracers { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:var(--sp-6); }
.tcard { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:.75rem .85rem; box-shadow:var(--shadow-sm); }
.tcard .th-row { display:flex; justify-content:space-between; align-items:center; margin-bottom:.45rem; }
.tcard .tn { font-weight:700; color:var(--text-strong); font-size:var(--fs-5); }
.capbar { background:var(--bg-section); border-radius:5px; height:8px; overflow:hidden; margin:.1rem 0 .55rem; }
.capfill { display:block; height:100%; background:var(--green); border-radius:5px; }
.capfill.over { background:var(--red); }
.tcard .tstats { display:flex; gap:var(--sp-7); font-size:var(--fs-1); color:var(--muted); margin-bottom:.5rem; flex-wrap:wrap; }
.tcard .tstats b { color:var(--text-strong); font-family:var(--mono); }
.tracer-list-link { margin-left:auto; padding:.18rem .45rem; font-size:var(--fs-1); }
.tracer-region { margin:1rem 0 1.35rem; }
.tracer-region h3 { margin:0 0 .55rem; font-size:var(--fs-4); color:var(--text-strong); }
.tli { font-size:var(--fs-2); padding:.25rem 0; border-top:1px solid var(--divider); cursor:pointer; color:var(--text); }
.tli:hover { color:var(--orange); }

/* Customizable views engine */
.viewbar { display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-3); margin:.2rem 0 .6rem; padding-bottom:.5rem; border-bottom:1px solid var(--border); }
.ops-mode { margin-bottom:.8rem; }
.bulk-edit-bar { position:sticky; top:52px; z-index:7; display:flex; flex-wrap:wrap; align-items:center; gap:.5rem;
  margin:.35rem 0 .7rem; padding:.6rem .7rem; border:1px solid var(--orange-line); border-radius:8px; background:var(--card);
  box-shadow:0 4px 14px rgba(15,23,42,.08); }
.bulk-edit-bar strong { min-width:6.4rem; }
.bulk-edit-bar select, .bulk-edit-bar input { min-height:34px; }
.bulk-check { display:flex; align-items:center; gap:.35rem; font-size:var(--fs-3); }
.bulk-hint { margin-left:auto; color:var(--muted); font-size:var(--fs-1); white-space:nowrap; }
.ops-mode { margin-bottom:.8rem; }
.bulk-edit-bar { position:sticky; top:52px; z-index:7; display:flex; flex-wrap:wrap; align-items:center; gap:.5rem;
  margin:.35rem 0 .7rem; padding:.6rem .7rem; border:1px solid var(--orange-line); border-radius:8px; background:var(--card);
  box-shadow:0 4px 14px rgba(15,23,42,.08); }
.bulk-edit-bar strong { min-width:6.4rem; }
.bulk-edit-bar select, .bulk-edit-bar input { min-height:34px; }
.bulk-check { display:flex; align-items:center; gap:.35rem; font-size:var(--fs-3); }
.viewchip { background:var(--bg-section); border:1px solid var(--border); color:var(--text);
  border-radius:7px; padding:.32rem .6rem; cursor:pointer; font-size:var(--fs-3); font-weight:600; font-family:var(--sans); }
.viewchip.on { background:var(--orange-soft); border-color:var(--orange-line); color:var(--orange); }
.viewadd { font-size:var(--fs-3); color:var(--muted); }
.viewadd select { background:var(--card); border:1px solid var(--border); color:var(--text); border-radius:7px; padding:.28rem .4rem; font-size:var(--fs-2); }
.vcfg { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:.7rem .85rem; margin-bottom:.7rem; display:flex; flex-direction:column; gap:var(--sp-4); }
.vcfg-row { display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-3); }
.vcfg-row .vl { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.04em; color:var(--muted); width:110px; flex:0 0 110px; }
.vcfg-col { align-items:flex-start; flex-direction:column; }
.vcfg select, .vcfg input { background:var(--card2); border:1px solid var(--border); color:var(--text-strong); border-radius:6px; padding:.28rem .45rem; font-size:var(--fs-2); font-family:var(--sans); }
.chipbtn { background:var(--bg-section); border:1px solid var(--border); color:var(--text); border-radius:999px; padding:.25rem .6rem; cursor:pointer; font-size:var(--fs-1); }
.chipbtn.on { background:var(--teal-soft); border-color:var(--teal-line); color:var(--teal); }
.filt { display:flex; gap:var(--sp-3); align-items:center; margin-bottom:.35rem; flex-wrap:wrap; }
.vcount { font-size:var(--fs-1); margin:.1rem 0 .5rem; }

/* Grouped grid sections */
.grp { margin-bottom:1rem; }
.grp-h { font-size:var(--fs-2); font-weight:700; color:var(--text-strong); background:var(--bg-section);
  padding:.4rem .6rem; border-radius:7px 7px 0 0; border:1px solid var(--border); border-bottom:none; }
.grp .dt { border:1px solid var(--border); }

/* Gallery */
.gallery { display:grid; grid-template-columns:repeat(auto-fill,minmax(240px,1fr)); gap:var(--sp-6); }
.gcard { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:.7rem .8rem; cursor:pointer; box-shadow:var(--shadow-sm); }
.gcard:hover { border-color:var(--orange-line); }
.gcard .gt { font-weight:700; color:var(--text-strong); font-size:var(--fs-5); margin-bottom:.45rem; }
.gcard .gr { display:flex; justify-content:space-between; gap:var(--sp-4); font-size:var(--fs-1); padding:.15rem 0; border-top:1px solid var(--divider); }
.gcard .gr .gl { color:var(--muted); }
.gcard .gr .gv { color:var(--text-strong); text-align:right; word-break:break-word; }

/* AI Assist - chat copilot */
.ai-wrap { max-width:920px; }
.ai-head { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-5); }
.ai-title { display:flex; align-items:center; gap:var(--sp-4); font-size:var(--fs-8); font-weight:700; color:var(--text-strong); }
.ai-status { display:inline-flex; align-items:center; gap:var(--sp-3); font-size:var(--fs-1); font-weight:600;
  padding:.12rem .5rem; border-radius:999px; border:1px solid var(--border); text-transform:uppercase; letter-spacing:.03em; }
.ai-dot { width:7px; height:7px; border-radius:50%; background:var(--dim); }
.ai-status.s-ok { background:var(--green-soft); border-color:var(--green-line); color:var(--green); }
.ai-status.s-ok .ai-dot { background:var(--green); box-shadow:0 0 0 3px var(--green-soft); animation:aipulse 2s infinite; }
.ai-status.s-down { background:var(--red-soft); border-color:var(--red-line); color:var(--red); }
.ai-status.s-down .ai-dot { background:var(--red); }
.ai-status.s-checking, .ai-status.s-waking, .ai-status.s-quota { background:var(--amber-soft); border-color:var(--amber-line); color:var(--amber); }
.ai-status.s-checking .ai-dot, .ai-status.s-waking .ai-dot, .ai-status.s-quota .ai-dot { background:var(--amber); animation:aipulse 1s infinite; }

/* Suggested-assignment cards with multiple ranked candidates */
.ai-card2 { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:.6rem .8rem; margin-bottom:.5rem; box-shadow:var(--shadow-sm); }
.ai-card2 .ai-card-main { cursor:pointer; margin-bottom:.45rem; }
.ai-card-opts { display:flex; flex-direction:column; gap:var(--sp-3); }
.ai-opt { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-5); padding:.35rem .5rem; background:var(--bg-section); border:1px solid var(--border); border-radius:8px; }
.ai-opt-main { display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap; min-width:0; }
.ai-opt-rank { font-size:var(--fs-1); font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); background:var(--card); border:1px solid var(--border); border-radius:5px; padding:.05rem .35rem; }
.ai-opt-rank.best { color:var(--green); background:var(--green-soft); border-color:var(--green-line); }
.ai-opt-name { font-weight:600; color:var(--text-strong); font-size:var(--fs-4); }
.ai-opt-reason { font-size:var(--fs-1); color:var(--muted); }
.ai-status.s-off { color:var(--muted); }
@keyframes aipulse { 0%,100%{opacity:1;} 50%{opacity:.35;} }
.ai-subtle { font-size:var(--fs-2); color:var(--muted); margin:.25rem 0 .5rem; }
.ai-conn { background:var(--card); border:1px solid var(--border); border-radius:var(--r);
  padding:.7rem .85rem; margin:.3rem 0 .7rem; display:flex; flex-direction:column; gap:var(--sp-3); box-shadow:var(--shadow-sm); }

.ai-chat { background:var(--card); border:1px solid var(--border); border-radius:var(--rl);
  padding:1rem; min-height:220px; max-height:46vh; overflow-y:auto; display:flex; flex-direction:column; gap:var(--sp-6); box-shadow:var(--shadow-sm); }
.ai-empty { margin:auto; text-align:center; padding:1.4rem 1rem; max-width:560px; }
.ai-empty-icon { font-size:var(--fs-12); color:var(--orange); opacity:.85; }
.ai-empty-h { font-size:var(--fs-6); font-weight:600; color:var(--text-strong); margin:.4rem 0 .9rem; }
.ai-chips { display:flex; flex-wrap:wrap; gap:var(--sp-4); justify-content:center; }
.ai-chip { background:var(--bg-section); border:1px solid var(--border); color:var(--text);
  border-radius:999px; padding:.4rem .8rem; cursor:pointer; font-size:var(--fs-3); font-family:var(--sans); transition:color .15s ease,background-color .15s ease,border-color .15s ease,box-shadow .15s ease,transform .15s ease,filter .15s ease; }
.ai-chip:hover { border-color:var(--orange-line); color:var(--orange); background:var(--orange-soft); transform:translateY(-1px); }
.ai-msg { display:flex; gap:var(--sp-4); align-items:flex-start; max-width:90%; animation:airise .2s ease; }
.ai-msg.user { align-self:flex-end; flex-direction:row-reverse; }
.ai-av { flex:0 0 26px; width:26px; height:26px; border-radius:50%; display:grid; place-items:center;
  background:var(--orange-soft); color:var(--orange); font-size:var(--fs-3); border:1px solid var(--orange-line); }
.ai-bubble { border-radius:12px; padding:.6rem .8rem; font-size:var(--fs-4); line-height:1.5; }
.ai-msg.bot .ai-bubble { background:var(--bg-section); border:1px solid var(--border); color:var(--text-strong); border-top-left-radius:3px; }
.ai-msg.user .ai-bubble { background:var(--orange); color:#fff; border-top-right-radius:3px; }
.ai-text { white-space:pre-wrap; }
.ai-flag { margin-top:.4rem; font-size:var(--fs-1); color:var(--amber); border-top:1px dashed var(--amber-line); padding-top:.3rem; }
.ai-typing { display:inline-flex; gap:4px; padding:.1rem 0; }
.ai-typing i { width:6px; height:6px; border-radius:50%; background:var(--dim); animation:aibounce 1.2s infinite; }
.ai-typing i:nth-child(2){ animation-delay:.2s; } .ai-typing i:nth-child(3){ animation-delay:.4s; }
@keyframes aibounce { 0%,60%,100%{ transform:translateY(0); opacity:.4;} 30%{ transform:translateY(-4px); opacity:1;} }
@keyframes airise { from{ opacity:0; transform:translateY(4px);} to{ opacity:1; transform:none;} }
.ai-composer { display:flex; gap:var(--sp-4); margin:.7rem 0 1.1rem; }
.ai-composer .ein { flex:1; padding:.55rem .7rem; font-size:var(--fs-5); }

.ai-sect-h { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-5);
  font-size:var(--fs-1); font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--muted);
  margin:.3rem 0 .6rem; padding-bottom:.4rem; border-bottom:1px solid var(--border); }
.ai-count { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 .35rem;
  background:var(--orange-soft); color:var(--orange); border-radius:999px; font-family:var(--mono); font-size:var(--fs-1); }
.ai-sect-actions { display:inline-flex; gap:var(--sp-3); }
.ai-cards { display:flex; flex-direction:column; gap:var(--sp-4); }
.ai-card { display:flex; align-items:center; gap:var(--sp-7); background:var(--card); border:1px solid var(--border);
  border-radius:var(--r); padding:.6rem .8rem; box-shadow:var(--shadow-sm); transition:border-color .15s ease, transform .15s ease; }
.ai-card:hover { border-color:var(--orange-line); transform:translateY(-1px); }
.ai-card-main { flex:1; min-width:0; cursor:pointer; }
.ai-card-ent { font-weight:600; color:var(--text-strong); font-size:var(--fs-5); }
.ai-card-main:hover .ai-card-ent { color:var(--orange); }
.ai-card-meta { font-size:var(--fs-1); color:var(--muted); }
.ai-card-sug { flex:1.2; min-width:0; }
.ai-card-tracer { color:var(--teal); font-size:var(--fs-3); font-weight:600; }
.ai-card-reason { font-size:var(--fs-1); color:var(--muted); }

/* Global smoothness */
.navlink, .btn, .btn-sec, .btn-ghost, .chipbtn, .viewchip, .tab, .gcard, .mc { transition:color .15s ease,background-color .15s ease,border-color .15s ease,box-shadow .15s ease,transform .15s ease,filter .15s ease; }
.btn:hover { transform:translateY(-1px); box-shadow:var(--shadow-sm); }
.btn-sec:hover { border-color:var(--orange-line); color:var(--orange); }
.mc:hover { border-color:var(--border-strong); }
.ein:focus, .toolbar input:focus, .toolbar select:focus { outline:none; border-color:var(--orange-line); box-shadow:0 0 0 3px var(--orange-soft); }

/* Case-drawer trace cards (full detail + per-trace QC) */
.trace-card { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:.6rem .7rem; margin-bottom:.55rem; box-shadow:var(--shadow-sm); }
.trace-card-h { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); margin-bottom:.45rem; }
.trace-card-t { font-weight:700; color:var(--text-strong); font-size:var(--fs-4); }
.trace-card-r { display:inline-flex; gap:var(--sp-3); flex-wrap:wrap; }
.trace-kv { display:flex; flex-direction:column; gap:var(--sp-2); font-size:var(--fs-3); }
.trace-kv > div { display:flex; gap:var(--sp-4); }
.trace-kv .tk { flex:0 0 96px; color:var(--muted); font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.03em; padding-top:1px; }
.trace-kv .tv { flex:1; color:var(--text-strong); word-break:break-word; }
.trace-kv code { font-size:var(--fs-1); word-break:break-all; }
.trace-qc { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin-top:.5rem; padding-top:.5rem; border-top:1px solid var(--divider); }
.qcchk { font-size:var(--fs-1); padding:.12rem .4rem; border-radius:5px; background:var(--bg-section); color:var(--muted); border:1px solid var(--border); }
.qcchk-ok { background:var(--green-soft); border-color:var(--green-line); color:var(--green); }
.qcchk-fail { background:var(--red-soft,rgba(220,53,69,.12)); border-color:var(--red-line,var(--red)); color:var(--red); }
.qcchk-unknown { background:var(--bg-section); border-color:var(--border); color:var(--muted); }
/* PR5 (console rework plan, D5.4): the sheet-side field-presence fallback
   ("this field is not blank") used to render in the exact same green as a
   REAL on-chain verified check (.qcchk-ok) - misleadingly implying the same
   confidence. .qcchk.ok is now visually distinct (blue, "present" not
   "verified") so nobody reads a blank-check as an on-chain pass. */
.qcchk.ok { background:var(--blue-soft); border-color:var(--blue-line); color:var(--blue); }
.qc-override-note { font-size:var(--fs-1); color:var(--muted); font-style:italic; }
.p.chip-active { outline:2px solid currentColor; outline-offset:1px; }
.btn-sec.active { background:var(--bg-section-active,var(--bg-section)); font-weight:700; }
.trace-qcres { margin-top:.45rem; font-size:var(--fs-1); color:var(--muted); font-family:var(--mono); word-break:break-word; }
/* QC-of-traces controls (ops console only) */
.qc-run-btn { margin-left:.5rem; vertical-align:middle; background:var(--bg-section); border:1px solid var(--orange-line);
  color:var(--orange); font-size:var(--fs-1); font-weight:700; text-transform:none; letter-spacing:0;
  border-radius:6px; padding:.2rem .5rem; cursor:pointer; }
.qc-run-btn:hover:not(:disabled) { background:var(--orange); color:#fff; }
.qc-run-btn:disabled { opacity:.55; cursor:default; }
.qc-msg { margin-left:.5rem; font-size:var(--fs-1); font-weight:500; text-transform:none; letter-spacing:0; color:var(--muted); }
.qc-stale { color:var(--amber); font-size:var(--fs-1); font-weight:700; }
.trace-qc-actions { margin-top:.45rem; }
.qc-ok-btn { background:var(--green-soft); border:1px solid var(--green-line); color:var(--green); font-size:var(--fs-1); font-weight:700;
  border-radius:6px; padding:.22rem .55rem; cursor:pointer; }
.qc-ok-btn:hover:not(:disabled) { background:var(--green); color:#fff; }
.qc-ok-btn:disabled { opacity:.55; cursor:default; }
.qc-ok-note { font-size:var(--fs-1); font-weight:600; color:var(--green); }

/* Admin board quick links */
.admin-links { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:var(--sp-5); margin-bottom:1rem; }
.admin-link { display:block; background:var(--card); border:1px solid var(--border); border-radius:var(--r);
  padding:.7rem .9rem; font-size:var(--fs-4); font-weight:600; color:var(--text-strong); box-shadow:var(--shadow-sm); transition:color .15s ease,background-color .15s ease,border-color .15s ease,box-shadow .15s ease,transform .15s ease,filter .15s ease; }
.admin-link:hover { border-color:var(--orange-line); color:var(--orange); transform:translateY(-1px); }

/* Insights (CSS bars) */
.insights { display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:var(--sp-7); }
.icard { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:.9rem 1rem; box-shadow:var(--shadow-sm); }
.icard .ih { font-size:var(--fs-2); font-weight:700; color:var(--text-strong); margin-bottom:.7rem; }
.bars { display:flex; flex-direction:column; gap:var(--sp-3); }
.barrow { display:grid; grid-template-columns:96px 1fr 70px; align-items:center; gap:var(--sp-4); font-size:var(--fs-2); }
.barrow .bv { text-align:right; font-family:var(--mono); color:var(--text-strong); white-space:nowrap; }
.barrow .bvp { color:var(--muted); font-weight:400; }
.barrow .bl { color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.barrow .bt { background:var(--bg-section); border-radius:5px; height:14px; overflow:hidden; }
.barrow .bf { display:block; height:100%; background:var(--orange); border-radius:5px; min-width:2px; }
.barrow .bf.bf-red { background:var(--red); }
.barrow .bv { text-align:right; font-family:var(--mono); color:var(--text-strong); }

/* ===== Client portal (client.html) ============================== */
/* One spacing rhythm token for every portal grid so nothing staggers. */
body.portal { background:var(--bg-soft); --pf-gap:var(--sp-7); }
.pf-shell { max-width:1180px; margin:0 auto; padding:0 1.4rem 2rem; min-height:100vh; display:flex; flex-direction:column; }
.pf-error { background:var(--card); border:1px solid var(--border); border-radius:var(--rl); padding:2rem; margin:3rem auto; max-width:560px; text-align:center; box-shadow:var(--shadow-sm); }
.pf-error h2 { color:var(--text-strong); margin:0 0 .5rem; }

/* header - one clean single-line band: brand left, tabs + utilities right */
.pf-hdr { position:sticky; top:0; z-index:20; background:var(--bg-soft); border-bottom:1px solid var(--border); }
.pf-hdr-row { display:flex; align-items:center; gap:var(--sp-9); min-height:64px; padding:.55rem 0; }
.pf-brand { display:flex; align-items:center; gap:var(--sp-6); margin-right:auto; min-width:0; }
.pf-logo, .pf-logo-img { width:40px; height:40px; border-radius:10px; flex:0 0 40px; }
.pf-logo { display:grid; place-items:center; color:#fff; font-weight:700; font-size:var(--fs-10); }
/* Client-branding rule: the client's logo tile is ALWAYS white, in BOTH themes.
   A client logo is fixed brand artwork - it must render identically in dark and
   light mode (a var(--card) tile went dark in dark mode and swallowed dark
   logo artwork, e.g. Elliptic). Never theme-tint or invert a client logo. */
.pf-logo-img { object-fit:contain; background:#fff; border:1px solid var(--border); padding:4px; }
.pf-name { font-size:var(--fs-9); font-weight:700; color:var(--text-strong); line-height:1.15; letter-spacing:-.01em; }
.pf-sub { font-size:var(--fs-1); font-weight:600; color:var(--orange); background:var(--orange-soft);
  border:1px solid var(--orange-line); border-radius:999px; padding:.05rem .5rem; vertical-align:middle; margin-left:.3rem; }
.pf-tag { font-size:var(--fs-1); color:var(--muted); margin-top:1px; white-space:nowrap; }
.pf-tag b { color:var(--text); }
.pf-hdr-right { display:flex; align-items:center; gap:var(--sp-4); flex:0 0 auto; }
.pf-secure { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; }
.pf-iconbtn { padding:.35rem .55rem; }
.pf-nav { display:flex; gap:var(--sp-2); flex:0 0 auto; }
.pf-navlink { background:none; border:1px solid transparent; color:var(--text);
  padding:.42rem .85rem; cursor:pointer; font-size:var(--fs-4); font-weight:600; font-family:var(--sans);
  border-radius:9px; transition:background .15s ease, color .15s ease, border-color .15s ease; white-space:nowrap; }
.pf-navlink:hover { background:var(--bg-section); color:var(--text-strong); }
.pf-navlink.on { color:var(--orange); background:var(--orange-soft); border-color:var(--orange-line); }
.pf-main { flex:1; padding:1.1rem 0; }

/* unified control bar - replaces the 3 stacked sub-bands (sync/stream/filters) */
.pf-controlbar { display:flex; align-items:center; gap:var(--sp-6); flex-wrap:wrap;
  margin:.9rem 0 1.2rem; padding:.5rem .65rem; background:var(--card);
  border:1px solid var(--border); border-radius:12px; box-shadow:var(--shadow-sm); }
.pf-seg { display:inline-flex; gap:var(--sp-1); background:var(--bg-section); border:1px solid var(--border); border-radius:9px; padding:.18rem; flex:0 0 auto; }
.pf-seg-b { background:none; border:none; color:var(--text); border-radius:7px; padding:.34rem .72rem;
  font-size:var(--fs-3); font-weight:600; font-family:var(--sans); cursor:pointer; white-space:nowrap; transition:background .15s, color .15s; }
.pf-seg-b:hover { color:var(--text-strong); }
.pf-seg-b.on { background:var(--card); color:var(--orange); box-shadow:var(--shadow-sm); }
.pf-controls-filters { display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap; flex:1 1 auto; min-width:0; }
.pf-controls-sync { display:flex; align-items:center; gap:var(--sp-4); margin-left:auto; font-size:var(--fs-1); color:var(--muted); white-space:nowrap; }
.pf-refresh { padding:.34rem .7rem; font-size:var(--fs-2); }

/* footer - clean balanced single line */
.pf-footer { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:var(--sp-6);
  font-size:var(--fs-3); color:var(--muted); border-top:1px solid var(--border); padding:1.1rem 0 .3rem; margin-top:2rem; }
.pf-footer b { color:var(--text-strong); }
.pf-foot-brand { display:flex; align-items:center; gap:var(--sp-4); }
.pf-foot-mark { display:grid; place-items:center; width:22px; height:22px; border-radius:6px;
  background:var(--cl-orange); color:#fff; font-weight:700; font-size:var(--fs-3); flex:0 0 22px; }
.pf-foot-right { display:flex; align-items:center; gap:var(--sp-8); }
.pf-foot-right a { color:var(--cl-orange); font-weight:600; text-decoration:none; }
.pf-foot-right a:hover { text-decoration:underline; }
/* Chainlabs wordmark in the footer (own brand - safe to inline; no client
   isolation concern). Full colour in light; crisp white in dark (the navy
   wordmark would vanish on the dark footer otherwise). */
.pf-foot-logo { display:inline-block; height:24px; width:101px; flex:0 0 auto;
  background:url('data:image/png;base64,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ERGZFhMRrORKpD/nodukXVujRERERESkUmOfs5I7kV6BioiIiIjIVBnrYKVvIj10SLQjvYiIiIjINKp8GZg9T2dEigYU9pIdrEeivBLpRURERESmWqnBSlataxX4Cmjy4dKtDhABb/mZA9ci/uA98iXSb7mntMpptYiIiIiIjKNSghVr4fkdj4H1Hku2bp45xjjgnK2LWZcsUOmen5Im0m+4TfZKaLaIiIiIiIyxoYMVe06TOXbpHmD0EwFbnBNxh/2uwY4R4XioHelFRERERGbDUMGKbfMYatnXpJOVJo5qOJeIiIiIiIyBgauB2UueUUegYrzhZ1X8EhERERGZNQPNrNgLVnHsl92YD0+kRHoRERERkVlVOFjJkQRfBiXSi4iIiIjMuOLLwO7wmGoDFYADBSoiIiIiIrOt0MxKNqtyUlVjrvmZT27bh0VERERERGZDsZmVOZrVNOMW97U7vYiIiIjILCsWrDi+qagdt53rq9rOJSIiIiIiY6dYsGI0KmrHbZrW6rJBpIiIiIiITL3cwYrt4KHm4OFu5Yn8IiIiIiIypvLPrPw8gsAh0MyKiIiIiMisGngHexERERERkSrlD1YClREWEREREZH65A5W3CZRhe243S90aj+niIiIiIiMhaKli+sLHoxIm0KKiIiIiMyuYsFKwtuK2vEhR7u2c4mIiIiIyNgpGqy0q2nGLc55U9u5RERERERk7LiiL7CXHGI0K2jLlZMQuacsVnoOEREREREZa8VLF//KVgXtuC6p4RwiIiIiIjLWCgcrbpM28Lr8pmQSXrtN9ip7fxERERERmQgDbQrpnrBeSQK8EfGeVunvKyIiIiIiE2fwHezv8BBKLWXcIWFF5YpFRERERAQGSLC/ybZ5BTwe8m0O+JlHClREREREROTC0MEKgD1njTmeAWGxFxKRsKUcFRERERERuamUYOWCPWeNO3zTt7Sxo03CW96xp9kUERERERG5TanBygVr4fmIBnOEWDbb4og4J+IXOgpQRERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERGTS/X9UOohL2PGJuwAAAABJRU5ErkJggg==') left center / contain no-repeat; }
:root[data-theme="dark"] .pf-foot-logo { filter:brightness(0) invert(1); opacity:.92; }

/* kpis - fixed 6-card deck (no auto-fit raggedness); equal-height flex cards */
.pf-kpis { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:var(--pf-gap); margin-bottom:1.1rem; }
/* When a 7th card is present (e.g. the On-hold card) the fixed 6-col grid would
   orphan it with 5 empty trailing cells. Flow the deck instead so cards fill each
   row. Two-class specificity keeps this winning over the responsive rules below. */
.pf-kpis.pf-kpis-flow { grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); }
.pf-kpis.cols-4 { grid-template-columns:repeat(4,minmax(0,1fr)); }
.pf-kpi { display:flex; flex-direction:column; background:var(--card); border:1px solid var(--border); border-radius:var(--r);
  padding:.8rem .9rem; box-shadow:var(--shadow-sm); border-top:3px solid var(--border); transition:border-color .15s ease, transform .15s ease; }
.pf-kpi:hover { border-color:var(--border-strong); transform:translateY(-1px); }
.pf-kpi.accent { border-top-color:var(--orange); }
.pf-kpi.good { border-top-color:var(--green); }
.pf-kpi-l { font-size:var(--fs-1); color:var(--muted); text-transform:uppercase; letter-spacing:.04em; line-height:1.3; }
.pf-kpi-v { font-size:var(--fs-12); font-weight:700; color:var(--text-strong); font-family:var(--mono); font-variant-numeric:tabular-nums; margin-top:.15rem; line-height:1.1; }

/* panels */
.pf-panel { background:var(--card); border:1px solid var(--border); border-radius:var(--rl);
  padding:1rem 1.1rem; margin-bottom:1rem; box-shadow:var(--shadow-sm); }
.pf-panel-h { display:flex; align-items:center; justify-content:space-between; font-size:var(--fs-5);
  font-weight:700; color:var(--text-strong); margin-bottom:.8rem; }
.pf-link, .pf-footer a, .pf-thanks a, .pf-recent a { background:none; border:none; color:var(--orange);
  cursor:pointer; font-size:var(--fs-2); font-weight:600; font-family:var(--sans); }
.pf-stagebars { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:var(--sp-8); }
.pf-stagebar-top { display:flex; justify-content:space-between; font-size:var(--fs-3); color:var(--text); margin-bottom:.3rem; }
.pf-stagebar-top b { color:var(--text-strong); font-family:var(--mono); }
.pf-track { background:var(--bg-section); border-radius:5px; height:8px; overflow:hidden; }
.pf-fill { display:block; height:100%; border-radius:5px; min-width:2px; background:var(--orange); transition:width .4s ease; }
.pf-fill.st-under_review { background:var(--blue); } .pf-fill.st-assigned { background:var(--purple); }
.pf-fill.st-wip { background:var(--amber); } .pf-fill.st-blocked { background:var(--red); }
.pf-fill.st-traced { background:var(--green); } .pf-fill.st-not_traceable { background:var(--dim); }
.pf-fill.st-closed { background:var(--dim); } .pf-fill.st-on_hold { background:#64748b; }
.pf-stagebar-hint { font-size:var(--fs-1); color:var(--muted); margin-top:.25rem; }
.pf-recent { display:flex; flex-direction:column; }
.pf-recent-row { display:grid; grid-template-columns:1fr auto auto; gap:var(--sp-6); align-items:center;
  padding:.5rem 0; border-top:1px solid var(--divider); font-size:var(--fs-4); }
.pf-recent-name { color:var(--text-strong); font-weight:600; }
.pf-recent-date { font-size:var(--fs-1); }

/* status pill */
.pf-pill { display:inline-block; font-size:var(--fs-1); font-weight:600; padding:.1rem .55rem; border-radius:999px;
  border:1px solid var(--border); white-space:nowrap;
  max-width:100%; overflow:hidden; text-overflow:ellipsis; vertical-align:bottom; }
.pf-pill.st-under_review { background:var(--blue-soft); border-color:var(--blue-line); color:var(--blue); }
.pf-pill.st-assigned { background:var(--purple-soft); border-color:var(--purple-line); color:var(--purple); }
.pf-pill.st-wip { background:var(--amber-soft); border-color:var(--amber-line); color:var(--amber); }
.pf-pill.st-blocked { background:var(--red-soft); border-color:var(--red-line); color:var(--red); }
.pf-pill.st-traced { background:var(--green-soft); border-color:var(--green-line); color:var(--green); }
.pf-pill.st-not_traceable { background:var(--bg-section); border-color:var(--border); color:var(--muted); }
.pf-pill.st-on_hold { background:#64748b1a; border-color:#64748b55; color:#64748b; }
.pf-pill.st-closed { background:var(--bg-section); color:var(--muted); }
.pf-pill.pf-urgent { margin-left:.4rem; background:var(--red-soft); border-color:var(--red-line); color:var(--red); }
.pf-pill.pf-high { margin-left:.4rem; background:var(--amber-soft); border-color:var(--amber-line); color:var(--amber); }
.pf-route { display:inline-block; margin-left:.4rem; font-size:var(--fs-1); font-weight:700; text-transform:uppercase;
  letter-spacing:.03em; padding:.06rem .4rem; border-radius:999px; background:var(--orange-soft);
  border:1px solid var(--orange-line); color:var(--orange); white-space:nowrap; }
.pf-prior { margin:.6rem 0 1rem; padding:.6rem .8rem; font-size:var(--fs-3); border-radius:10px;
  background:var(--amber-soft); border:1px solid var(--amber-line); color:var(--text); }
.pf-prior a { cursor:pointer; font-weight:600; text-decoration:underline; }
/* in-app nav rendered as a button (keyboard-focusable) but styled like a link */
.pf-linkbtn { background:none; border:none; padding:0; font:inherit; font-weight:600; color:var(--orange);
  text-decoration:underline; cursor:pointer; }
.pf-linkbtn:focus-visible { outline:2px solid var(--orange); outline-offset:2px; border-radius:3px; }
.pf-preapproval { margin-top:1rem; padding:.7rem .8rem; border-radius:10px;
  background:var(--amber-soft); border:1px solid var(--amber-line); }
.pf-fa-row { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-5);
  padding:.35rem 0; border-top:1px solid var(--amber-line); font-size:var(--fs-3); }
.pf-fa-row:first-of-type { border-top:none; }
.pf-fa-act { display:flex; gap:var(--sp-3); }
.pf-fa-done { font-weight:700; font-size:var(--fs-1); color:var(--green); }
.pf-fa-done.q { color:var(--red); }

/* requests */
.pf-filters { display:flex; flex-wrap:wrap; gap:var(--sp-4); align-items:center; margin-bottom:1rem; }
.pf-search { width:auto; min-width:220px; flex:0 1 280px; }
.pf-fchip { background:var(--card); border:1px solid var(--border); color:var(--text); border-radius:999px;
  padding:.35rem .75rem; cursor:pointer; font-size:var(--fs-2); font-family:var(--sans); transition:color .15s ease,background-color .15s ease,border-color .15s ease,box-shadow .15s ease,transform .15s ease,filter .15s ease; }
.pf-fchip:hover { border-color:var(--orange-line); }
.pf-fchip.on { background:var(--orange-soft); border-color:var(--orange-line); color:var(--orange); font-weight:600; }
.pf-empty { padding:2rem; text-align:center; }
.pf-table { background:var(--card); border:1px solid var(--border); border-radius:var(--rl); overflow:hidden; box-shadow:var(--shadow-sm); }
/* All columns are FIXED fractions (no auto) so every row - each its own grid -
   resolves identical track widths and the columns line up cleanly. */
.pf-tr { display:grid; grid-template-columns:minmax(0,1.7fr) minmax(0,1.2fr) minmax(0,1.3fr) minmax(0,.5fr) minmax(0,.95fr) minmax(0,1.3fr); gap:var(--sp-6); align-items:center;
  padding:.6rem .9rem; border-bottom:1px solid var(--divider); font-size:var(--fs-4); cursor:pointer; transition:background .12s ease; }
/* Keep cells on one line; ellipsize the text columns so a long value can't push a row out of alignment. */
.pf-tr > * { min-width:0; }
.pf-tr > :nth-child(1), .pf-tr > :nth-child(2), .pf-tr > :nth-child(3) { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-tr > :nth-child(4) { text-align:right; }      /* Traces (numeric) */
.pf-tr > :nth-child(5) { white-space:nowrap; }     /* Submitted date */
.pf-tr > :nth-child(6) { display:flex; flex-wrap:wrap; gap:var(--sp-2); align-items:center; }  /* Status pill + transferred chip stay in-cell */
.pf-tr:last-child { border-bottom:none; }
.pf-tr:not(.pf-th):hover { background:var(--bg-section); }
.pf-th { background:var(--bg-section); color:var(--muted); font-size:var(--fs-1); text-transform:uppercase;
  letter-spacing:.04em; cursor:default; font-weight:700; }
/* Sortable header cells */
.pf-th .pf-sort { background:none; border:none; padding:0; margin:0; font:inherit; color:inherit;
  text-transform:inherit; letter-spacing:inherit; cursor:pointer; display:inline-flex; align-items:center; gap:var(--sp-2); }
.pf-th .pf-sort:hover { color:var(--text-strong); }
.pf-th .pf-sort.on { color:var(--text-strong); }
.pf-th .pf-sort:focus-visible { outline:2px solid var(--orange); outline-offset:2px; border-radius:3px; color:var(--text-strong); }
.pf-sort-arrow { font-size:var(--fs-1); opacity:.7; }
.pf-td-name { color:var(--text-strong); font-weight:600; }
/* "transferred" tag (entity moved DR -> AH; shown as one row, not a duplicate) */
.pf-xfer { display:inline-block; margin-left:.4rem; font-size:var(--fs-1); font-weight:700; text-transform:uppercase;
  letter-spacing:.03em; color:var(--purple); background:var(--purple-soft,rgba(139,92,246,.12));
  border:1px solid var(--purple-line,rgba(139,92,246,.3)); border-radius:999px; padding:.05rem .4rem; white-space:nowrap; }
/* "Published" = entity already live in the client's production dataset (Retool host
   match). Green, client-safe wording (never says "Retool"). */
.pf-published { display:inline-block; margin-left:.4rem; font-size:var(--fs-1); font-weight:700; letter-spacing:.02em;
  color:var(--green); background:var(--green-soft,rgba(31,157,87,.12));
  border:1px solid var(--green-line,rgba(31,157,87,.3)); border-radius:999px; padding:.05rem .4rem; white-space:nowrap; }

/* drawer */
.pf-drawer-wrap { position:fixed; inset:0; background:rgba(0,0,0,.35); z-index:50; display:flex; justify-content:flex-end; animation:pffade .15s ease; }
@keyframes pffade { from{opacity:0;} to{opacity:1;} }
.pf-drawer { width:min(480px,92vw); background:var(--bg); height:100%; overflow-y:auto; padding:1.2rem;
  box-shadow:-8px 0 30px rgba(0,0,0,.18); animation:pfslide .2s ease; }
@keyframes pfslide { from{transform:translateX(24px); opacity:.6;} to{transform:none; opacity:1;} }
.pf-drawer-h { display:flex; justify-content:space-between; align-items:flex-start; gap:var(--sp-7); margin-bottom:1rem; }
.pf-drawer-title { font-size:var(--fs-9); font-weight:700; color:var(--text-strong); margin-bottom:.4rem; }
.pf-fields { display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-5) 1rem; }
.pf-field { display:flex; flex-direction:column; border-bottom:1px solid var(--divider); padding-bottom:.4rem; }
.pf-field-l { font-size:var(--fs-1); color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
.pf-field-v { font-size:var(--fs-4); color:var(--text-strong); word-break:break-word; }
.pf-outcome { background:var(--green-soft); border:1px solid var(--green-line); border-radius:var(--r);
  padding:.7rem .85rem; margin-top:1rem; font-size:var(--fs-4); color:var(--text-strong); }
.pf-subtle { font-size:var(--fs-2); color:var(--muted); margin-bottom:.5rem; }
.pf-ai { background:var(--orange-soft); border:1px solid var(--orange-line); border-radius:var(--r); padding:.7rem .85rem; margin-top:1rem; }
.pf-ai-head { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-5); }
.pf-ai-title { font-size:var(--fs-3); font-weight:700; color:var(--orange); }
.pf-ai-text { margin-top:.55rem; font-size:var(--fs-4); line-height:1.5; color:var(--text-strong); white-space:pre-wrap; }
.pf-noteadd { display:flex; gap:var(--sp-4); align-items:flex-end; }
.pf-noteadd textarea { flex:1; resize:vertical; }
.pf-notes { margin-top:.8rem; display:flex; flex-direction:column; gap:var(--sp-4); }
.pf-note { background:var(--bg-section); border:1px solid var(--border); border-radius:var(--r); padding:.55rem .7rem; font-size:var(--fs-4); color:var(--text-strong); }
.pf-note-meta { font-size:var(--fs-1); color:var(--muted); margin-bottom:.2rem; display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap; }
.pf-note-who { color:var(--text-strong); font-size:var(--fs-1); }
.pf-note-role { font-size:var(--fs-1); font-weight:600; text-transform:uppercase; letter-spacing:.03em; color:#fff; background:var(--cl-orange); border-radius:3px; padding:.05rem .3rem; }
.pf-note-sheet { font-size:var(--fs-1); font-weight:600; text-transform:uppercase; letter-spacing:.03em; color:var(--muted); border:1px solid var(--divider); border-radius:3px; padding:.05rem .3rem; }
.pf-note-time { color:var(--muted); }
.pf-note-team { border-left:2px solid var(--cl-orange); }

/* token multi-select */
.pf-tokens { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin:.2rem 0 .15rem; }
.pf-tok { background:var(--card); border:1px solid var(--border); color:var(--text); border-radius:7px;
  padding:.32rem .6rem; cursor:pointer; font-size:var(--fs-2); font-family:var(--mono); transition:color .12s ease,background-color .12s ease,border-color .12s ease,box-shadow .12s ease,transform .12s ease,filter .12s ease; }
.pf-tok:hover { border-color:var(--orange-line); }
.pf-tok.on { background:var(--orange-soft); border-color:var(--orange-line); color:var(--orange); font-weight:600; }
.pf-tokcount { font-size:var(--fs-1); color:var(--orange); font-weight:600; }
.pf-tok-default { margin-left:.5rem; background:var(--bg-section); border:1px solid var(--border); color:var(--muted);
  border-radius:6px; padding:.1rem .45rem; cursor:pointer; font-size:var(--fs-1); font-family:var(--sans); }
.pf-tok-default:hover { border-color:var(--orange-line); color:var(--orange); }

/* requests view toggle + client board */
.pf-viewtog { display:inline-flex; border:1px solid var(--border); border-radius:8px; overflow:hidden; }
.pf-vt { background:var(--card); border:none; color:var(--muted); padding:.35rem .6rem; cursor:pointer; font-size:var(--fs-5); }
.pf-vt.on { background:var(--orange-soft); color:var(--orange); }
.pf-board { display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-6); }
.pf-lane { background:var(--bg-section); border:1px solid var(--border); border-radius:var(--r); display:flex; flex-direction:column; }
.pf-lane-h { display:flex; align-items:center; justify-content:space-between; padding:.55rem .7rem;
  border-bottom:1px solid var(--border); font-weight:700; font-size:var(--fs-3); color:var(--text-strong); }
.pf-lane-n { font-family:var(--mono); font-size:var(--fs-1); color:var(--muted); }
.pf-lane-body { padding:.5rem; display:flex; flex-direction:column; gap:var(--sp-4); min-height:60px; max-height:62vh; overflow-y:auto; }
.pf-lane-empty { color:var(--dim); text-align:center; padding:.6rem 0; }
.pf-bcard { background:var(--card); border:1px solid var(--border); border-radius:8px; padding:.55rem .65rem; cursor:pointer; box-shadow:var(--shadow-sm); transition:border-color .12s ease; }
.pf-bcard:hover { border-color:var(--orange-line); }
.pf-bcard-name { font-weight:600; color:var(--text-strong); font-size:var(--fs-4); }
.pf-bcard-meta { font-size:var(--fs-1); color:var(--muted); margin:.15rem 0; }
@media (max-width:760px) { .pf-board { grid-template-columns:1fr 1fr; } }

/* new request form */
.pf-form { background:var(--card); border:1px solid var(--border); border-radius:var(--rl);
  padding:1.3rem; max-width:680px; box-shadow:var(--shadow-sm); display:flex; flex-direction:column; gap:var(--sp-6); }
.pf-form-h { font-size:var(--fs-8); font-weight:700; color:var(--text-strong); }
.pf-form-row { display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-6); }
.pf-form-actions { margin-top:.4rem; }
.pf-form textarea { resize:vertical; }
.pf-thanks { background:var(--card); border:1px solid var(--border); border-radius:var(--rl);
  padding:2.5rem; max-width:520px; margin:2rem auto; text-align:center; box-shadow:var(--shadow-sm); }
.pf-thanks-icon { width:54px; height:54px; border-radius:50%; background:var(--green-soft); color:var(--green);
  border:1px solid var(--green-line); display:grid; place-items:center; font-size:var(--fs-11); margin:0 auto 1rem; }
.pf-thanks h2 { color:var(--text-strong); margin:0 0 .5rem; }

@media (max-width:640px) {
  .pf-fields, .pf-form-row { grid-template-columns:1fr; }
  .pf-tr { grid-template-columns:1.4fr auto; }
  .pf-tr > :nth-child(2), .pf-tr > :nth-child(3), .pf-tr > :nth-child(4), .pf-tr > :nth-child(5) { display:none; }
}

/* ===== Professional polish pass ================================== */
/* Subtle, consistent custom scrollbars (kanban, chat, tables, drawers). */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; border: 2px solid var(--bg-soft); }
*::-webkit-scrollbar-thumb:hover { background: var(--dim); }

/* Selection + sharper headings */
::selection { background: var(--orange-soft); color: var(--text-strong); }
.app-hdr h1, .pf-name, .pf-form-h, .ai-title, .icard .ih, .pf-drawer-title, h1, h2 { letter-spacing: -0.01em; }
.mv, .mc .mv, .pf-kpi-v { letter-spacing: -0.02em; font-feature-settings: "tnum" 1; font-variant-numeric: tabular-nums; }

/* Crisper, more consistent buttons + inputs */
.btn { box-shadow: var(--shadow-sm); }
.btn:active, .btn-sec:active, .btn-ghost:active { transform: translateY(0.5px); }
/* Disabled main buttons now LOOK disabled (previously identical to an enabled one). */
.btn:disabled, .btn-sec:disabled, .btn-ghost:disabled { opacity:.5; cursor:not-allowed; box-shadow:none; transform:none; filter:none; }
.btn-sec, .btn-ghost, .chipbtn, .viewchip, .pf-fchip, .ai-chip, .pf-tok { transition:color .14s ease,background-color .14s ease,border-color .14s ease,box-shadow .14s ease,transform .14s ease,filter .14s ease; }
input, select, textarea, .ein, .toolbar input, .toolbar select { transition: border-color .14s ease, box-shadow .14s ease; }

/* Card hover lift consistency */
.icard, .tcard, .gcard, .pf-panel, .pf-table, .ai-chat { transition: border-color .15s ease, box-shadow .15s ease; }
.icard:hover, .tcard:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); }

/* Kanban column header sits cleaner */
.col-hd { backdrop-filter: saturate(1.05); }

/* Tables: zebra-free but clearer row separation + hover */
table.dt tbody tr { transition: background .12s ease; }
table.dt th { position: sticky; top: 0; background: var(--bg-section); z-index: 1; }

/* Nav active underline animates in */
.navlink { position: relative; }
.navlink.on { background: transparent; }

/* Signals view (Workstream B) - scannable cards with severity rails */
.sig-strip { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin:.2rem 0 .9rem; }
.sig-chip { font-size:var(--fs-1); padding:.25rem .55rem; border-radius:999px; background:var(--card);
  border:1px solid var(--border); color:var(--muted); cursor:default; }
.sig-chip b { color:var(--text-strong); margin-right:.2rem; }
.sig-chip.sig-red b { color:var(--red); }
.sig-chip.sig-amber b { color:var(--amber); }
.sig-chip.sig-blue b { color:var(--blue); }
.sig-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); gap:var(--sp-7); }
.sig-card { background:var(--card); border:1px solid var(--border); border-radius:12px;
  padding:.7rem .8rem .6rem; border-left:3px solid var(--border); }
.sig-card.sig-red { border-left-color:var(--red); }
.sig-card.sig-amber { border-left-color:var(--amber); }
.sig-card.sig-blue { border-left-color:var(--blue); }
.sig-card.sig-grey { border-left-color:var(--muted); }
.sig-hd { display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-4); }
.sig-name { font-weight:600; color:var(--text-strong); font-size:var(--fs-5); cursor:help; }
.sig-count { font-family:var(--mono); font-size:var(--fs-3); color:var(--muted); white-space:nowrap; }
.sig-def { font-size:var(--fs-1); color:var(--muted); margin:.25rem 0 .5rem; line-height:1.35; }
.sig-list { display:flex; flex-direction:column; gap:1px; }
.sig-li { display:flex; flex-direction:column; padding:.32rem .4rem; border-radius:7px; cursor:pointer; }
.sig-li:hover { background:var(--bg-section, rgba(127,127,127,.08)); }
.sig-li-n { font-size:var(--fs-3); color:var(--text); font-weight:500; }
.sig-li-m { font-size:var(--fs-1); color:var(--muted); }
.sig-empty { font-size:var(--fs-1); color:var(--muted); padding:.3rem .4rem; font-style:italic; }
.sig-more { align-self:flex-start; background:none; border:none; color:var(--orange); cursor:pointer;
  font-size:var(--fs-1); padding:.3rem .4rem; }

/* Client portal - clickable KPIs/stages + trace drill-down (Workstream H) */
.pf-kpi-click, .pf-stagebar-click { cursor:pointer; transition:border-color .15s ease; }
.pf-kpi-click:hover, .pf-stagebar-click:hover { border-color:var(--orange-line, var(--orange)); }
.pf-traces { margin:.6rem 0; }
.pf-tracelist { display:flex; flex-direction:column; gap:1px; }
.pf-tracerow { display:flex; align-items:baseline; gap:var(--sp-4); padding:.3rem .4rem; border-radius:6px; font-size:var(--fs-3); }
.pf-tracerow:hover { background:var(--bg-section, rgba(127,127,127,.08)); }
.pf-trace-tok { font-weight:600; font-family:var(--mono); min-width:78px; }
.pf-trace-meta { flex:1; }
.pf-trace-links { display:flex; gap:var(--sp-4); align-items:center; }
.pf-trace-tx { font-family:var(--mono); color:var(--muted); }

.pf-tok-search { margin:.35rem 0; width:100%; }

/* Charts - donut (compositions) + spark (trends), richer than flat bars */
.donut-wrap { display:flex; align-items:center; gap:var(--sp-8); flex-wrap:wrap; }
.donut { flex:0 0 auto; }
.donut-c { font-family:var(--mono); font-size:var(--fs-8); font-weight:700; fill:var(--text-strong); }
.donut-l { font-size:var(--fs-1); fill:var(--muted); text-transform:uppercase; letter-spacing:.05em; }
.donut-leg { flex:1; min-width:130px; display:flex; flex-direction:column; gap:var(--sp-2); }
.dleg { display:grid; grid-template-columns:12px 1fr auto; align-items:center; gap:var(--sp-3); font-size:var(--fs-1); }
.dleg .dot { width:9px; height:9px; border-radius:2px; }
.dleg .dll { color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dleg .dlv { color:var(--muted); font-family:var(--mono); white-space:nowrap; }
.spark-wrap { width:100%; }
.spark { width:100%; height:96px; display:block; }
.spark-area { fill:var(--orange-soft); opacity:.6; }
.spark-line { fill:none; stroke:var(--orange); stroke-width:2; stroke-linejoin:round; stroke-linecap:round; vector-effect:non-scaling-stroke; }
.spark-dot { fill:var(--orange); stroke:var(--card); stroke-width:1; }
.spark-x { display:flex; justify-content:space-between; font-size:var(--fs-1); color:var(--muted); margin-top:.2rem; }
.spark-x span { flex:1; text-align:center; }
.spark-x span:first-child { text-align:left; }
.spark-x span:last-child { text-align:right; }

/* Customisable tabs menu (header nav) */
.tabcustomize { position:relative; flex:0 0 auto; }
.tabcog { padding:.4rem .55rem; font-size:var(--fs-7); color:var(--muted); }
.tabcog:hover { color:var(--orange); }
.tabmenu { position:absolute; right:0; top:100%; margin-top:.3rem; z-index:60;
  background:var(--card); border:1px solid var(--border); border-radius:10px;
  box-shadow:var(--shadow-md); padding:.5rem; min-width:190px; }
.tabmenu-h { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.04em;
  color:var(--muted); padding:.2rem .4rem .4rem; }
.tabmenu-i { display:flex; align-items:center; gap:var(--sp-4); padding:.32rem .4rem;
  font-size:var(--fs-3); color:var(--text); cursor:pointer; border-radius:6px; }
.tabmenu-i:hover { background:var(--bg-section); }

/* Admin key / Retool-import / scoped-access messages (Workstream G) */
.op-msg { font-size:var(--fs-1); color:var(--muted); }

/* Auth (Workstream M) - non-breaking login control + optional gate */
.authchip { display:inline-flex; align-items:center; gap:var(--sp-3); }
.authemail { font-size:var(--fs-2); color:var(--text); }
.authgate { min-height:60vh; display:grid; place-items:center; }
.authgate-card { background:var(--card); border:1px solid var(--border); border-radius:var(--rl);
  padding:1.6rem 1.8rem; text-align:center; box-shadow:var(--shadow-md); max-width:360px; }
.authgate-card h2 { margin:0 0 .4rem; color:var(--text-strong); }
.authgate-card .btn { margin-top:.8rem; }
/* UX design pass PR 7 (startup-and-transitions): SignInGate now shares this
   markup with the other sign-in wall (one design language for both), so its
   buttons/paragraphs need the rhythm that used to be inline per-element. */
.authgate-card > * + * { margin-top:.8rem; }
.authgate-detail { margin-top:1rem; font-size:var(--fs-1); color:var(--muted); text-align:left; }
.authgate-detail summary { cursor:pointer; }
.authgate-detail pre { white-space:pre-wrap; word-break:break-all; margin:.4rem 0 0; font-family:var(--mono); }

/* ── Two-factor (MFA / TOTP) step-up gate ──────────────────────────────────
   Shared by the ops console (app.js MfaGate) and the client portal (client.js
   MfaGate): one full-screen, brand-orange, dyslexia-friendly card so 2FA looks
   the same on both surfaces. */
.mfa-overlay { position:fixed; inset:0; z-index:1000; display:flex; align-items:center;
  justify-content:center; padding:24px; box-sizing:border-box;
  background:radial-gradient(125% 125% at 50% -12%, color-mix(in srgb,var(--accent) 8%,var(--bg-soft)), var(--bg-soft) 58%); }
.mfa-card { width:100%; max-width:420px; background:var(--card); border:1px solid var(--border);
  border-radius:18px; padding:34px 30px 28px; text-align:center; box-shadow:var(--shadow-lg);
  font-family:var(--sans); box-sizing:border-box; }
.mfa-badge { width:56px; height:56px; margin:0 auto 18px; border-radius:15px; display:flex;
  align-items:center; justify-content:center; color:var(--accent);
  background:color-mix(in srgb,var(--accent) 13%,transparent); }
.mfa-badge svg { width:28px; height:28px; }
.mfa-title { font-size:20px; font-weight:700; color:var(--text-strong); margin:0 0 7px; letter-spacing:-.01em; }
.mfa-sub { font-size:14px; line-height:1.55; color:var(--muted); margin:0 auto 22px; max-width:332px; }
.mfa-qr-frame { width:188px; height:188px; margin:0 auto 16px; padding:10px; background:#fff;
  border:1px solid var(--border); border-radius:14px; box-shadow:var(--shadow-sm); box-sizing:border-box; }
.mfa-qr-frame img { width:100%; height:100%; display:block; }
.mfa-key { display:inline-flex; align-items:center; gap:8px; margin:0 auto 6px; padding:7px 7px 7px 12px;
  background:var(--bg-section); border:1px solid var(--border); border-radius:10px; max-width:100%;
  font-family:var(--mono); font-size:12.5px; color:var(--text-strong); }
.mfa-key span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; letter-spacing:.04em; }
.mfa-key-copy { flex:none; border:1px solid var(--border); background:var(--card); color:var(--text);
  border-radius:7px; padding:4px 9px; font-size:11.5px; font-weight:600; cursor:pointer; font-family:var(--sans);
  transition:border-color .12s, color .12s; }
.mfa-key-copy:hover { border-color:var(--accent); color:var(--accent); }
.mfa-key-hint { font-size:11.5px; color:var(--dim); margin:0 0 18px; }
.mfa-otp { width:100%; max-width:248px; margin:0 auto; display:block; text-align:center;
  font-family:var(--mono); font-size:26px; font-weight:600; letter-spacing:10px;
  padding:13px 12px 13px 22px; color:var(--text-strong); background:var(--bg-section);
  border:1.5px solid var(--border); border-radius:12px; box-sizing:border-box;
  transition:border-color .12s, box-shadow .12s; }
.mfa-otp:focus { outline:none; border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent); }
.mfa-otp::placeholder { color:var(--dim); }
.mfa-btn { width:100%; max-width:248px; margin:18px auto 0; display:block; padding:12px 16px;
  border:none; border-radius:11px; background:var(--accent); color:#fff; font-size:15px; font-weight:700;
  cursor:pointer; font-family:var(--sans); transition:filter .12s, opacity .12s; }
.mfa-btn:hover:not(:disabled) { filter:brightness(.94); }
.mfa-btn:disabled { opacity:.5; cursor:not-allowed; }
.mfa-err { margin:14px auto 0; max-width:300px; padding:9px 12px; border-radius:10px; font-size:13px;
  line-height:1.45; color:var(--red); background:var(--red-soft); border:1px solid var(--red-line); text-align:left; }
.mfa-link { background:none; border:none; color:var(--muted); font-family:var(--sans); font-size:13px;
  text-decoration:underline; cursor:pointer; margin-top:18px; }
.mfa-link:hover { color:var(--text-strong); }
.mfa-foot { margin-top:20px; padding-top:15px; border-top:1px solid var(--divider);
  font-size:12px; color:var(--dim); line-height:1.5; }
.mfa-spin { width:30px; height:30px; margin:8px auto 4px; border-radius:50%;
  border:3px solid var(--border); border-top-color:var(--accent); animation:mfaspin .8s linear infinite; }
@keyframes mfaspin { to { transform:rotate(360deg); } }

/* Sign-in modal (AuthModal in app.js) - Google SSO primary + email one-time-code */
.modal.auth-modal { width:min(400px,94vw); }
.auth-body { padding:1.1rem 1.25rem 1.4rem; }
.auth-step { display:flex; flex-direction:column; }
.auth-lead { margin:0 0 1rem; font-size:var(--fs-4); line-height:1.55; color:var(--muted); }
.auth-lead b { color:var(--text-strong); font-weight:600; }
.auth-google { display:flex; align-items:center; justify-content:center; gap:10px; width:100%;
  padding:.7rem 1rem; border:1px solid var(--border); border-radius:10px; background:var(--card);
  color:var(--text-strong); font-family:var(--sans); font-size:var(--fs-5); font-weight:600; cursor:pointer;
  transition:border-color .15s, box-shadow .15s, transform .12s; }
.auth-google:hover:not(:disabled) { border-color:var(--orange-line); box-shadow:var(--shadow-sm); transform:translateY(-1px); }
.auth-google:disabled { opacity:.55; cursor:not-allowed; }
.auth-g { flex:none; display:block; }
.auth-or { display:flex; align-items:center; gap:var(--sp-6); margin:1.05rem 0; color:var(--dim);
  font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.08em; }
.auth-or::before, .auth-or::after { content:""; flex:1; height:1px; background:var(--border); }
.auth-fld { display:block; }
.auth-fld span { display:block; margin-bottom:.3rem; font-size:var(--fs-1); font-weight:600; color:var(--muted); }
.auth-input { width:100%; box-sizing:border-box; padding:.62rem .7rem; font-size:var(--fs-5);
  background:var(--bg-section); color:var(--text-strong); border:1.5px solid var(--border); border-radius:10px;
  font-family:var(--sans); transition:border-color .12s, box-shadow .12s; }
.auth-input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent); }
.auth-otp { width:100%; box-sizing:border-box; margin:.2rem 0 0; text-align:center;
  font-family:var(--mono); font-size:26px; font-weight:600; letter-spacing:12px;
  padding:.7rem .5rem .7rem 1rem; color:var(--text-strong); background:var(--bg-section);
  border:1.5px solid var(--border); border-radius:12px; transition:border-color .12s, box-shadow .12s; }
.auth-otp:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent); }
.auth-otp::placeholder { color:var(--dim); letter-spacing:8px; }
.auth-primary { width:100%; margin-top:.85rem; padding:.7rem 1rem; border:none; border-radius:10px;
  background:var(--accent); color:#fff; font-family:var(--sans); font-size:var(--fs-5); font-weight:700; cursor:pointer;
  transition:filter .12s, opacity .12s, transform .12s; }
.auth-primary:hover:not(:disabled) { filter:brightness(.95); transform:translateY(-1px); }
.auth-primary:disabled { opacity:.5; cursor:not-allowed; }
.auth-secondary { margin-top:.7rem; }
.auth-err { margin-top:.8rem; padding:.55rem .7rem; border-radius:9px; font-size:var(--fs-2); line-height:1.45;
  color:var(--red); background:var(--red-soft); border:1px solid var(--red-line); text-align:left; }
.auth-altrow { display:flex; align-items:center; justify-content:center; gap:var(--sp-4); margin-top:1rem; }
.auth-dot { color:var(--dim); }
.auth-link { background:none; border:none; padding:.2rem 0; font-family:var(--sans); font-size:var(--fs-2);
  color:var(--muted); cursor:pointer; text-decoration:underline; }
.auth-link:hover:not(:disabled) { color:var(--orange); }
.auth-link:disabled { opacity:.5; cursor:not-allowed; }

.cov-tags { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin:.2rem 0 .6rem; }

/* Client portal - Chainalysis DR/AH stream toggle */
.pf-stream { display:flex; gap:var(--sp-3); margin:1rem 0 .9rem; flex-wrap:wrap; }
.pf-stream-b { background:var(--card); border:1px solid var(--border); color:var(--text);
  border-radius:8px; padding:.4rem .85rem; font-size:var(--fs-3); font-weight:600; cursor:pointer; }
.pf-stream-b.on { background:var(--pf-accent, var(--orange)); border-color:transparent; color:#fff; }

/* Reporting - hours this week vs weekly cap */
.tcard .capbar { height:8px; }
.caps { display:flex; flex-direction:column; gap:var(--sp-4); }
.caprow { display:grid; grid-template-columns:120px 1fr auto; align-items:center; gap:var(--sp-5); font-size:var(--fs-2); }
.capbar { background:var(--bg-section); border-radius:5px; height:14px; overflow:hidden; }
.capfill { display:block; height:100%; background:var(--green); border-radius:5px; min-width:2px; }
.capfill.over { background:var(--red); }
.capv { font-family:var(--mono); color:var(--text-strong); white-space:nowrap; }

/* Clickable metrics + bar rows (drill-down to contributing entities) */
.mc-click { cursor:pointer; transition:border-color .15s ease, transform .1s ease; }
.mc-click:hover { border-color:var(--orange-line); }
.barrow-click { cursor:pointer; border-radius:6px; }
.barrow-click:hover { background:var(--bg-section); }

/* Polish: visible keyboard focus across interactive elements */
.navlink:focus-visible, .btn:focus-visible, .btn-sec:focus-visible, .btn-ghost:focus-visible,
.mc-click:focus-visible, .barrow-click:focus-visible, .pf-stream-b:focus-visible, .pf-tok:focus-visible,
.ai-chip:focus-visible, .sig-li:focus-visible, .tli:focus-visible {
  outline:2px solid var(--orange); outline-offset:2px; border-radius:6px;
}

/* Toast notifications */
.toast-host { position:fixed; right:1rem; bottom:1rem; z-index:9999; display:flex; flex-direction:column; gap:var(--sp-4); }
.toast { background:var(--card); color:var(--text-strong); border:1px solid var(--border);
  border-left:3px solid var(--orange); border-radius:10px; padding:.6rem .9rem; font-size:var(--fs-3);
  box-shadow:var(--shadow-md); opacity:0; transform:translateY(8px); transition:opacity .25s ease, transform .25s ease; max-width:340px; }
.toast.in { opacity:1; transform:translateY(0); }
.toast-warn { border-left-color:var(--amber); }
.toast-error { border-left-color:var(--red); }
.toast-success { border-left-color:var(--green); }

/* Duplicate-trace groups (Admin) */
.dup-groups { display:flex; flex-direction:column; gap:var(--sp-5); margin:.2rem 0 .6rem; }
.dup-group { border:1px solid var(--red-line); background:var(--red-soft); border-radius:10px; padding:.5rem .7rem; }
.dup-head { display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-5); font-size:var(--fs-2); }
.dup-mono { font-family:var(--mono); font-size:var(--fs-1); color:var(--muted); }
.dup-members { margin-top:.4rem; display:flex; flex-direction:column; gap:var(--sp-2); }
.dup-mem { display:flex; flex-direction:column; padding:.25rem .4rem; background:var(--card); border-radius:6px; font-size:var(--fs-2); }

/* Signals redesign (step 3) - full-width severity rows, items as chips */
.sig-chip { cursor:pointer; }
.sig-list-wrap { display:flex; flex-direction:column; gap:var(--sp-4); }
.sig-row { background:var(--card); border:1px solid var(--border); border-left:3px solid var(--border);
  border-radius:10px; padding:.6rem .8rem; }
.sig-row.sig-red { border-left-color:var(--red); }
.sig-row.sig-amber { border-left-color:var(--amber); }
.sig-row.sig-blue { border-left-color:var(--blue); }
.sig-row.sig-grey { border-left-color:var(--muted); }
.sig-row-hd { display:flex; align-items:baseline; gap:var(--sp-5); flex-wrap:wrap; margin-bottom:.5rem; }
.sig-row-hd .sig-name { font-weight:700; color:var(--text-strong); font-size:var(--fs-5); cursor:help; }
.sig-row-hd .sig-count { font-family:var(--mono); font-size:var(--fs-3); color:var(--muted); }
.sig-row-hd .sig-def { font-size:var(--fs-1); color:var(--muted); flex:1; min-width:160px; }
.sig-chips { display:flex; flex-wrap:wrap; gap:var(--sp-3); }
.sig-item { display:inline-flex; align-items:center; gap:var(--sp-3); background:var(--bg-section);
  border:1px solid var(--border); border-radius:999px; padding:.25rem .6rem; font-size:var(--fs-2);
  color:var(--text); cursor:pointer; transition:transform .12s ease, border-color .12s ease; }
.sig-item:hover { border-color:var(--orange-line); color:var(--orange); transform:translateY(-1px); }
.sig-item-a { font-family:var(--mono); font-size:var(--fs-1); color:var(--muted); }
.sig-clear { font-size:var(--fs-2); color:var(--green); padding:.4rem .2rem; }

/* ── Web3 entity-cluster loader ────────────────────────────────────────────
   On-brand animated network graph: a central Chainlabs "C" hub with sonar
   rings, attribution edges that draw out to labelled entity nodes (exchanges,
   mixers, bridges...), and data packets flowing along the edges. Mirrors the
   on-chain entity-clustering visual on chainlabs.ai. Pure CSS/SVG, no JS, so
   it paints immediately before app.js loads. All colour from theme vars so it
   flips with light/dark. */
.cl-loader { display:flex; flex-direction:column; align-items:center; gap:var(--sp-9); padding:1.2rem 0 .4rem; }
.cl-graph { width:min(480px,86vw); height:auto; overflow:visible; display:block; }

/* attribution edges (hub -> node), drawn once on load */
.cl-edges line { stroke:var(--orange-line); stroke-width:1.4; fill:none; stroke-linecap:round;
  stroke-dasharray:340; stroke-dashoffset:340; opacity:0; animation:cl-draw .85s ease forwards; }
@keyframes cl-draw { to { stroke-dashoffset:0; opacity:.85; } }
/* UX design pass PR 7 (startup-and-transitions): the entrance stagger used
   to run all the way to 1.36s, but data typically lands ~400ms in - the
   graph got cut mid-draw on every normal load. Delays compressed (same
   proportional stagger, same durations/easing/keyframes - only the delay
   values scaled down) so the whole sequence finishes within ~0.4s. */
.cl-edges line:nth-child(1){ animation-delay:.01s; } .cl-edges line:nth-child(2){ animation-delay:.05s; }
.cl-edges line:nth-child(3){ animation-delay:.08s; } .cl-edges line:nth-child(4){ animation-delay:.11s; }
.cl-edges line:nth-child(5){ animation-delay:.14s; } .cl-edges line:nth-child(6){ animation-delay:.18s; }
.cl-edges line:nth-child(7){ animation-delay:.21s; }

/* flowing data packets */
.cl-packet { fill:var(--orange); filter:drop-shadow(0 0 5px var(--orange)); }

/* entity nodes pop in after their edge */
.cl-nodes circle { fill:var(--orange); transform-box:fill-box; transform-origin:center;
  opacity:0; animation:cl-pop .5s cubic-bezier(.34,1.56,.64,1) forwards; }
@keyframes cl-pop { from { transform:scale(0); opacity:0; } to { transform:scale(1); opacity:1; } }
.cl-nodes circle:nth-child(1){ animation-delay:.16s; } .cl-nodes circle:nth-child(2){ animation-delay:.19s; }
.cl-nodes circle:nth-child(3){ animation-delay:.23s; } .cl-nodes circle:nth-child(4){ animation-delay:.26s; }
.cl-nodes circle:nth-child(5){ animation-delay:.29s; } .cl-nodes circle:nth-child(6){ animation-delay:.32s; }
.cl-nodes circle:nth-child(7){ animation-delay:.36s; }

/* entity labels fade in with their node */
.cl-labels text { fill:var(--muted); font-family:var(--mono); font-size:11px; letter-spacing:.3px;
  opacity:0; animation:cl-fade .5s ease forwards; }
@keyframes cl-fade { to { opacity:1; } }
.cl-labels text:nth-child(1){ animation-delay:.21s; } .cl-labels text:nth-child(2){ animation-delay:.24s; }
.cl-labels text:nth-child(3){ animation-delay:.27s; } .cl-labels text:nth-child(4){ animation-delay:.30s; }
.cl-labels text:nth-child(5){ animation-delay:.34s; } .cl-labels text:nth-child(6){ animation-delay:.37s; }
.cl-labels text:nth-child(7){ animation-delay:.40s; }

/* central hub: sonar rings + breathing "C" mark */
.cl-ring { fill:none; stroke:var(--orange); stroke-width:1.5; transform-box:fill-box; transform-origin:center;
  opacity:0; animation:cl-ping 2.6s ease-out infinite; }
.cl-ring:nth-child(2){ animation-delay:.87s; } .cl-ring:nth-child(3){ animation-delay:1.74s; }
@keyframes cl-ping { 0% { transform:scale(.55); opacity:.5; } 80%,100% { transform:scale(2.6); opacity:0; } }
.cl-hub { fill:var(--orange); filter:drop-shadow(0 0 9px var(--orange)); transform-box:fill-box;
  transform-origin:center; animation:cl-breathe 2.6s ease-in-out infinite; }
@keyframes cl-breathe { 0%,100% { transform:scale(1); } 50% { transform:scale(1.07); } }
.cl-hub-c { fill:#fff; font-family:'DM Sans',system-ui,sans-serif; font-weight:700; font-size:21px;
  text-anchor:middle; dominant-baseline:central; }

/* cycling status line + live dot */
.cl-status { display:flex; align-items:center; gap:var(--sp-4); }
.cl-live { width:7px; height:7px; border-radius:50%; background:var(--orange); flex:none;
  animation:cl-livedot 1.7s ease-out infinite; }
@keyframes cl-livedot { 0% { box-shadow:0 0 0 0 var(--orange-line); } 70%,100% { box-shadow:0 0 0 8px transparent; } }
.cl-msgs { position:relative; display:block; height:1.3em; min-width:230px; text-align:left; }
.cl-msg { position:absolute; inset:0; white-space:nowrap; color:var(--text-strong);
  font-size:var(--fs-5); font-weight:500; opacity:0; animation:cl-cycle 9s infinite; }
.cl-msg:nth-child(1){ animation-delay:0s; } .cl-msg:nth-child(2){ animation-delay:3s; } .cl-msg:nth-child(3){ animation-delay:6s; }
@keyframes cl-cycle { 0% { opacity:0; transform:translateY(5px); } 4%,28% { opacity:1; transform:none; }
  33%,100% { opacity:0; transform:translateY(-5px); } }
.cl-tag { font-family:var(--mono); font-size:var(--fs-1); letter-spacing:.4px; color:var(--dim); }

/* honour reduced-motion: show a calm static graph + first message */
@media (prefers-reduced-motion: reduce) {
  .cl-edges line, .cl-nodes circle, .cl-labels text { animation:none !important; opacity:1 !important;
    stroke-dashoffset:0 !important; transform:none !important; }
  .cl-ring, .cl-packet { display:none; }
  .cl-hub, .cl-live { animation:none; }
  .cl-msg { animation:none; } .cl-msg:nth-child(1){ opacity:1; } .cl-msg:nth-child(n+2){ display:none; }
}

/* Chart hover - dynamic small feel */
.donut circle { transition:opacity .15s ease, stroke-width .15s ease; cursor:pointer; }
.donut:hover circle { opacity:.5; }
.donut circle:hover { opacity:1; stroke-width:24; }
.spark-dot { transition:r .12s ease; cursor:pointer; }
.spark-dot:hover { r:4.5; }
.barrow .bf { transition:filter .15s ease; }
.barrow:hover .bf { filter:brightness(1.1); }

/* Floating Ask-AI launcher */
.ai-fab { position:fixed; left:1rem; bottom:1rem; z-index:50; background:var(--orange); color:#fff;
  border:none; border-radius:999px; padding:.6rem 1rem; font-weight:700; font-size:var(--fs-4); cursor:pointer;
  box-shadow:var(--shadow-md); transition:transform .15s ease, filter .15s ease; }
.ai-fab:hover { transform:translateY(-2px); filter:brightness(1.05); }

/* focus-visible for the new Signals chips + Ask-AI launcher */
.sig-item:focus-visible, .sig-chip:focus-visible, .ai-fab:focus-visible, .dup-mem:focus-visible {
  outline:2px solid var(--orange); outline-offset:2px; border-radius:8px;
}

/* Coverage world map */
.cov-map { margin:.4rem 0 1rem; padding:.6rem; background:var(--card); border:1px solid var(--border); border-radius:12px; }
.cov-svg { width:100%; height:auto; display:block; background:var(--bg-section); border-radius:8px; }
.cov-svg path { transition:fill .15s, stroke-width .15s; }
.cov-svg path:hover { stroke:var(--accent); stroke-width:1.1; }
.cov-legend { display:flex; flex-wrap:wrap; gap:var(--sp-8); margin-top:.5rem; font-size:var(--fs-2); color:var(--muted); }
.cov-legend span { display:inline-flex; align-items:center; gap:var(--sp-3); }
.cov-legend i { width:11px; height:11px; border-radius:3px; display:inline-block; border:1px solid var(--border); }

/* Freelancer comms - per-tracer two-way DM threads */
.comms-wrap { display:grid; grid-template-columns:minmax(180px,260px) 1fr; gap:var(--sp-7); margin-top:.5rem; }
.comms-list { display:flex; flex-direction:column; gap:var(--sp-2); max-height:480px; overflow:auto; border:1px solid var(--border); border-radius:10px; padding:.4rem; background:var(--card); }
.comms-row { display:flex; flex-direction:column; align-items:flex-start; gap:var(--sp-1); text-align:left; padding:.45rem .55rem; border:0; border-radius:8px; background:transparent; cursor:pointer; font:inherit; color:var(--text); }
.comms-row:hover { background:var(--bg-section); }
.comms-row.on { background:var(--blue-soft); border:1px solid var(--blue-line); }
.comms-row .muted { font-size:var(--fs-1); }
.comms-thread { border:1px solid var(--border); border-radius:10px; background:var(--card); min-height:200px; max-height:480px; overflow:auto; }
.thread-hd { position:sticky; top:0; background:var(--card); border-bottom:1px solid var(--border); padding:.55rem .7rem; font-weight:600; }
.thread-body { display:flex; flex-direction:column; gap:var(--sp-4); padding:.7rem; }
.msg { max-width:78%; padding:.45rem .6rem; border-radius:12px; }
.msg.in  { align-self:flex-start; background:var(--bg-section); border:1px solid var(--border); }
.msg.out { align-self:flex-end; background:var(--blue-soft); border:1px solid var(--blue-line); }
.msg-meta { font-size:var(--fs-1); color:var(--muted); margin-bottom:.15rem; }
.msg-body { font-size:var(--fs-4); white-space:pre-wrap; word-break:break-word; }
@media (max-width:720px){ .comms-wrap { grid-template-columns:1fr; } }

/* Sheets-style per-column filter row */
.dt .filt-row th { padding:.2rem .3rem; background:var(--bg-section); position:sticky; top:0; }
.colfilt { width:100%; box-sizing:border-box; font:inherit; font-size:var(--fs-1); padding:.2rem .35rem;
  border:1px solid var(--border); border-radius:6px; background:var(--card); color:var(--text); }
.colfilt::placeholder { color:var(--dim); }

/* AI Assist - excluded-from-assignment chips */
.ai-excl { display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-3); margin:.2rem 0 .6rem; }
.ai-excl .p { border:0; font:inherit; }

/* Comms sub-mode toggle (Conversations | Notifications) - BUILD PUSH 4 WS2 */
.seg { display:inline-flex; border:1px solid var(--border-strong); border-radius:6px; overflow:hidden; vertical-align:middle; }
.seg-i { font:inherit; font-size:var(--fs-3); padding:.18rem .6rem; background:var(--card); color:var(--muted); border:0; cursor:pointer; }
.seg-i + .seg-i { border-left:1px solid var(--border); }
.seg-i.on { background:var(--orange-soft); color:var(--text-strong); font-weight:600; }

/* KYC-verified pick citations (BUILD PUSH 4 WS1) */
.ai-opt-cite { display:inline-flex; gap:var(--sp-3); margin-left:.4rem; }
.ai-opt-cite a { font-size:var(--fs-1); color:var(--orange); text-decoration:none; }
.ai-opt-cite a:hover { text-decoration:underline; }

/* ============================================================================
   PROFESSIONAL POLISH v2 - chrome refinement (header / nav / toolbar / icons).
   Loaded last so it wins the cascade. Internal ops console + client portal both
   benefit (shared tokens); no client-specific data is referenced here.
   ========================================================================== */

/* Inline stroke-icon base - replaces emoji glyphs across the chrome. */
.ic { flex:0 0 auto; display:inline-block; vertical-align:-2px; color:currentColor; }
button .ic, a .ic { pointer-events:none; }

/* ---- Header: frosted sticky bar + refined logo + title ---- */
.app-hdr { padding:.7rem 0 .65rem; background:var(--header-bg);
  backdrop-filter:saturate(1.1) blur(12px); -webkit-backdrop-filter:saturate(1.1) blur(12px);
  border-bottom:1px solid var(--border); }
.app-hdr-title { gap:var(--sp-5); }
.logo { width:36px; height:36px; border-radius:11px; font-size:var(--fs-8); letter-spacing:-.02em;
  background:var(--grad-accent); color:#fff;
  box-shadow:0 3px 8px rgba(244,122,0,.32), inset 0 1px 0 rgba(255,255,255,.30); }
.app-hdr h1 { font-size:var(--fs-9); letter-spacing:-.015em; }
.meta { font-size:var(--fs-1); margin-top:2px; letter-spacing:.005em; font-variant-numeric:tabular-nums; }

/* Header right cluster - clean icon buttons */
.app-hdr-right { gap:var(--sp-4); }
.btn-ghost { width:auto; min-width:34px; height:34px; display:inline-grid; place-items:center;
  border-radius:9px; padding:0 .55rem; }
/* 2026-09-15: the Live pill is gone; the refresh control carries the age
   (Mally: "the live button should be merged with refresh"). */
.fresh-age { color:var(--muted); font-weight:500; margin-left:.35em; font-variant-numeric:tabular-nums; }
.fresh-age:empty { display:none; }
#refresh-btn { display:inline-flex; align-items:center; gap:.3em; white-space:nowrap;
  max-width:34ch; overflow:hidden; text-overflow:ellipsis; }
#refresh-btn.stale { border-color:var(--amber-line); color:var(--amber); background:var(--amber-soft); }
#refresh-btn.stale .fresh-age { color:var(--amber); }

/* ---- Primary navigation ---- */
.topnav-inner { gap:var(--sp-1); }
.navlink { padding:.42rem .72rem; font-size:var(--fs-4); font-weight:600; border-radius:8px;
  border-bottom:none; color:var(--text); }
.navlink:hover { background:var(--bg-section); color:var(--text-strong); }
.navlink.on, .navlink.on:hover { color:var(--orange); background:var(--orange-soft); }
.navlink.on::after { content:''; position:absolute; left:.72rem; right:.72rem; bottom:-.65rem;
  height:2px; border-radius:2px; background:var(--orange); }
.tabcog { width:34px; height:34px; display:inline-grid; place-items:center; padding:0; border-radius:8px; }
.tabcog:hover { background:var(--bg-section); }

/* ---- Toolbar: search | filters | spacer | count | actions ---- */
/* NEVER render a .modal-overlay (or any position:fixed element) inside
   .toolbar. `backdrop-filter` with a non-none value makes this element the
   containing block for every position:fixed descendant - exactly the trap an
   animated `transform` caused on #main.enter, documented at the secfade rule
   above. A fixed overlay nested here sizes against the ~39px toolbar strip
   instead of the viewport (measured in Chromium at 1400x800: 1400x38.6 at
   y=60, not 1400x800 at y=0), so its backdrop paints as a dark band across
   the toolbar row and the centred modal spills off screen top and bottom.
   .toolbar's z-index:20 stacking context also caps the overlay's z-index:60.
   The frosted effect is deliberate and stays; overlays go at the top-level
   modal layer instead - see the comment beside PendingChangesModal in app.js. */
.toolbar { gap:var(--sp-4); padding:.55rem 0; background:var(--header-bg);
  backdrop-filter:saturate(1.1) blur(12px); -webkit-backdrop-filter:saturate(1.1) blur(12px);
  border-bottom:1px solid var(--border); }
.toolbar input[type="search"], .toolbar select, .toolbar .btn, .toolbar .btn-sec,
.tb-actions button, .tb-actions select, .authchip .btn-sec {
  height:34px; border-radius:9px; }
.toolbar select { font-size:var(--fs-3); }

.tb-search { position:relative; display:inline-flex; align-items:center; }
.tb-search .ic { position:absolute; left:.62rem; color:var(--muted); }
.tb-search input[type="search"] { padding-left:2.05rem; min-width:230px; }

.tb-filters { display:inline-flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap; }
.tb-sel { max-width:178px; }
.tb-sel.date { max-width:128px; }

.tb-count { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; font-variant-numeric:tabular-nums; padding-right:.2rem; }
/* Actions hug the right edge and wrap as one right-aligned unit. */
.tb-actions { display:inline-flex; align-items:center; gap:var(--sp-3); flex:0 0 auto; margin-left:auto; }

/* Client filter chips - read clearly as toggles, distinct from status pills */
.cfil { display:inline-flex; align-items:center; gap:var(--sp-3); height:34px; padding:0 .7rem;
  border-radius:9px; border:1px solid var(--border); background:var(--card); color:var(--text);
  font:inherit; font-size:var(--fs-3); font-weight:600; cursor:pointer; white-space:nowrap;
  transition:border-color .14s ease, background .14s ease, color .14s ease; }
.cfil:hover { border-color:var(--border-strong); color:var(--text-strong); }
.cfil .ic { opacity:0; width:0; margin-left:-.32rem; transition:opacity .12s ease; }
.cfil.on { background:var(--orange-soft); border-color:var(--orange-line); color:var(--orange); }
.cfil.on .ic { opacity:1; width:14px; margin-left:0; }

/* Icon-leading select wrapper (View as…) */
.tb-iconsel { position:relative; display:inline-flex; align-items:center; }
.tb-iconsel > .ic { position:absolute; left:.58rem; color:var(--muted); z-index:1; }
.tb-iconsel select { padding-left:1.95rem; }

/* Compact icon-only secondary actions (share / reset) */
.iconbtn { display:inline-grid; place-items:center; width:34px; height:34px; border-radius:9px;
  background:var(--card); border:1px solid var(--border); color:var(--text); cursor:pointer;
  transition:border-color .14s ease, color .14s ease, background .14s ease; }
.iconbtn:hover { border-color:var(--orange-line); color:var(--orange); background:var(--orange-soft); }
.iconbtn.ok { border-color:var(--green-line); color:var(--green); background:var(--green-soft); }

/* Buttons that carry an icon + label sit aligned */
.btn, .btn-sec, .btn-ghost, .iconbtn, .cfil, .navlink, .ai-fab, .pf-stream-b, .seg-i { display:inline-flex; }
.btn, .btn-sec { align-items:center; gap:var(--sp-3); }
.btn { background:var(--grad-accent); box-shadow:0 2px 6px rgba(244,122,0,.25); }
.btn:hover { filter:brightness(1.04); }
.tb-actions .btn-sec.p-green { background:var(--green-soft); border-color:var(--green-line); color:var(--green); font-weight:600; }

/* Clients multi-select dropdown (replaces the row of client chips) */
.cfdd { position:relative; display:inline-flex; }
.cfdd-btn { display:inline-flex; align-items:center; gap:var(--sp-3); height:34px; padding:0 .7rem;
  border-radius:9px; border:1px solid var(--border); background:var(--card); color:var(--text);
  font:inherit; font-size:var(--fs-3); font-weight:600; cursor:pointer; white-space:nowrap;
  transition:border-color .14s ease, background .14s ease, color .14s ease; }
.cfdd-btn:hover { border-color:var(--border-strong); color:var(--text-strong); }
.cfdd-btn.on { background:var(--orange-soft); border-color:var(--orange-line); color:var(--orange); }
.cfdd-count { display:inline-grid; place-items:center; min-width:18px; height:18px; padding:0 5px;
  border-radius:9px; background:var(--orange); color:#fff; font-size:var(--fs-1); font-weight:700; }
.cfdd-caret { font-size:var(--fs-1); color:var(--muted); }
.cfdd-menu { position:absolute; top:calc(100% + 6px); left:0; z-index:60; min-width:200px;
  background:var(--card); border:1px solid var(--border); border-radius:10px;
  box-shadow:0 8px 24px rgba(0,0,0,.12); padding:.35rem; display:flex; flex-direction:column; gap:1px; }
.cfdd-all { text-align:left; background:none; border:none; cursor:pointer; font:inherit; font-size:var(--fs-2);
  font-weight:600; color:var(--orange); padding:.4rem .5rem; border-radius:7px; }
.cfdd-all:hover { background:var(--orange-soft); }
.cfdd-opt { display:flex; align-items:center; gap:var(--sp-4); padding:.4rem .5rem; border-radius:7px;
  font-size:var(--fs-3); color:var(--text-strong); cursor:pointer; }
.cfdd-opt:hover { background:var(--bg-section); }
.cfdd-opt input { accent-color:var(--orange); }
.cfdd-grouped { min-width:280px; max-height:min(70vh, 560px); overflow:auto; }
.cfdd-group { border-top:1px solid var(--divider); }
.cfdd-group summary { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-6);
  padding:.45rem .5rem; border-radius:7px; color:var(--text-strong); font-size:var(--fs-2);
  font-weight:700; cursor:pointer; list-style:none; }
.cfdd-group summary::-webkit-details-marker { display:none; }
.cfdd-group summary::before { content:'▸'; color:var(--muted); margin-right:.15rem; }
.cfdd-group[open] summary::before { content:'▾'; }
.cfdd-group summary:hover { background:var(--bg-section); }
.cfdd-group .cfdd-opt { padding-left:1.45rem; }
.cfdd-group-all { display:block; text-align:left; background:none; border:none; cursor:pointer; font:inherit;
  font-size:var(--fs-4); font-weight:600; color:var(--orange); padding:.2rem .5rem .35rem 1.45rem; border-radius:7px; }
.cfdd-group-all:hover { background:var(--orange-soft); }

/* Labeled compact action buttons (Share / Reset) */
.iconbtn.lbl { width:auto; display:inline-flex; align-items:center; gap:var(--sp-3); padding:0 .65rem; }
.iconbtn-t { font-size:var(--fs-2); font-weight:600; }
@media (max-width:760px) { .iconbtn-t { display:none; } .iconbtn.lbl { width:34px; padding:0; } }

/* Clickable insight card (e.g. Traces by month -> expand) */
.icard-click { cursor:pointer; transition:border-color .14s ease, box-shadow .14s ease; }
.icard-click:hover { border-color:var(--orange-line); box-shadow:0 2px 10px rgba(244,122,0,.12); }
.icard-click:focus-visible { outline:2px solid var(--orange-line); outline-offset:2px; }
.expand-chart { padding:.4rem 0 1rem; }

/* Inactivity lock overlay (1h auto-logout) */
.idle-lock { display:none; position:fixed; inset:0; z-index:2147483647; background:var(--bg);
  color:var(--text); align-items:center; justify-content:center; padding:1.5rem; }
.idle-lock.is-active { display:flex; }
.idle-lock-card { background:var(--card); border:1px solid var(--border); border-radius:14px;
  box-shadow:0 8px 24px rgba(0,0,0,.12); padding:2.25rem 2rem; max-width:380px; width:100%; text-align:center; }
.idle-lock-icon { display:inline-flex; align-items:center; justify-content:center; width:64px; height:64px;
  margin-bottom:1rem; border-radius:50%; background:var(--orange-soft); color:var(--orange); }
.idle-lock-card h2 { margin:0 0 .4rem; font-size:var(--fs-9); font-weight:700; color:var(--text-strong); }
.idle-lock-msg { margin:0 0 1.4rem; font-size:var(--fs-4); line-height:1.5; color:var(--muted); }
.idle-lock-btn { appearance:none; border:none; cursor:pointer; font:inherit; font-size:var(--fs-4); font-weight:600;
  color:#fff; background:var(--orange); border-radius:9px; padding:.6rem 1.4rem; }
.idle-lock-btn:hover { filter:brightness(.96); }
.idle-lock-btn:focus-visible { outline:2px solid var(--orange-line); outline-offset:2px; }

/* Subbar (PM tabs row) actions get the same alignment */
.subbar .btn, .subbar .btn-sec { height:34px; }

/* ---- Metric cards -> stat strip (2026-09-15) ----
   Mally: "stop using these AI boxes ... its everywhere and annoying to see".
   Every .metrics grid on every tab is now ONE surface: the numbers sit side
   by side behind 1px hairlines, label above value, fixed height, no border
   or radius per number. The data makes the grid (ui-typography, Tables);
   the count sub-line (.mnote) stays under every USD figure (CLAUDE.md 36).
   Overrides the base .metrics/.mc rules above; nothing at the 9 call sites
   changes. Scoped nowhere special on purpose - the client portal renders no
   .metrics or .mc at all (checked), so this cannot reach it. */
.metrics { display:flex; flex-wrap:wrap; gap:0; background:var(--card); border:1px solid var(--border);
  border-radius:var(--rl); overflow:hidden; box-shadow:var(--shadow-sm); }
.mc { flex:1 1 0; min-width:150px; min-height:64px; padding:var(--sp-5) var(--sp-8); border:0; border-radius:0;
  box-shadow:none; background:transparent; border-left:1px solid var(--divider);
  display:flex; flex-direction:column; justify-content:center; }
.mc:first-child { border-left:0; }
/* A clipped label must be recoverable: Metric passes title="label: value",
   so hover gives the full text (ui-ux-pro-max, truncation-strategy). */
.mc .ml { font-size:var(--fs-1); font-weight:600; letter-spacing:.06em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.mc .mv { font-size:var(--fs-10); margin-top:var(--sp-1); line-height:1.2; letter-spacing:-.02em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.mc.alert { box-shadow:inset 3px 0 0 var(--red); }
.mc:hover { border-color:var(--divider); background:var(--bg-section); }
.mc-click:hover { border-color:var(--divider); }
/* State colour lives on the value, by class, instead of an inline style. */
.mv-good { color:var(--green); } .mv-warn { color:var(--amber); } .mv-bad { color:var(--red); }

/* ---- Floating Ask-AI launcher + AI title ---- */
.ai-fab { align-items:center; gap:var(--sp-3); border-radius:12px; padding:.58rem .95rem;
  background:var(--grad-accent); box-shadow:var(--shadow-lg); }
.ai-title { gap:var(--sp-4); }
.ai-title .ai-glyph { display:inline-grid; place-items:center; width:28px; height:28px; border-radius:8px;
  background:var(--orange-soft); color:var(--orange); border:1px solid var(--orange-line); }

/* ---- Inputs: unified focus ring ---- */
.toolbar input:focus, .toolbar select:focus, .ein:focus, input:focus, select:focus, textarea:focus {
  outline:none; border-color:var(--orange-line); box-shadow:0 0 0 3px var(--ring); }

/* ---- Footer: quieter ---- */
.footer-note { font-size:var(--fs-1); line-height:1.6; }

.iconbtn:focus-visible, .cfil:focus-visible, .mode-pill:focus-visible, .tabcog:focus-visible {
  outline:2px solid var(--orange); outline-offset:2px; border-radius:9px;
}

@media (max-width:900px) {
  .tb-search input[type="search"] { min-width:150px; }
  .tb-count { display:none; }
}

/* ── Onboarding: welcome modal ── */
.navhelp { font-weight:700; width:30px; text-align:center; }
.modal.onb { width:min(440px,94vw); }
.onb-x { background:none; border:none; color:var(--muted); font-size:var(--fs-10); line-height:1; cursor:pointer; padding:0 .2rem; }
.onb-x:hover { color:var(--text-strong); }
.onb-body { text-align:center; }
.onb-ic { width:54px; height:54px; margin:.2rem auto .7rem; border-radius:14px; display:grid; place-items:center;
  background:var(--bg-section); color:var(--accent); border:1px solid var(--border); }
.onb-text { font-size:var(--fs-5); line-height:1.5; color:var(--text); margin:0 auto .9rem; max-width:34ch; }
.onb-dots { display:flex; gap:var(--sp-3); justify-content:center; }
.onb-dot { width:7px; height:7px; border-radius:50%; background:var(--border-strong); transition:background .2s; }
.onb-dot.on { background:var(--accent); }
.onb-foot { justify-content:space-between; align-items:center; }
.onb-nav { display:flex; gap:var(--sp-4); }

/* ── Onboarding: spotlight tour ── */
.tour-backdrop { position:fixed; inset:0; z-index:100; background:transparent; }
.tour-spot { position:fixed; z-index:101; border-radius:10px; pointer-events:none;
  box-shadow:0 0 0 9999px rgba(8,12,20,.62), 0 0 0 2px var(--accent), 0 0 18px 2px rgba(244,122,0,.55);
  transition:top .18s ease, left .18s ease, width .18s ease, height .18s ease; }
.tour-pop { position:fixed; z-index:102; background:var(--card); border:1px solid var(--border-strong);
  border-radius:var(--rl); box-shadow:var(--shadow-lg); padding:.9rem 1rem; }
.tour-pop-t { font-size:var(--fs-6); font-weight:700; color:var(--text-strong); margin-bottom:.3rem; }
.tour-pop-b { font-size:var(--fs-4); line-height:1.45; color:var(--text); }
.tour-pop-f { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); margin-top:.8rem; }
.tour-step { font-size:var(--fs-1); color:var(--muted); }
.tour-pop-btns { display:flex; gap:var(--sp-3); }
@media (prefers-reduced-motion: reduce) {
  .tour-spot { transition:none; }
  .onb-dot { transition:none; }
}

/* ── Notifications: grouped/categorised view ── */
.nf-wrap { margin-top:.2rem; }
.nf-summary { display:flex; gap:var(--sp-9); flex-wrap:wrap; padding:.6rem .8rem; margin-bottom:.7rem;
  background:var(--bg-section); border:1px solid var(--border); border-radius:var(--r); }
.nf-stat { font-size:var(--fs-3); color:var(--muted); }
.nf-stat b { color:var(--text-strong); font-size:var(--fs-6); }
.nf-cat { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.06em; color:var(--muted);
  font-weight:600; margin:.9rem 0 .4rem; }
.nf-group { border:1px solid var(--border); border-radius:var(--r); margin-bottom:.4rem; overflow:hidden; background:var(--card); }
.nf-group-h { width:100%; display:flex; align-items:center; gap:var(--sp-5); padding:.55rem .7rem;
  background:none; border:none; cursor:pointer; text-align:left; font-size:var(--fs-4); color:var(--text); }
.nf-group-h:hover { background:var(--bg-section); }
.nf-caret { color:var(--muted); width:.9rem; flex:none; }
.nf-name { font-weight:600; color:var(--text-strong); flex:none; min-width:160px; }
.nf-chips { display:flex; gap:var(--sp-3); flex-wrap:wrap; flex:1; }
.nf-meta { color:var(--muted); font-size:var(--fs-2); flex:none; white-space:nowrap; }
.nf-detail { border-top:1px solid var(--divider); padding:.3rem .7rem .5rem; background:var(--bg-section); }
.nf-line { display:flex; gap:var(--sp-5); align-items:baseline; padding:.22rem 0; font-size:var(--fs-3);
  border-bottom:1px solid var(--divider); }
.nf-line:last-child { border-bottom:none; }
.nf-when { color:var(--muted); font-size:var(--fs-1); white-space:nowrap; flex:none; min-width:130px; }
.nf-to { font-weight:600; color:var(--text); white-space:nowrap; flex:none; min-width:150px; }
.nf-msg { color:var(--text); flex:1; min-width:0; overflow-wrap:anywhere; }
@media (max-width:720px) {
  .nf-name { min-width:0; }
  .nf-when { min-width:0; }
  .nf-to { min-width:0; }
  .nf-group-h { flex-wrap:wrap; }
}

/* ── Client portal redesign (Overview reporting, richer detail, form) ── */
.pf-overview-h { display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-8); margin-bottom:1rem; }
.pf-overview-title { font-size:var(--fs-10); font-weight:700; color:var(--text-strong); }
.pf-panel-sub { font-weight:400; font-size:var(--fs-1); color:var(--muted); margin-left:.5rem; }
.pf-panel-foot { text-align:right; margin-top:.2rem; }
.pf-topgrid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); grid-auto-rows:1fr; gap:var(--pf-gap); margin-bottom:1rem; }
.pf-toppanel { margin-bottom:0; }
/* Overview load summaries (requests by requester / project) */
.pf-loadgrid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--pf-gap); margin-bottom:1rem; }
/* When only one load panel has data (LoadPanel returns null on empty rows) the
   lone panel spans the full row instead of sitting in a half-empty 2-col grid.
   Same pattern as .pf-reportgrid-1. */
.pf-loadgrid.pf-loadgrid-1 { grid-template-columns:1fr; }
.pf-loadpanel { margin-bottom:0; }
.pf-loadlist { display:flex; flex-direction:column; gap:var(--sp-1); }
.pf-loadrow { display:grid; grid-template-columns:minmax(80px,1fr) minmax(60px,1.4fr) auto; align-items:center; gap:var(--sp-5);
  background:transparent; border:0; border-radius:8px; padding:.4rem .5rem; cursor:pointer; text-align:left; color:inherit; }
.pf-loadrow:hover { background:var(--bg-section); }
.pf-loadrow-name { font-size:var(--fs-4); font-weight:600; color:var(--text-strong); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-loadrow-track { height:8px; }
.pf-loadrow-n { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; }
.pf-loadrow-n b { color:var(--text-strong); }
.pf-allreq-h { font-size:var(--fs-8); font-weight:700; color:var(--text-strong); margin:1.4rem 0 .7rem; scroll-margin-top:1rem; }
.pf-toplist { display:flex; flex-direction:column; }
.pf-toprow { display:grid; grid-template-columns:1fr auto; grid-template-areas:'name pill' 'date pill'; gap:var(--sp-1) .6rem;
  align-items:center; width:100%; text-align:left; background:none; border:none; cursor:pointer;
  padding:.5rem .3rem; border-bottom:1px solid var(--divider); border-radius:6px; }
.pf-toprow:last-child { border-bottom:none; }
.pf-toprow:hover { background:var(--bg-section); }
.pf-toprow-name { grid-area:name; color:var(--text-strong); font-weight:600; font-size:var(--fs-4); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-toprow-date { grid-area:date; font-size:var(--fs-1); }
.pf-toprow .pf-pill { grid-area:pill; }
.pf-top-empty { padding:.6rem .3rem; font-size:var(--fs-3); }

/* KPI inline percentage sub-line (no more standalone % boxes) */
.pf-kpi-sub { font-size:var(--fs-1); color:var(--muted); margin-top:.15rem; }
/* Overview header actions (dashboard link + new request) */
.pf-overview-actions { display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap; }
/* Fees panel stat line (this-month + MoM) */
.pf-statline { display:flex; align-items:center; gap:var(--sp-7); margin:.1rem 0 .5rem; }
.pf-stat { font-size:var(--fs-3); color:var(--text); } .pf-stat b { color:var(--text-strong); }
.pf-stat-up { color:var(--red); } .pf-stat-dn { color:var(--green); }
/* Current-month emphasis on month bars */
.pf-mbar.is-cur .pf-mbar-fill { outline:2px solid var(--text-strong); outline-offset:-1px; }
.pf-mbar.is-cur .pf-mbar-l { color:var(--text-strong); font-weight:700; }

/* Compact request-pipeline funnel (replaces the tall stacked bars) */
.pf-funnel { display:flex; gap:3px; height:30px; border-radius:8px; overflow:hidden; margin:.2rem 0 .6rem; }
.pf-funnel-seg { border:none; cursor:pointer; min-width:24px; display:flex; align-items:center; justify-content:center;
  color:#fff; font-size:var(--fs-1); font-weight:700; transition:opacity .15s ease; padding:0; }
.pf-funnel-seg:hover { opacity:.85; }
.pf-funnel-seg.st-under_review { background:var(--blue); } .pf-funnel-seg.st-assigned { background:var(--purple); }
.pf-funnel-seg.st-wip { background:var(--amber); } .pf-funnel-seg.st-blocked { background:var(--red); }
.pf-funnel-seg.st-traced { background:var(--green); } .pf-funnel-seg.st-not_traceable { background:var(--dim); }
.pf-funnel-seg.st-closed { background:var(--dim); } .pf-funnel-seg.st-on_hold { background:#64748b; }
.pf-funnel-seg-n { text-shadow:0 1px 1px rgba(0,0,0,.25); }
/* grey (dim) segments: white-on-grey fails contrast in light mode - use strong ink */
.pf-funnel-seg.st-not_traceable, .pf-funnel-seg.st-closed { color:var(--text-strong); }
.pf-funnel-seg.st-not_traceable .pf-funnel-seg-n, .pf-funnel-seg.st-closed .pf-funnel-seg-n { text-shadow:none; }
.pf-funnel-legend { display:flex; flex-wrap:wrap; gap:var(--sp-3) .8rem; }
.pf-leg { display:inline-flex; align-items:center; gap:var(--sp-3); background:none; border:none; cursor:pointer; padding:.15rem .2rem; font-size:var(--fs-2); color:var(--text); border-radius:6px; }
.pf-leg:hover { background:var(--bg-section); }
.pf-leg-sw { width:10px; height:10px; border-radius:3px; display:inline-block; }
.pf-leg-sw.st-under_review { background:var(--blue); } .pf-leg-sw.st-assigned { background:var(--purple); }
.pf-leg-sw.st-wip { background:var(--amber); } .pf-leg-sw.st-blocked { background:var(--red); }
.pf-leg-sw.st-traced { background:var(--green); } .pf-leg-sw.st-not_traceable { background:var(--dim); }
.pf-leg-sw.st-closed { background:var(--dim); } .pf-leg-sw.st-on_hold { background:#64748b; }
.pf-leg b { color:var(--text-strong); }

/* Reporting grid: fees-by-month + hours-by-month panels */
.pf-reportgrid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--pf-gap); margin-bottom:1rem; align-items:start; }
/* Only one report panel present (e.g. a client with no worklog hours) -> the lone
   panel fills the row instead of leaving an empty second column. Two-class
   specificity wins over the media-query .pf-reportgrid rules below. */
.pf-reportgrid.pf-reportgrid-1 { grid-template-columns:1fr; }
.pf-mbars { display:flex; align-items:flex-end; gap:var(--sp-3); height:120px; padding:.3rem 0 0; }
.pf-mbar { flex:1 1 0; min-width:0; display:flex; flex-direction:column; align-items:center; gap:var(--sp-2); height:100%; }
.pf-mbar-track { flex:1 1 auto; width:100%; display:flex; align-items:flex-end; }
.pf-mbar-fill { width:100%; background:var(--blue); border-radius:4px 4px 0 0; min-height:3px; transition:height .4s ease; }
.pf-mbar-fill.acc { background:var(--green); }
.pf-mbar-v { font-size:var(--fs-1); color:var(--text-strong); font-weight:600; white-space:nowrap; }
.pf-mbar-l { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; }
.pf-flag { color:var(--amber); font-weight:700; }
/* Weekly intake vs completion (grouped bars, 13-week window) */
.pf-weekchart { display:flex; align-items:flex-end; gap:var(--sp-3); height:140px; padding:.3rem 0 0; }
.pf-week { flex:1 1 0; min-width:0; display:flex; flex-direction:column; align-items:center; gap:var(--sp-2); height:100%; }
.pf-week-bars { flex:1 1 auto; width:100%; display:flex; align-items:flex-end; justify-content:center; gap:2px; }
.pf-week-bar { width:42%; min-height:2px; border-radius:3px 3px 0 0; transition:height .4s ease; }
.pf-week-in { background:var(--blue); }
.pf-week-done { background:var(--green); }
.pf-week-l { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; }
.pf-caprow { display:flex; align-items:center; gap:var(--sp-4); margin-top:.5rem; }
.pf-captrack { flex:1 1 auto; height:8px; }

/* Monthly hours vs cap billing-transparency table */
.pf-monthcaps { display:flex; flex-direction:column; }
.pf-monthcaps-row { display:grid; grid-template-columns:110px 100px 90px 70px 1fr; gap:var(--sp-5); align-items:center;
  padding:.5rem 0; border-bottom:1px solid var(--divider); font-size:var(--fs-3); }
.pf-monthcaps-row:last-child { border-bottom:none; }
.pf-monthcaps-h { font-size:var(--fs-1); color:var(--muted); text-transform:uppercase; letter-spacing:.03em;
  border-bottom:1px solid var(--border); padding-bottom:.4rem; }
.pf-monthcaps-month { font-weight:600; color:var(--text-strong); }
.pf-monthcaps-over { color:var(--red); font-weight:600; }
.pf-monthcaps-chips { display:flex; flex-wrap:wrap; gap:.3rem; }
.pf-cluster-chip { display:inline-flex; align-items:center; gap:.25rem; background:var(--bg-section); border:1px solid var(--border);
  border-radius:20px; padding:.15rem .55rem; font-size:var(--fs-1); color:var(--text); white-space:nowrap; }
.pf-cluster-chip b { color:var(--text-strong); font-weight:600; }
@media (max-width:640px) {
  .pf-monthcaps { overflow-x:auto; }
  .pf-monthcaps-row { grid-template-columns:90px 80px 70px 60px 220px; min-width:520px; }
}

/* Expandable chart cards (Reporting & analytics) */
.pf-chartcard { display:flex; flex-direction:column; }
.pf-chart-expandbtn { width:100%; background:none; border:none; font:inherit; color:inherit; cursor:pointer;
  text-align:left; padding:0; margin-bottom:.8rem; border-radius:6px; transition:color .15s ease; }
.pf-chart-expandbtn:hover { color:var(--orange); }
.pf-chart-expandbtn:hover .pf-expand-ico { opacity:1; color:var(--orange); }
.pf-chart-expandbtn:focus-visible { outline:2px solid var(--orange); outline-offset:3px; }
.pf-chart-expand-r { display:inline-flex; align-items:center; gap:var(--sp-4); }
.pf-expand-ico { font-size:var(--fs-6); opacity:.45; transition:opacity .15s ease, color .15s ease; }

/* Treemap (coverage by category) */
.pf-tmap-wrap { display:flex; flex-direction:column; gap:var(--sp-5); }
.pf-tmap { width:100%; height:auto; aspect-ratio:100/62; border-radius:8px; overflow:hidden;
  background:var(--bg-section); display:block; }
.pf-tmap rect { transition:opacity .15s ease; cursor:default; }
.pf-tmap:hover rect { opacity:.55; } .pf-tmap rect:hover { opacity:1; }
.pf-tmap-t { font-size:3.1px; font-weight:700; fill:#fff; font-family:var(--sans); pointer-events:none;
  paint-order:stroke; stroke:rgba(0,0,0,.18); stroke-width:.25px; }
.pf-tmap-n { font-size:3px; fill:rgba(255,255,255,.92); font-family:var(--mono); pointer-events:none; }
.pf-tmap-leg { flex-direction:row; flex-wrap:wrap; gap:var(--sp-2) .8rem; }
.pf-tmap-leg .dleg { display:inline-flex; width:auto; }

/* Chart expand modal (reuses .pf-guide overlay chrome) */
.pf-cmodal { width:min(760px,94vw); max-height:88vh; display:flex; flex-direction:column; overflow:hidden; }
.pf-cmodal-body { flex:1 1 auto; min-height:0; overflow-y:auto; display:flex; flex-direction:column; gap:var(--sp-8); }
.pf-cmodal-chart { padding:.4rem 0; }
.pf-cmodal-table { border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.pf-ct-head, .pf-ct-row { display:grid; grid-template-columns:1fr auto auto; gap:var(--sp-8); padding:.4rem .8rem; align-items:center; }
.pf-ct-head { background:var(--bg-section); color:var(--muted); font-size:var(--fs-1); text-transform:uppercase;
  letter-spacing:.04em; font-weight:700; }
.pf-ct-head span:nth-child(2), .pf-ct-head span:nth-child(3), .pf-ct-n, .pf-ct-pct { text-align:right; min-width:46px; }
.pf-ct-row { border-top:1px solid var(--divider); font-size:var(--fs-3); }
.pf-ct-name { display:flex; align-items:center; gap:var(--sp-4); color:var(--text-strong); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-ct-dot { width:9px; height:9px; border-radius:2px; flex:0 0 auto; }
.pf-ct-n { font-family:var(--mono); color:var(--text-strong); font-weight:600; }
.pf-ct-pct { font-family:var(--mono); color:var(--muted); }

/* Not-traceable summary panel */
.pf-ntpanel { border-left:3px solid var(--dim); }

/* Global filter bar (above Overview + Traces) */
.pf-globalfilter { display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-4); margin:0 0 1rem; padding:.5rem .6rem;
  background:var(--bg-section); border:1px solid var(--border); border-radius:10px; }
.pf-gf-label { font-size:var(--fs-1); font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
.pf-gf-clear { background:none; border:1px solid var(--border-strong); border-radius:8px; cursor:pointer; font-size:var(--fs-1); padding:.3rem .55rem; color:var(--text); }
.pf-gf-clear:hover { background:var(--card); }

/* Requests: filter selects + result meta + board trace count */
.pf-fsel { height:34px; padding:.3rem .5rem; border-radius:8px; font-size:var(--fs-3); max-width:180px; }
.pf-result-meta { font-size:var(--fs-2); margin:-.4rem 0 .7rem; }
.pf-bcard-traces { display:inline-block; font-size:var(--fs-1); color:var(--muted); margin-top:.2rem; }

/* Drawer: richer trace cards with seed address / tx chips */
.pf-tracecard { padding:.45rem .5rem; border:1px solid var(--border); border-radius:8px; margin-bottom:.4rem; background:var(--card2,var(--card)); }
.pf-tracecard-top { display:flex; align-items:baseline; gap:var(--sp-4); font-size:var(--fs-3); }
.pf-tracecard-top .pf-trace-tok { font-weight:600; font-family:var(--mono); min-width:78px; }
.pf-tracecard-top .pf-trace-meta { flex:1; color:var(--muted); }
.pf-trace-chain { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin-top:.4rem; }
.pf-chip-copy { display:inline-flex; align-items:center; gap:var(--sp-3); background:var(--bg-section); border:1px solid var(--border);
  border-radius:6px; padding:.2rem .45rem; font-family:var(--mono); font-size:var(--fs-1); color:var(--text); cursor:pointer; }
.pf-chip-copy:hover { border-color:var(--orange-line); }
.pf-chip-l { font-family:var(--font,inherit); font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.04em; color:var(--muted); }
/* TxID chip linked to the block explorer (matches the freelancer sheets) */
.pf-chip-link { text-decoration:none; color:var(--orange); border-color:var(--orange-line); }
.pf-chip-link:hover { background:var(--orange-soft,rgba(245,158,11,.1)); }
.pf-chip-link .pf-chip-l { color:var(--orange); }
.pf-chip-mini { padding:.2rem .35rem; font-size:var(--fs-1); }

/* New request: roomier 2-col grid, help, chip multipicker */
/* Centered in the 1180px shell - without margin:auto the form pinned hard left
   and left a dead right half on wide screens. */
.pf-form-wide { max-width:760px; width:100%; margin:0 auto; }
.pf-form-head { display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-8); }
.pf-form-grid { display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-6) 1rem; }
.pf-grid-2 { grid-template-columns:1fr 1fr; }
.pf-help { background:var(--bg-section); border:1px solid var(--border); border-radius:var(--r);
  padding:.7rem .85rem; font-size:var(--fs-3); line-height:1.5; color:var(--text); }
.pf-picker { display:flex; flex-direction:column; }
.pf-picker-actions { float:right; display:inline-flex; gap:var(--sp-3); }
.pf-chips { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin:.3rem 0 .15rem; }
.pf-chip { display:inline-flex; align-items:center; gap:var(--sp-3); border-radius:7px; padding:.25rem .5rem;
  font-size:var(--fs-2); cursor:pointer; border:1px solid var(--orange-line); background:var(--orange-soft); color:var(--orange); font-weight:600; }
.pf-chip-net { font-weight:400; font-size:var(--fs-1); opacity:.8; }
.pf-chip-x { opacity:.7; }
.pf-chip:hover { filter:brightness(.97); }
.pf-tok-net { font-size:var(--fs-1); color:var(--muted); margin-left:.3rem; }
.pf-othercat { flex-direction:row; align-items:center; gap:var(--sp-4); }
.pf-othercat input { flex:1; }
.pf-batch-actions { display:flex; gap:var(--sp-4); flex-wrap:wrap; margin:.2rem 0 .4rem; }
.pf-filebtn { cursor:pointer; display:inline-flex; align-items:center; }
.pf-batch-paste { width:100%; font-family:var(--mono); font-size:var(--fs-2); resize:vertical; }
.pf-batch-preview { margin:.6rem 0; }
.pf-batch-table .pf-tr { grid-template-columns:1.4fr 1fr .7fr .7fr .8fr; }
.pf-tr-bad { opacity:.55; }
.pf-tr-bad .pf-td-name { color:var(--red); }
/* chart-card footnote (excluded-Unknown note etc.) */
.pf-chart-foot { font-size:var(--fs-1); color:var(--muted); margin-top:.55rem; padding-top:.45rem; border-top:1px dashed var(--divider); }
.cov-legend-note { color:var(--muted); font-style:italic; }
/* clickable bar rows (token / network / reason drill-in) */
.pf-loadrow-click { width:100%; }
.pf-loadrow-go { color:var(--muted); margin-left:.35rem; font-weight:700; }
.pf-loadrow-click:hover .pf-loadrow-go { color:var(--orange); }
/* drill-down list inside the chart modal */
.pf-drilllist { display:flex; flex-direction:column; gap:var(--sp-1); max-height:58vh; overflow:auto; }
.pf-drillrow { display:flex; align-items:center; gap:var(--sp-6); width:100%; text-align:left; background:none;
  border:none; border-bottom:1px solid var(--divider); padding:.5rem .4rem; cursor:pointer; border-radius:6px; }
.pf-drillrow:last-child { border-bottom:none; }
.pf-drillrow:hover { background:var(--bg-section); }
.pf-drillrow-name { font-weight:600; color:var(--text-strong); font-size:var(--fs-4); flex:0 0 auto; max-width:42%;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-drillrow-meta { flex:1 1 auto; min-width:0; color:var(--muted); font-size:var(--fs-2);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-drillrow .pf-pill { flex:0 0 auto; margin-left:auto; }

/* Traces tab toolbar: one aligned control row, then the status chips on their
   own line - no more chip/button soup wrapping mid-row. */
.pf-toolbar { display:flex; align-items:center; gap:var(--sp-4); margin-bottom:.6rem; }
.pf-toolbar .pf-search { flex:1 1 auto; min-width:0; max-width:420px; }
.pf-toolbar .pf-viewtog { margin-left:auto; }
.pf-stagechips { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin-bottom:.5rem; }
/* export confirm modal */
.pf-exportmodal { width:min(480px,94vw); }
.pf-export-opt { display:flex; align-items:flex-start; gap:var(--sp-5); border:1px solid var(--border); border-radius:10px;
  padding:.65rem .8rem; margin-bottom:.55rem; cursor:pointer; transition:border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease); }
.pf-export-opt:hover { border-color:var(--orange-line); }
.pf-export-opt.on { border-color:var(--orange); background:var(--orange-soft); }
.pf-export-opt.off { opacity:.45; cursor:not-allowed; }
.pf-export-opt input { margin-top:.2rem; accent-color:var(--orange); }
.pf-export-opt span b { display:block; color:var(--text-strong); font-size:var(--fs-5); }
.pf-export-opt .pf-subtle { display:block; margin-top:.1rem; }
.pf-export-actions { display:flex; justify-content:flex-end; gap:var(--sp-4); margin-top:.4rem; }

/* dark mode: header controls carry Chainlabs ORANGE (the per-client accent
   stays everywhere else; Mally wants the header itself on-brand in dark). */
:root[data-theme="dark"] .pf-navlink:hover { color:var(--cl-orange); }
:root[data-theme="dark"] .pf-navlink.on { color:var(--cl-orange); background:rgba(255,147,38,.12);
  border-color:rgba(255,147,38,.35); box-shadow:inset 0 -2px 0 var(--cl-orange); }
:root[data-theme="dark"] .pf-hdr .btn-ghost:hover { color:var(--cl-orange); border-color:var(--cl-orange); }

/* inline traces under a request row (Traces tab): count chip + expandable sub-list */
.pf-trchip { display:inline-flex; align-items:center; gap:var(--sp-2); background:var(--orange-soft); border:1px solid var(--orange-line);
  color:var(--orange); border-radius:999px; padding:.12rem .55rem; font-size:var(--fs-1); font-weight:700; font-family:var(--mono);
  cursor:pointer; transition:background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease); }
.pf-trchip:hover { transform:translateY(-1px); }
.pf-trchip.on { background:var(--orange); border-color:transparent; color:#fff; }
.pf-trzero { font-family:var(--mono); }
.pf-tr-open { background:var(--bg-section); }
@keyframes subExpand { from { opacity:0; transform:translateY(-4px); } }
.pf-subtraces { border-bottom:1px solid var(--divider); background:var(--bg-section); padding:.45rem .9rem .55rem 1.6rem;
  animation:subExpand var(--t-fast) var(--ease) both; cursor:default; }
.pf-strow { display:grid; grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr) minmax(0,.8fr) minmax(0,.9fr) minmax(0,1.6fr) minmax(0,.9fr);
  gap:var(--sp-6); align-items:center; padding:.32rem 0; border-bottom:1px dashed var(--divider); font-size:var(--fs-2); }
.pf-strowwrap { border-bottom:1px dashed var(--divider); padding:.32rem 0; }
.pf-strowwrap:last-of-type { border-bottom:none; }
.pf-strowwrap .pf-strow { border-bottom:none; padding:0; }
.pf-st-meta { display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-4); margin-top:.28rem; font-size:var(--fs-1); }
.pf-st-fee { font-family:var(--mono); color:var(--muted); }
.pf-chip-mini2 { font-size:var(--fs-1); padding:.05rem .35rem; }
.pf-strow:last-of-type { border-bottom:none; }
.pf-st-tok { font-family:var(--mono); font-weight:700; color:var(--text-strong); }
.pf-st-type, .pf-st-date { color:var(--muted); }
.pf-st-amt { font-family:var(--mono); color:var(--text); }
.pf-st-status { display:inline-flex; align-items:center; gap:var(--sp-3); color:var(--text); min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-st-dot { width:9px; height:9px; border-radius:3px; flex:0 0 auto; }
.pf-st-links { display:flex; gap:var(--sp-6); justify-content:flex-end; }
.pf-st-links a { color:var(--orange); font-weight:600; }
.pf-st-open { display:block; margin:.45rem 0 0 auto; background:none; border:none; color:var(--orange);
  font-weight:600; font-size:var(--fs-2); cursor:pointer; font-family:var(--sans); }
.pf-st-open:hover { text-decoration:underline; }
@media (max-width:760px) { .pf-strow { grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr); } }

/* donut de-squeeze inside report cards: ring centred on top, breakdown list full-width below */
.pf-chartcard .donut-wrap { flex-direction:column; align-items:center; gap:var(--sp-5); }
.pf-chartcard .donut-wrap .donut-leg { width:100%; }

/* category multi-select dropdown (filter control) */
.pf-multi { position:relative; }
.pf-multi-sum { display:inline-flex; align-items:center; gap:var(--sp-3); cursor:pointer; list-style:none; user-select:none;
  background:var(--card); border:1px solid var(--border); color:var(--text); height:34px; padding:.3rem .6rem;
  border-radius:8px; font-size:var(--fs-3); white-space:nowrap; max-width:200px; }
.pf-multi-sum::-webkit-details-marker { display:none; }
.pf-multi-sum::after { content:'▾'; color:var(--muted); font-size:var(--fs-1); margin-left:.1rem; }
.pf-multi[open] .pf-multi-sum { border-color:var(--orange-line); color:var(--orange); }
.pf-multi-pop { position:absolute; z-index:30; top:calc(100% + 4px); left:0; min-width:240px; max-height:300px; overflow:auto;
  background:var(--card); border:1px solid var(--border); border-radius:10px; box-shadow:var(--shadow-md); padding:.35rem; }
.pf-multi-opt { display:flex; align-items:center; gap:var(--sp-4); padding:.34rem .45rem; border-radius:7px; font-size:var(--fs-3);
  color:var(--text); cursor:pointer; }
.pf-multi-opt:hover { background:var(--bg-section); }
.pf-multi-opt input { accent-color:var(--orange); }
.pf-multi-clear { display:block; width:100%; text-align:left; background:none; border:none; border-bottom:1px solid var(--divider);
  color:var(--orange); font-weight:600; font-size:var(--fs-2); padding:.3rem .45rem .4rem; cursor:pointer; margin-bottom:.2rem; }

/* ═══ dynamic + glossy polish (one motion language: --ease, fast/slow) ═══ */
.pf-hdr { background:var(--header-bg); -webkit-backdrop-filter:saturate(1.1) blur(12px); backdrop-filter:saturate(1.1) blur(12px);
  border-bottom:1px solid transparent; box-shadow:inset 0 -1px 0 var(--border); }
/* cards: sheen overlay + hover lift. overflow:hidden only on KPI cards (panels
   hold line charts that draw a few px outside their box via overflow:visible). */
.pf-kpi { overflow:hidden; }
.pf-kpi, .pf-panel { position:relative;
  transition:transform var(--t-slow) var(--ease), box-shadow var(--t-slow) var(--ease), border-color var(--t-fast) var(--ease); }
.pf-kpi::before, .pf-panel::before { content:""; position:absolute; inset:0; background:var(--sheen); pointer-events:none; border-radius:inherit; }
.pf-kpi:hover, .pf-panel:hover { transform:translateY(-2px); box-shadow:var(--shadow-lift); border-color:var(--border-strong); }
.pf-kpi.accent::after, .pf-kpi.good::after { content:""; position:absolute; inset:0; pointer-events:none; opacity:.55; }
.pf-kpi.accent::after { background:var(--tint-accent); }
.pf-kpi.good::after { background:var(--tint-good); }
.pf-kpi > *, .pf-panel > * { position:relative; z-index:1; }
/* donut ring draw-in (staggered per segment via --seg-delay) */
@keyframes donutDraw { from { stroke-dasharray:0 9999; } }
.donut circle { animation:donutDraw var(--t-slow) var(--ease) both; animation-delay:var(--seg-delay,0ms); }
/* bars: subtle gloss overlay (per-status/inline colour still shows) + hover */
.pf-fill { background-image:linear-gradient(180deg,rgba(255,255,255,.22),rgba(255,255,255,0));
  transition:width var(--t-slow) var(--ease), filter var(--t-fast) var(--ease); }
.pf-loadrow-click:hover .pf-fill { filter:brightness(1.06) saturate(1.05); }
/* primary button / segmented / nav active gloss - derived from the CLIENT accent (--orange) */
.btn { position:relative; overflow:hidden; transition:transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease), filter var(--t-fast) var(--ease); }
.btn::before { content:""; position:absolute; inset:0; background:linear-gradient(180deg,rgba(255,255,255,.25),rgba(255,255,255,0) 55%); pointer-events:none; }
.btn:hover { filter:brightness(1.05); box-shadow:0 4px 14px var(--ring); transform:translateY(-1px); }
.btn:active { transform:translateY(0); }
.pf-seg-b { transition:background var(--t-fast) var(--ease), color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease); }
.pf-seg-b.on { background:linear-gradient(180deg,var(--card),var(--card2)); box-shadow:var(--shadow-sm), inset 0 0 0 1px var(--border); }
.pf-navlink.on { box-shadow:inset 0 -2px 0 var(--orange); }
.pf-chartcard { transition:transform var(--t-slow) var(--ease), box-shadow var(--t-slow) var(--ease); }
.pf-chartcard:hover { transform:translateY(-2px); box-shadow:var(--shadow-lift); }
/* modal pop + overlay blur */
@keyframes modalPop { from { opacity:0; transform:translateY(8px) scale(.97); } }
@keyframes overlayIn { from { opacity:0; } }
.pf-guide-overlay { -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px); animation:overlayIn var(--t-fast) var(--ease) both; }
.pf-guide { animation:modalPop var(--t-slow) var(--ease) both; transform-origin:center 40%; }
@media (prefers-reduced-motion:reduce) {
  .pf-kpi:hover, .pf-panel:hover, .pf-chartcard:hover, .btn:hover { transform:none !important; }
  .donut circle { animation:none !important; }
  .pf-guide, .pf-guide-overlay { animation:none !important; }
}

/* portal grid breakpoints - 6/3/2 and 3/2/1 always divide evenly (no orphans) */
@media (max-width:1080px) {
  .pf-kpis { grid-template-columns:repeat(3,minmax(0,1fr)); }
  .pf-kpis.cols-4 { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .pf-reportgrid, .pf-topgrid { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:760px) {
  .pf-kpis, .pf-kpis.cols-4 { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .pf-reportgrid, .pf-topgrid, .pf-loadgrid { grid-template-columns:1fr; }
  .pf-controls-sync { margin-left:0; }
}
@media (max-width:640px) {
  .pf-form-grid, .pf-grid-2 { grid-template-columns:1fr; }
  .pf-overview-h { flex-direction:column; gap:var(--sp-5); }
  .pf-hdr-row { flex-wrap:wrap; min-height:0; gap:var(--sp-5) .9rem; }
  .pf-brand { margin-right:0; flex:1 1 100%; }
}

/* ---- Portal line chart (intake-vs-completion, hours-by-month) ---- */
.pf-linechart { margin:.4rem 0 .2rem; }
.pf-line-svg { width:100%; height:150px; display:block; overflow:visible; }
.pf-line-x { display:flex; margin-top:.25rem; }
.pf-line-x span { flex:1 1 0; text-align:center; font-size:var(--fs-1); color:var(--muted); white-space:nowrap; overflow:hidden; }

/* ---- Portal onboarding / help guide ---- */
.pf-guidewrap { display:inline-flex; }
.pf-guidebtn { font-size:var(--fs-1); font-weight:600; }
.pf-guide-overlay { position:fixed; inset:0; z-index:1000; background:rgba(8,12,20,.55);
  display:flex; align-items:center; justify-content:center; padding:1.2rem; overflow:auto; }
.pf-guide { background:var(--card); border:1px solid var(--border); border-radius:14px;
  box-shadow:var(--shadow-lg); max-width:560px; width:100%; max-height:86vh; overflow:auto;
  margin:auto; /* safe-centre: a card taller than the viewport scrolls instead of clipping its top */ }
.pf-guide-h { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4);
  padding:1rem 1.2rem; border-bottom:1px solid var(--border); position:sticky; top:0; background:var(--card); }
.pf-guide-h h2 { margin:0; font-size:var(--fs-8); font-weight:700; color:var(--text-strong); }
.pf-guide-body { padding:1rem 1.2rem; font-size:var(--fs-4); line-height:1.55; color:var(--text); }
.pf-guide-body ul { margin:.4rem 0 .8rem; padding-left:1.1rem; }
.pf-guide-body li { margin:.3rem 0; }
.pf-guide-sub { font-weight:700; color:var(--text-strong); margin:.6rem 0 .2rem; }
.pf-guide-stat { list-style:none; padding-left:0; }
.pf-guide-stat li { display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap; }
.pf-guide-foot { color:var(--muted); font-size:var(--fs-3); margin-top:.6rem; }
.pf-guide-actions { padding:.8rem 1.2rem 1.1rem; display:flex; justify-content:flex-end; }
.pf-btn { appearance:none; border:none; cursor:pointer; font:inherit; font-size:var(--fs-4); font-weight:600;
  color:#fff; background:var(--accent); border-radius:9px; padding:.55rem 1.3rem; }
.pf-btn:hover { filter:brightness(1.04); }

/* ---- Portal in-app @mentions ---- */
.pf-mention { color:var(--accent); font-weight:600; background:var(--orange-soft);
  border-radius:5px; padding:0 3px; }
.pf-mention-known { box-shadow:inset 0 -2px 0 var(--accent); }
.pf-mention-hint { margin-top:.35rem; }
/* @-tag autocomplete popup */
.pf-noteadd-field { position:relative; flex:1; display:flex; }
.pf-noteadd-field textarea { flex:1; }
.pf-mention-pop { position:absolute; bottom:calc(100% + 4px); left:0; z-index:30; min-width:220px; max-width:320px;
  background:var(--card); border:1px solid var(--border); border-radius:var(--r); box-shadow:var(--shadow-md);
  overflow:hidden; display:flex; flex-direction:column; }
.pf-mention-opt { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); width:100%;
  background:none; border:0; text-align:left; padding:.45rem .6rem; cursor:pointer; font-size:var(--fs-3); color:var(--text-strong); }
.pf-mention-opt:hover { background:var(--bg-section); }
.pf-mention-opt-name { font-weight:600; }
.pf-mention-opt-role { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.03em; color:var(--muted); }
.pf-mention-opt-role.staff { color:#fff; background:var(--cl-orange); border-radius:3px; padding:.05rem .3rem; }
/* message reactions */
.pf-react-bar { display:flex; align-items:center; gap:var(--sp-2); margin-top:.35rem; flex-wrap:wrap; }
.pf-react { font-size:var(--fs-1); line-height:1; padding:.15rem .35rem; border:1px solid var(--border); border-radius:10px;
  background:var(--bg-section); cursor:pointer; color:var(--text-strong); }
.pf-react.mine { border-color:var(--orange); background:var(--orange-soft); }
.pf-react-add { display:inline-flex; gap:var(--sp-1); opacity:0; transition:opacity .12s; }
.pf-note:hover .pf-react-add { opacity:.7; }
.pf-react-add:hover { opacity:1; }
.pf-react-opt { font-size:var(--fs-3); line-height:1; background:none; border:0; cursor:pointer; padding:.1rem .15rem; border-radius:6px; }
.pf-react-opt:hover { background:var(--bg-section); }
/* message edit/delete controls */
.pf-note-act { margin-left:auto; display:inline-flex; gap:var(--sp-1); opacity:0; transition:opacity .12s; }
.pf-note:hover .pf-note-act { opacity:.65; }
.pf-note-act:hover { opacity:1; }
.pf-note-actbtn { background:none; border:0; cursor:pointer; font-size:var(--fs-1); padding:.05rem .2rem; border-radius:5px; color:var(--muted); }
.pf-note-actbtn:hover { background:var(--bg-section); color:var(--text-strong); }
.pf-note-edit { display:flex; flex-direction:column; gap:var(--sp-3); }
.pf-note-edit textarea { width:100%; resize:vertical; }
.pf-note-edit-act { display:flex; gap:var(--sp-3); }
/* staff entity delete (two-step confirm) */
.pf-del-entity.armed { background:var(--red); border-color:var(--red); color:#fff; }
.pf-del-entity.armed:hover { filter:brightness(.9); }

/* ---- Notification bell (header) ---- */
.notif-bell { position:relative; }
.notif-bell.alert { border-color:var(--red); color:var(--red); background:var(--red-soft); }
.notif-badge { display:inline-grid; place-items:center; min-width:16px; height:16px; padding:0 4px; margin-left:.25rem;
  border-radius:8px; background:var(--red); color:#fff; font-size:var(--fs-1); font-weight:700; line-height:1; }

/* ---- In-place inbox dropdown (the 🔔 bell) ---- */
.nbell { position:relative; display:inline-flex; }
.nbell-menu { position:absolute; top:calc(100% + 6px); right:0; z-index:70; width:340px; max-width:92vw;
  background:var(--card); border:1px solid var(--border); border-radius:12px;
  box-shadow:0 10px 30px rgba(0,0,0,.16); overflow:hidden; }
.nbell-hd { display:flex; align-items:center; gap:var(--sp-4); padding:.6rem .75rem; border-bottom:1px solid var(--border); }
.nbell-hd b { font-size:var(--fs-5); }
.nbell-count { font-size:var(--fs-1); color:var(--muted); }
.nbell-markall { margin-left:auto; background:none; border:none; cursor:pointer; font:inherit; font-size:var(--fs-1);
  font-weight:600; color:var(--orange); padding:.2rem .4rem; border-radius:6px; }
.nbell-markall:hover { background:var(--orange-soft); }
.nbell-list { max-height:60vh; overflow-y:auto; padding:.25rem; }
.nbell-row { display:flex; align-items:flex-start; gap:var(--sp-4); padding:.5rem; border-radius:8px; }
.nbell-row + .nbell-row { border-top:1px solid var(--border); }
.nbell-row.clickable { cursor:pointer; }
.nbell-row.clickable:hover { background:var(--bg-section); }
/* 2026-09-16: unsaved edits are an alert; they sit first in the bell's inbox. */
.nbell-row.ma-pending { background:var(--red-soft); }
.nbell-row.ma-pending .nbell-ic { color:var(--red); }
.nbell-ic { font-size:var(--fs-7); line-height:1.2; flex-shrink:0; }
.nbell-txt { flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; }
.nbell-txt b { font-size:var(--fs-3); color:var(--text-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.nbell-sub { font-size:var(--fs-1); color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.nbell-time { flex-shrink:0; font-size:var(--fs-1); color:var(--muted); white-space:nowrap; margin-top:1px; }
.nbell-x { flex-shrink:0; background:none; border:1px solid var(--border); cursor:pointer; color:var(--muted);
  font-size:var(--fs-1); line-height:1; padding:.2rem .4rem; border-radius:6px; }
.nbell-x:hover { border-color:var(--green-line); color:var(--green); background:var(--green-soft); }
.nbell-empty { padding:1.3rem .75rem; text-align:center; font-size:var(--fs-3); color:var(--muted); }
.nbell-more { padding:.5rem; text-align:center; font-size:var(--fs-1); color:var(--muted); }
.nbell-foot { display:block; width:100%; text-align:left; background:none; border:none; border-top:1px solid var(--border);
  cursor:pointer; font:inherit; font-size:var(--fs-2); font-weight:600; color:var(--orange); padding:.6rem .75rem; }
.nbell-foot:hover { background:var(--orange-soft); }

/* ---- Status timeline (case drawer) ---- */
.pf-timeline { margin-top:.75rem; padding-top:.6rem; border-top:1px solid var(--border); }
.pf-tl-row { display:flex; align-items:baseline; gap:var(--sp-4); padding:.25rem 0; font-size:var(--fs-3); line-height:1.4; }
.pf-tl-dot { flex-shrink:0; width:7px; height:7px; border-radius:50%; background:var(--orange); margin-bottom:1px; }
.pf-tl-label { flex:1; color:var(--text-strong); }
.pf-tl-date { flex-shrink:0; color:var(--muted); white-space:nowrap; }

/* ---- Admin collapsible sections ---- */
.afold { border-top:1px solid var(--border); margin-top:.4rem; }
.afold-h { display:flex; align-items:center; gap:var(--sp-3); }
.afold-caret { color:var(--muted); font-size:var(--fs-3); width:1rem; display:inline-block; }
.afold-body { padding-top:.2rem; }

/* ---- Per-trace QC status chip (client-safe engine verdict) ---- */
.pf-qc { display:inline-flex; align-items:center; gap:.25em; font-size:var(--fs-1); font-weight:600;
  padding:.1em .5em; border-radius:999px; border:1px solid transparent; white-space:nowrap; line-height:1.5; }
.pf-qc-ok { background:var(--green-soft); border-color:var(--green-line); color:var(--green); }
.pf-qc-review { background:var(--amber-soft); border-color:var(--amber-line); color:var(--amber); }
.pf-qc-pending { background:var(--bg-section); border-color:var(--border); color:var(--muted); }

/* ---- Timeline: trace-edit events (vs status changes) ---- */
.pf-tl-edit .pf-tl-dot { color:var(--cl-orange); font-size:var(--fs-1); line-height:1; background:none; }
.pf-tl-edit .pf-tl-label { color:var(--text); }


/* ── Dark-mode button ink (ops console) ──────────────────────────────────────
   Decision 2026-07-09: in dark theme the bright Chainlabs orange (#FF9326)
   fails contrast with white text (~2.2:1), so orange-filled controls switch to
   dark ink. Scoped to the ops console (body:not(.portal)) - client portals keep
   white ink because their accents are darker brand colours (e.g. Chainalysis
   blue) where white still reads best. */
:root[data-theme="dark"] body:not(.portal) .btn,
:root[data-theme="dark"] body:not(.portal) .ai-fab,
:root[data-theme="dark"] body:not(.portal) .auth-primary,
:root[data-theme="dark"] body:not(.portal) .mfa-btn,
:root[data-theme="dark"] body:not(.portal) .idle-lock-btn,
:root[data-theme="dark"] body:not(.portal) .cfdd-count,
:root[data-theme="dark"] body:not(.portal) .ai-msg.user .ai-bubble { color:#16191F; }
/* Console design pass (PR 1): 7 more orange-filled controls the correction
   above missed - still white-on-bright-orange in dark mode. */
:root[data-theme="dark"] body:not(.portal) .cdb-chip.active,
:root[data-theme="dark"] body:not(.portal) .cdb-chip.active .cdb-chip-n,
:root[data-theme="dark"] body:not(.portal) .pf-trchip.on,
:root[data-theme="dark"] body:not(.portal) .qc-run-btn:hover:not(:disabled),
:root[data-theme="dark"] body:not(.portal) .qc-ok-btn:hover:not(:disabled),
:root[data-theme="dark"] body:not(.portal) .pf-stream-b.on,
:root[data-theme="dark"] body:not(.portal) .pf-note-role,
:root[data-theme="dark"] body:not(.portal) .pf-mention-opt-role.staff { color:#16191F; }

/* --- Country distribution board (EntityDistributionView, updated 2026-07-17 11:05:
   feel pass - entrance motion + reduced-motion guard, concentric radius, tactile
   press on the block button, tabular col counts) --- */
@keyframes cdb-enter { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }
.cdb { background:var(--bg-section); border:1px solid var(--border); border-radius:var(--rl); padding:0.85rem; margin-bottom:1rem; animation:cdb-enter .22s ease-out; }
@media (prefers-reduced-motion: reduce) { .cdb { animation:none; } }
.cdb-head { display:flex; flex-direction:column; gap:0.15rem; margin-bottom:0.7rem; }
.cdb-head span { text-wrap:pretty; }
.cdb-empty { text-wrap:pretty; }
.cdb-col-h { text-wrap:balance; }
.cdb-countries { display:flex; flex-wrap:wrap; gap:0.4rem; margin-bottom:0.85rem; max-height:132px; overflow:auto; padding-bottom:0.15rem; }
.cdb-chip { display:inline-flex; align-items:center; gap:0.4rem; min-height:34px; padding:5px 11px; border:1px solid var(--border-strong); border-radius:999px; background:var(--card); color:var(--text); font-size:0.82rem; cursor:pointer; transition-property:background-color,border-color,color,transform; transition-duration:.12s; transition-timing-function:ease-out; }
.cdb-chip:hover { border-color:var(--orange-line); }
.cdb-chip:active { transform:scale(0.97); }
.cdb-chip:focus-visible { outline:2px solid var(--orange); outline-offset:2px; }
.cdb-chip.active { background:var(--orange); border-color:var(--orange); color:#fff; }
.cdb-chip.notracer { border-color:var(--amber-line); background:var(--amber-soft); }
.cdb-chip.notracer.active { background:var(--orange); border-color:var(--orange); color:#fff; }
.cdb-chip-n { min-width:18px; text-align:center; font-weight:700; font-size:0.72rem; font-variant-numeric:tabular-nums; padding:1px 6px; border-radius:999px; background:var(--bg-section); color:var(--text-strong); }
.cdb-chip.active .cdb-chip-n { background:rgba(255,255,255,0.25); color:#fff; }
.cdb-chip-warn { color:var(--amber); }
.cdb-grid { display:grid; grid-template-columns:1fr 1fr; gap:0.85rem; align-items:start; }
@media (max-width:720px) { .cdb-grid { grid-template-columns:1fr; } }
/* Concentric radius: col (outer) uses --rl so the --r cards nest coherently. */
.cdb-col { background:var(--card); border:1px solid var(--border); border-radius:var(--rl); padding:0.55rem 0.6rem; min-height:120px; }
.cdb-col-h { font-size:0.82rem; font-weight:700; color:var(--text-strong); margin-bottom:0.35rem; font-variant-numeric:tabular-nums; }
.cdb-drop-hint { font-size:0.72rem; margin-bottom:0.5rem; }
.cdb-empty { font-size:0.82rem; color:var(--muted); padding:0.9rem 0.4rem; text-align:center; }
.cdb-empty.cdb-notracer { color:var(--amber); background:var(--amber-soft); border:1px dashed var(--amber-line); border-radius:var(--r); }
.cdb-ecard { display:flex; align-items:center; justify-content:space-between; gap:0.5rem; padding:0.5rem 0.6rem; border:1px solid var(--border); border-radius:var(--r); background:var(--bg-section); margin-bottom:0.4rem; cursor:grab; transition-property:border-color,box-shadow,opacity; transition-duration:.12s; transition-timing-function:ease-out; }
.cdb-ecard:hover { border-color:var(--orange-line); box-shadow:0 1px 4px rgba(0,0,0,0.06); }
.cdb-ecard:focus-visible { outline:2px solid var(--orange); outline-offset:2px; }
.cdb-ecard.dragging { opacity:0.45; cursor:grabbing; }
.cdb-ecard.busy { opacity:0.7; cursor:default; }
.cdb-busy-tag { flex:0 0 auto; display:inline-flex; align-items:center; gap:0.4rem; font-size:0.75rem; color:var(--orange); }
.cdb-spin { width:13px; height:13px; border:2px solid var(--border); border-top-color:var(--orange); border-radius:50%; animation:mfaspin .7s linear infinite; }
.cdb-ecard-main { min-width:0; flex:1 1 auto; }
.cdb-ecard-name { font-size:0.85rem; font-weight:600; color:var(--text-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cdb-ecard-meta { display:flex; align-items:center; gap:0.4rem; margin-top:0.15rem; }
.cdb-ecard-url { font-size:0.72rem; color:var(--muted); text-decoration:none; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cdb-ecard-url:hover { color:var(--orange); text-decoration:underline; }
.cdb-ecard-actions { flex:0 0 auto; display:flex; align-items:center; gap:0.35rem; }
.cdb-assign-sel { font-size:0.72rem; padding:4px 6px; min-height:32px; border:1px solid var(--border-strong); border-radius:6px; background:var(--card); color:var(--text); cursor:pointer; max-width:130px; }
.cdb-assign-sel:focus-visible { outline:2px solid var(--orange); outline-offset:1px; }
.cdb-block-btn { flex:0 0 auto; min-height:32px; font-size:0.72rem; padding:3px 8px; border:1px solid var(--red-line); border-radius:6px; background:var(--red-soft); color:var(--red); cursor:pointer; transition-property:background-color,color,border-color; transition-duration:.12s; transition-timing-function:ease-out; }
.cdb-block-btn:hover:not(:disabled) { background:var(--red); color:#fff; border-color:var(--red); }
.cdb-block-btn:active:not(:disabled) { transform:scale(0.97); }
.cdb-block-btn:focus-visible { outline:2px solid var(--red); outline-offset:1px; }
.cdb-block-btn:disabled { opacity:0.5; cursor:default; }
.cdb-tzone { display:flex; align-items:center; justify-content:space-between; gap:0.5rem; padding:0.55rem 0.65rem; border:1.5px dashed var(--border-strong); border-radius:var(--r); background:var(--bg-section); margin-bottom:0.4rem; transition-property:border-color,background-color,box-shadow; transition-duration:.12s; transition-timing-function:ease-out; }
.cdb-tzone.under { border-color:var(--green-line); }
.cdb-tzone.full { opacity:0.6; cursor:not-allowed; }
.cdb-tzone.over { border-style:solid; border-color:var(--orange); background:var(--orange-soft); box-shadow:0 0 0 2px var(--orange-line) inset; }
.cdb-tzone-main { flex:1 1 auto; min-width:0; }
.cdb-tzone-name { font-size:0.85rem; font-weight:600; color:var(--text-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cdb-tzone-load { display:flex; align-items:center; gap:0.45rem; margin-top:0.25rem; font-size:0.72rem; font-variant-numeric:tabular-nums; }
.cdb-load-bar { flex:1 1 auto; height:5px; background:var(--border); border-radius:3px; overflow:hidden; max-width:120px; }
.cdb-load-fill { height:100%; background:var(--orange); border-radius:3px; }
.cdb-tzone.under .cdb-load-fill { background:var(--green); }
.cdb-tzone-tag { flex:0 0 auto; font-size:0.68rem; font-weight:700; padding:2px 7px; border-radius:999px; text-transform:uppercase; letter-spacing:0.03em; }
.cdb-tzone-tag.under { background:var(--green-soft); color:var(--green); }
.cdb-tzone-tag.full { background:var(--red-soft); color:var(--red); }

/* ─── Console phone layout (full-stack): stack the kanban, collapse the nav to a
   native section dropdown, and turn data tables into stacked card rows. Console-only
   (internal); the client portal has its own responsive rules. Placed last so it
   overrides the base .board/.col/table.dt/.topnav rules when the media query matches. ─── */
.topnav-mobile { display:none; }  /* appears only on phones (see the media block) */
@media (max-width:640px) {
  /* Nav: hide the scrolling tab row, show a native section dropdown instead */
  .topnav-inner { display:none; }
  .topnav-mobile { display:block; width:100%; background:var(--card); color:var(--text-strong);
    border:1px solid var(--border); border-radius:8px; padding:.5rem .6rem;
    font-size:var(--fs-3); font-family:var(--sans); font-weight:600; cursor:pointer; }
  /* Kanban: columns stack vertically, each full width */
  .board { flex-direction:column; overflow-x:visible; gap:var(--sp-5); }
  .board .col, .board-swim .col { flex:1 1 auto; width:100%; max-height:none; }
  .col-body { max-height:none; }
  /* Data tables become stacked card rows (label + value per line) */
  .tablewrap { overflow-x:visible; }
  table.dt, table.dt tbody { display:block; width:100%; }
  table.dt thead { display:none; }
  table.dt tr.filt-row { display:none; }
  /* Sheets mode is a DESKTOP layout: on a phone table.dt becomes stacked
     cards, so a fixed row height and nowrap would clip every card. */
  body:not(.portal) table.dt.sheet { table-layout:auto; }
  body:not(.portal) table.dt.sheet td { height:auto; white-space:normal; padding:.45rem .6rem; }
  table.dt tr { display:block; background:var(--card); border:1px solid var(--border);
    border-radius:var(--r); margin-bottom:var(--sp-4); padding:.15rem var(--sp-4); }
  table.dt td { display:flex; justify-content:space-between; align-items:baseline; gap:var(--sp-4);
    text-align:right; padding:.4rem 0; border-bottom:1px solid var(--divider); }
  table.dt tr td:last-child { border-bottom:none; }
  table.dt td::before { content:attr(data-label); text-align:left; font-weight:600;
    color:var(--muted); white-space:nowrap; }
  table.dt td:empty { display:none; }
}

/* ─── UX design pass PR 2 (sidebar-nav, plan sunny-munching-pascal): the flat
   horizontal nav wrapped inside .app-hdr on narrower widths, opening a
   see-through slit between the header and the sticky toolbar and (on some
   widths) sliding the toolbar underneath the wrapped row. D3 moves navigation
   into a left sidebar instead - the header becomes one row that never wraps,
   and .toolbar's sticky offset locks to the real header height (--hdr-h). ─── */
/* :has() gates this to index.html specifically - entitydist.html shares this
   stylesheet and also has #app at its root, but with no .sidenav child (it
   kept its old horizontal-nav layout in this PR), so it must not become a
   flex container or its lone .shell child's sizing changes. */
body:not(.portal) #app:has(> .sidenav) { display:flex; align-items:flex-start; }
.sidenav { flex:0 0 220px; width:220px; height:100vh; position:sticky; top:0;
  display:flex; flex-direction:column; background:var(--bg-section);
  border-right:1px solid var(--border); overflow-y:auto; overflow-x:hidden; z-index:30;
  transition:flex-basis var(--t-fast) var(--ease), width var(--t-fast) var(--ease); }
.sidenav .topnav-inner { display:flex; flex-direction:column; gap:var(--sp-2);
  padding:var(--sp-6) var(--sp-4); flex:1 1 auto; }
.sidenav .navlink { display:flex; align-items:center; gap:var(--sp-4); width:100%;
  min-height:var(--ctl-h); padding:0 var(--sp-4); border-radius:var(--r-ctl);
  border-left:2px solid transparent; border-bottom:none; text-align:left; white-space:nowrap; }
.sidenav .navlink:hover { background:var(--card); color:var(--text-strong); }
.sidenav .navlink.on { background:var(--orange-soft); color:var(--orange);
  border-left-color:var(--orange); }
/* The horizontal-nav "polish pass" layer draws an ::after underline bar
   sized for a pill-shaped tab - wrong shape entirely for a stacked sidebar
   row, where the left border above is the active indicator instead. */
.sidenav .navlink.on::after { display:none; }
.sidenav .navlink .ic { flex:0 0 auto; }
.sidenav .navlink-t { overflow:hidden; text-overflow:ellipsis; }
.sidenav-foot { flex:0 0 auto; display:flex; flex-direction:column; gap:1px;
  padding:var(--sp-4); border-top:1px solid var(--border); }
.sidenav .tabcustomize { position:relative; width:100%; }
.sidenav .tabmenu { left:0; right:auto; bottom:100%; top:auto; margin:0 0 .3rem; }
.sidenav .navcollapse .ic { transition:transform var(--t-fast) var(--ease); }
/* Collapsed rail (D3): icons only, 56px. Pre-stamped on the root by
   index.html's theme-bootstrap script before paint, so there is no flash of
   the wide sidebar on load. */
html[data-nav="collapsed"] .sidenav { flex-basis:56px; width:56px; }
html[data-nav="collapsed"] .sidenav .navlink-t { display:none; }
html[data-nav="collapsed"] .sidenav .navlink { justify-content:center; padding:0; }
html[data-nav="collapsed"] .sidenav .navcollapse .ic { transform:rotate(180deg); }
html[data-nav="collapsed"] .sidenav .tabmenu { left:100%; margin-left:.4rem; }

/* Header/toolbar seam fix: with nav out of .app-hdr, the header is a single
   row that never wraps, so its height is now a real constant (--hdr-h) - the
   toolbar's sticky offset locks to it instead of the old hardcoded 60px,
   which used to leave a 4px see-through slit and, between ~1100-640px, let
   the toolbar slide underneath the header once it wrapped. */
body:not(.portal) .app-hdr { flex-wrap:nowrap; min-height:var(--hdr-h); }
body:not(.portal) .toolbar { top:var(--hdr-h); }

@media (max-width:640px) {
  /* Phone: sidebar collapses to a static full-width strip; the nav-group
     rows and collapse control hide in favour of the existing .topnav-mobile
     dropdown (still rendered inside the same slot, just hidden by CSS
     above this breakpoint). */
  body:not(.portal) #app { display:block; }
  .sidenav { position:static; width:100%; height:auto; flex-basis:auto;
    border-right:none; border-bottom:1px solid var(--border); }
  .sidenav .topnav-inner { display:none; }
  .sidenav-foot { display:none; }
}

/* UX design pass PR 3 (screen-fit): the console had only 3 breakpoints above
   640px (the client portal has 7). These narrow the kanban column floor and
   the shell gutter progressively as the viewport shrinks, so a 1280px
   laptop still shows real columns instead of one giant one. */
@media (max-width:1440px) {
  body:not(.portal) .board:not(.board-swim) .col { min-width:232px; }
}
@media (max-width:1280px) {
  body:not(.portal) .board:not(.board-swim) .col { min-width:220px; }
  body:not(.portal) .shell { padding:0 var(--sp-8) var(--sp-9); }
}
@media (max-width:1024px) {
  body:not(.portal) .board:not(.board-swim) .col { min-width:208px; }
  body:not(.portal) .mc { min-width:120px; }
}

/* UX design pass PR 3: PM chrome rhythm - the toolbar/subbar/sortbar/metrics/
   board stack used 5 different margin systems (a literal .85rem here, a
   unique 1rem inset there); one scale now, every gap named. .drawer-body's
   3rem bottom pad was a leftover clearance for the removed Ask-AI FAB. */
body:not(.portal) .toolbar { margin-bottom:var(--sp-4); }
body:not(.portal) .subbar, body:not(.portal) .tabs { margin:0 0 var(--sp-6); }
body:not(.portal) .pm-sortbar { padding:var(--sp-4) 0 var(--sp-2); }
body:not(.portal) .pm-filterbar { padding:0 0 var(--sp-6); }
body:not(.portal) .pm-metrics { margin:0 0 var(--sp-6); }
body:not(.portal) .metrics { margin:0 0 var(--sp-8); }
body:not(.portal) .drawer-body { padding-bottom:var(--sp-10); }
body:not(.portal) .rep-note { margin:var(--sp-2) 0 var(--sp-4); }

/* UX design pass PR 6 (controls-consolidation, plan sunny-munching-pascal):
   24+ button variants and 9 border radii across the console, hit areas
   13-27px below the toolbar's own 34px standard, .btn:hover defined 4x with
   conflicting results, 3 focus-ring colors (2 dead rules), ~25 interactive
   classes with no focus-visible at all, 7 transition durations. One spec
   each, appended (never deleting the existing conflicting rules - shared
   styles.css, portal safety): control height/radius/gap/transition, one
   hover, one disabled, one focus ring for every class the audit found
   uncovered. .btn/.btn-sec/.btn-ghost/.iconbtn/.ein are heavily used in the
   client portal (confirmed by grep), so every rule here is
   body:not(.portal)-scoped. */
body:not(.portal) :is(.btn, .btn-sec, .btn-ghost, .iconbtn) {
  min-height:var(--ctl-h); border-radius:var(--r-ctl); display:inline-flex;
  align-items:center; justify-content:center; gap:var(--sp-3);
  transition:filter var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
    background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
    box-shadow var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
body:not(.portal) .toolbar input[type="search"],
body:not(.portal) .toolbar select,
body:not(.portal) .ein { min-height:var(--ctl-h); }
body:not(.portal) :is(.btn, .btn-sec, .btn-ghost, .iconbtn):hover:not(:disabled) { filter:brightness(.95); }
body:not(.portal) :is(.btn, .btn-sec, .btn-ghost, .iconbtn):disabled { opacity:.55; cursor:default; }
body:not(.portal) :is(.x, .showmore, .chipbtn, .viewchip, .tab, .qc-run-btn, .qc-ok-btn,
  .miniassign, .cellin, .seg-i, .cfdd-btn, .cfdd-opt, .colfilt, .tabmenu-i, .admin-link,
  .gcard, .ptab, .navcollapse, .col-collapse, .col-rail, .drawer-hd-sel):focus-visible {
  outline:2px solid var(--orange); outline-offset:2px;
}

/* --- Distribution pace banner (EntityDistributionView, 2026-07-17) --- */
.dist-pace { display:flex; align-items:center; gap:0.7rem; flex-wrap:wrap; background:var(--green-soft); border:1px solid var(--green-line); border-radius:var(--r); padding:0.5rem 0.7rem; margin-bottom:0.75rem; font-size:0.82rem; font-variant-numeric:tabular-nums; }
.dist-pace.behind { background:var(--amber-soft); border-color:var(--amber-line); }
.dist-pace-goal { color:var(--text-strong); }
.dist-pace-goal b { font-size:0.95rem; }
.dist-pace-bar { flex:1 1 120px; min-width:100px; max-width:260px; height:6px; background:var(--border); border-radius:3px; overflow:hidden; }
.dist-pace-fill { height:100%; background:var(--green); border-radius:3px; }
.dist-pace.behind .dist-pace-fill { background:var(--amber); }
.dist-pace-tag { font-weight:600; color:var(--green); }
.dist-pace-tag.behind { color:var(--amber); }
.dist-pace-day { font-size:0.75rem; }

/* --- Per-country coverage panel (EntityDistributionView, 2026-07-17) --- */
.cvg { background:var(--bg-section); border:1px solid var(--border); border-radius:var(--rl); padding:0.85rem; margin-bottom:1rem; animation:cdb-enter .22s ease-out; }
@media (prefers-reduced-motion: reduce) { .cvg { animation:none; } }
.cvg-table { border:1px solid var(--border); border-radius:var(--r); overflow:hidden; }
.cvg-row { display:grid; grid-template-columns:1.4fr 1.6fr 0.6fr 1.8fr; gap:0.6rem; align-items:center; padding:0.4rem 0.65rem; font-size:0.82rem; font-variant-numeric:tabular-nums; border-top:1px solid var(--divider); }
.cvg-row:first-child { border-top:none; }
.cvg-head-row { font-size:0.72rem; font-weight:700; text-transform:uppercase; letter-spacing:0.03em; color:var(--muted); background:var(--card2); }
.cvg-row.red { background:var(--red-soft); }
.cvg-row.warn { background:var(--amber-soft); }
.cvg-country { font-weight:600; color:var(--text-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cvg-ent { display:flex; align-items:center; gap:0.5rem; }
.cvg-bar { flex:1 1 auto; height:6px; background:var(--border); border-radius:3px; overflow:hidden; max-width:140px; }
.cvg-fill { display:block; height:100%; background:var(--orange); border-radius:3px; }
.cvg-row.ok .cvg-fill { background:var(--green); }
.cvg-n { color:var(--muted); font-size:0.76rem; white-space:nowrap; }
.cvg-tr { text-align:center; font-weight:600; }
.cvg-status { font-size:0.78rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* Work-log "start tracking?" chip. Bottom-left, above nothing else, and it
   never traps focus - it appears while the operator is mid-edit, so it must be
   ignorable. Scoped body:not(.portal): the client portal has no timer. */
body:not(.portal) .wl-prompt {
  position:fixed; left:1rem; bottom:1rem; z-index:55;
  display:flex; align-items:center; gap:.5rem;
  padding:.5rem .6rem; border-radius:10px;
  background:var(--card); border:1px solid var(--orange-line);
  box-shadow:0 6px 20px rgba(0,0,0,.18); font-size:var(--fs-2);
}
body:not(.portal) .wl-prompt-txt { white-space:nowrap; }
body:not(.portal) .wl-prompt-go {
  border:none; border-radius:7px; padding:.25rem .6rem; cursor:pointer;
  background:var(--orange); color:#fff; font-weight:600; font:inherit;
  font-size:var(--fs-2);
}
body:not(.portal) .wl-prompt-x {
  border:none; background:none; color:var(--muted); cursor:pointer;
  font-size:1rem; line-height:1; padding:0 .2rem;
}
@media (prefers-reduced-motion: no-preference) {
  body:not(.portal) .wl-prompt { animation: secfade .18s var(--ease) backwards; }
}

/* Running-timer dock. Bottom-left, only while a timer runs. z-index sits BELOW
   .wl-prompt so the two can never fight for the corner - in practice they are
   mutually exclusive (the prompt suppresses itself when a timer is already
   running), and the ordering makes that safe rather than lucky. */
body:not(.portal) .wl-dock {
  position:fixed; left:1rem; bottom:1rem; z-index:54;
  display:inline-flex; align-items:center; gap:.55rem;
  padding:.4rem .5rem .4rem .7rem;
  border-radius:999px;
  background:var(--card); border:1px solid var(--orange-line);
  box-shadow:0 6px 18px rgba(0,0,0,.16);
}
/* The live signal. A number alone does not read as "running" at a glance. */
body:not(.portal) .wl-dock-dot {
  width:7px; height:7px; border-radius:50%; background:var(--orange); flex:0 0 auto;
  animation:wlPulse 2.4s ease-out infinite;
}
@keyframes wlPulse {
  0%   { box-shadow:0 0 0 0 var(--orange-soft); }
  70%  { box-shadow:0 0 0 7px transparent; }
  100% { box-shadow:0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  body:not(.portal) .wl-dock-dot { animation:none; }
}
body:not(.portal) .wl-dock-time {
  font-family:var(--mono); font-variant-numeric:tabular-nums;
  font-weight:700; font-size:.92rem; color:var(--text-strong);
}
body:not(.portal) .wl-dock-ctx {
  font-size:.78rem; color:var(--muted);
  max-width:9rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* No client picked yet - an open question, not a settled blank. */
body:not(.portal) .wl-dock-ctx.is-unset { color:var(--orange); font-weight:600; }
body:not(.portal) .wl-dock-btn {
  border:none; background:none; cursor:pointer; color:var(--muted);
  padding:.15rem .32rem; border-radius:6px; font:inherit; font-size:.8rem; line-height:1;
}
body:not(.portal) .wl-dock-btn:hover { background:var(--bg-section); color:var(--text); }
body:not(.portal) .wl-dock-btn:focus-visible { outline:2px solid var(--orange); outline-offset:1px; }
/* Narrow viewport: the client name goes first. The clock and the stop control
   are what the dock exists for. */
@media (max-width: 640px) {
  body:not(.portal) .wl-dock-ctx { display:none; }
}

/* Tracked-time row in the end-of-day work-log draft. */
body:not(.portal) .wl-tracked {
  display:flex; align-items:center; gap:.6rem; flex-wrap:wrap;
  padding:.45rem .6rem; margin-bottom:.6rem;
  border:1px solid var(--orange-line); border-radius:8px;
  background:var(--orange-soft); font-size:var(--fs-2);
}

/* Work-log timer widget. Scoped to the console; the client portal never
   renders it. Classes replace the inline styles the first version carried. */
body:not(.portal) .wl-timer { border:1px solid var(--border); border-radius:var(--r); padding:.75rem .9rem .65rem; margin-bottom:1rem; background:var(--card); }
body:not(.portal) .wl-timer.is-running { border-color:var(--accent); }
body:not(.portal) .wl-timer-head { display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; }
body:not(.portal) .wl-clock { font-family:var(--mono); font-size:2.1rem; line-height:1; color:var(--text-strong); font-variant-numeric:tabular-nums; letter-spacing:-.01em; }
body:not(.portal) .wl-clock-s { font-size:1.35rem; opacity:.55; }
body:not(.portal) .wl-timer-state { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.06em; color:var(--muted); }
body:not(.portal) .wl-timer.is-running .wl-timer-state { color:var(--accent); }
body:not(.portal) .wl-timer-actions { display:flex; align-items:center; gap:.5rem; margin-left:auto; flex-wrap:wrap; }
body:not(.portal) .wl-clear { background:none; border:0; padding:.2rem .35rem; font:inherit; font-size:var(--fs-3); color:var(--muted); cursor:pointer; text-decoration:underline; }
body:not(.portal) .wl-clear:hover { color:var(--text-strong); }
body:not(.portal) .wl-timer-ctx { display:flex; gap:.75rem; flex-wrap:wrap; margin-top:.6rem; padding-top:.6rem; border-top:1px solid var(--border); }
body:not(.portal) .wl-timer-ctx .fld { min-width:12rem; flex:1 1 12rem; }
body:not(.portal) .wl-timer-foot { font-size:var(--fs-2); color:var(--muted); margin-top:.5rem; }


/* ---- Reporting "Progress" section + presentation mode (plans/REPORT_TAB_PROGRESS.md) ----
   Console-only: every selector is body:not(.portal)-scoped or body.present
   (a class only app.js ever sets). The portal never reads these names. */
body:not(.portal) .prog-sect { margin-bottom:var(--sp-7); }
body:not(.portal) .prog-head { display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap; margin-bottom:.6rem; }
body:not(.portal) .prog-note { font-size:var(--fs-1); }
body:not(.portal) .prog-present { margin-left:auto; }
body:not(.portal) .prog-metrics { margin-bottom:var(--sp-5); }
body:not(.portal) .prog-delta { font-family:var(--mono); }
body:not(.portal) .prog-up { color:var(--green); }
body:not(.portal) .prog-down { color:var(--red); }
body:not(.portal) .prog-flat { color:var(--muted); }
body:not(.portal) .prog-trend { margin-bottom:var(--sp-5); }
body:not(.portal) .prog-table th, body:not(.portal) .prog-table td { white-space:nowrap; }
body.present { background:#FFFFFF; }
body.present .sidenav, body.present .app-hdr, body.present .toolbar, body.present .footer-note { display:none !important; }
body.present .shell { max-width:1120px; margin:0 auto; padding:1.2rem 1.5rem 2rem; }
body.present .present-actions { display:flex; gap:var(--sp-3); justify-content:flex-end; margin-bottom:.8rem; }
body.present .present-hdr { display:flex; align-items:flex-end; justify-content:space-between; gap:var(--sp-7); border-bottom:2px solid var(--cl-orange); padding-bottom:.7rem; margin-bottom:1rem; }
body.present .present-brand { display:flex; align-items:center; gap:.6rem; }
body.present .present-brand .logo { width:34px; height:34px; border-radius:8px; background:var(--cl-orange); color:#fff; display:inline-flex; align-items:center; justify-content:center; font-weight:700; font-size:1.2rem; }
body.present .present-name { font-weight:700; font-size:1.1rem; color:var(--text-strong); }
body.present .present-tag { font-size:var(--fs-2); color:var(--muted); }
body.present .present-title { font-weight:700; font-size:1.15rem; color:var(--text-strong); text-align:right; }
body.present .present-sub { font-size:var(--fs-2); color:var(--muted); text-align:right; }
body.present .present-internal { background:var(--red-soft); color:var(--red); border:1px solid var(--red-line); border-radius:var(--r); padding:.4rem .7rem; margin-bottom:.8rem; font-weight:600; }
body.present .present-foot { font-size:var(--fs-1); color:var(--muted); border-top:1px solid var(--border); margin-top:1rem; padding-top:.6rem; }
@media print {
  body.present .present-actions { display:none !important; }
  body.present .shell { max-width:none; padding:0; }
  body.present .icard, body.present .mc, body.present .tablewrap { break-inside:avoid; box-shadow:none; }
  @page { size:A4 landscape; margin:12mm; }
}


/* ---- Portal Reports "Progress" block (plans/REPORT_TAB_PROGRESS.md PR 3).
   Additions only; theme-independent via existing tokens. */
.pf-prog { margin-bottom:var(--pf-gap); }
.pf-prog-head { display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap; margin:.2rem 0 .8rem; }
.pf-prog-up { color:var(--green); }
.pf-prog-down { color:var(--red); }
.pf-prog-flat { color:var(--muted); }
.pf-prog-table { margin-top:.8rem; }
.pf-prog-row { grid-template-columns:minmax(0,1.6fr) repeat(6,minmax(0,1fr)); }
.pf-prog-row span { text-align:right; }
.pf-prog-row span:first-child { text-align:left; }


/* ---- Like-for-like progress presentation (Mally, 02/09/2026: a period 2 days
   old was being compared with a whole previous month, so "Completed" read
   -84% when it was actually ahead). ---- */
body:not(.portal) .prog-pill { margin-left:.45rem; font-size:var(--fs-1); vertical-align:middle; }
body:not(.portal) .prog-ctx { color:var(--muted); font-family:var(--mono); }
body:not(.portal) .prog-basis { border-left:3px solid var(--border-strong); padding-left:.6rem; margin:.1rem 0 .7rem; }
body:not(.portal) .prog-basis-live { border-left-color:var(--amber); }
body:not(.portal) .prog-partial-note { margin-top:-.2rem; }
.spark-line-partial { stroke-dasharray:3 3; opacity:.75; }
.spark-dot-partial { fill:var(--bg); stroke:var(--accent); stroke-width:1.6; }
.pf-prog-pill { margin-left:.4rem; font-size:var(--fs-1); }
.pf-prog-ctx { color:var(--muted); }
.pf-prog-basis { border-left:3px solid var(--border-strong); padding-left:.6rem; margin:.2rem 0 .7rem; }


/* ---- Progress period navigation + custom range (Mally, 02/09/2026: compare
   the exact months, and allow a custom date option). ---- */
body:not(.portal) .prog-nav { display:inline-flex; align-items:center; gap:var(--sp-2); }
body:not(.portal) .prog-step { padding:.15rem .45rem; line-height:1; }
body:not(.portal) .prog-step[disabled] { opacity:.35; cursor:not-allowed; }
body:not(.portal) .prog-cur { font-weight:700; color:var(--text-strong); min-width:9ch; text-align:center; }
body:not(.portal) .prog-custom { display:inline-flex; align-items:center; gap:var(--sp-3); }
body:not(.portal) .prog-date { background:var(--card); border:1px solid var(--border); border-radius:var(--r-sm, 6px);
  color:var(--text-strong); font:inherit; font-size:var(--fs-2); padding:.2rem .4rem; }
body:not(.portal) .prog-row-cur td { background:var(--bg-section); font-weight:600; }
.pf-prog-nav { display:inline-flex; align-items:center; gap:var(--sp-2); }
.pf-prog-step { padding:.15rem .45rem; line-height:1; }
.pf-prog-step[disabled] { opacity:.35; cursor:not-allowed; }
.pf-prog-cur { font-weight:700; color:var(--text-strong); min-width:9ch; text-align:center; }
.pf-prog-custom { display:inline-flex; align-items:center; gap:var(--sp-3); }
.pf-prog-date { background:var(--card); border:1px solid var(--border); border-radius:6px;
  color:var(--text-strong); font:inherit; font-size:var(--fs-2); padding:.2rem .4rem; }
.pf-prog-row-cur { background:var(--bg-section); font-weight:600; }


/* ---- Reporting tab sections (plans/REPORTING_TAB_ONE_FILTER.md) ---- */
body:not(.portal) .rep-sect { margin:var(--sp-7) 0 0; }
body:not(.portal) .rep-sect-h { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); margin-bottom:var(--sp-4); }
body:not(.portal) .rep-sect-toggle { background:none; border:0; padding:.2rem 0; font:inherit; font-size:var(--fs-4); font-weight:700; color:var(--text-strong); cursor:pointer; display:inline-flex; align-items:baseline; gap:.45rem; text-align:left; }
body:not(.portal) .rep-sect-toggle:hover { color:var(--accent); }
body:not(.portal) .rep-chev { font-size:var(--fs-3); color:var(--muted); }
body:not(.portal) .rep-sect-sub { font-size:var(--fs-1); font-weight:400; color:var(--muted); }
body:not(.portal) .rep-sect-body > .insights + .insights { margin-top:var(--sp-7); }
body:not(.portal) .prog-sect .rep-sect { margin-top:var(--sp-5); }


/* ---- Per-tab time basis + column menus (plans/CONSOLE_TIME_AND_COLUMN_FILTERS.md) ----
   The sort control and the column menus extend the EXISTING .cfdd dropdown
   system (the one the Status / Tracer / Client filters use) rather than
   inventing a parallel one, so they inherit its dark-theme colours. */
body:not(.portal) .tab-datenote { font-size:var(--fs-1); color:var(--muted); border-left:3px solid var(--accent);
  padding:.3rem .6rem; margin:0 0 var(--sp-5); background:var(--bg-section); border-radius:0 var(--r) var(--r) 0; }
body:not(.portal) .tab-datenote-off { border-left-color:var(--border-strong); }
body:not(.portal) .tab-datenote b { color:var(--text-strong); }
body:not(.portal) .tab-datenote-keep { color:var(--amber); }
/* Sort control: the direction toggle sits flush beside the sort button. */
body:not(.portal) .cfdd .sort-dir { margin-left:var(--sp-2); padding:0 .5rem; font-family:var(--mono); }
body:not(.portal) .pm-ctrl-sep { display:inline-block; width:1px; height:1.1rem; background:var(--border);
  margin:0 .35rem; vertical-align:middle; }
/* The chosen sort option, and any menu row acting as a toggle. */
body:not(.portal) .cfdd-all.on { background:var(--orange-soft); color:var(--orange); font-weight:600; }
/* Column header menu: a .cfdd button that inherits the table header's type. */
body:not(.portal) .colmenu { display:inline-flex; }
body:not(.portal) .colmenu-btn { display:inline-flex; align-items:center; gap:var(--sp-3); background:none;
  border:0; padding:0; font:inherit; color:inherit; cursor:pointer; white-space:nowrap; }
body:not(.portal) .colmenu-btn:hover, body:not(.portal) .colmenu-btn.on { color:var(--orange); }
body:not(.portal) .colmenu-arrow { font-size:var(--fs-1); }
body:not(.portal) .colmenu-menu { min-width:15rem; max-width:22rem; }
body:not(.portal) .colmenu-sep { font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.05em;
  color:var(--muted); padding:.35rem .5rem .2rem; border-top:1px solid var(--divider); margin-top:.2rem; }
body:not(.portal) .colmenu-search { width:100%; box-sizing:border-box; margin:.2rem 0; padding:.25rem .45rem;
  font:inherit; font-size:var(--fs-2); background:var(--card2); border:1px solid var(--border);
  border-radius:7px; color:var(--text-strong); }
body:not(.portal) .colmenu-list { max-height:15rem; overflow:auto; }
body:not(.portal) .colmenu-clear { border-top:1px solid var(--divider); margin-top:.2rem; color:var(--red); }
body:not(.portal) .coltable-bar { display:flex; align-items:center; gap:var(--sp-4); font-size:var(--fs-1);
  color:var(--muted); padding:.3rem 0 .5rem; }
body:not(.portal) th.th-menu { cursor:default; }


/* ---- Unsaved-changes panel: an edit the sheet has overtaken must LOOK
   different from one that is merely unsent, because saving it would undo
   someone else's work. ---- */
body:not(.portal) .pend-row { border:1px solid var(--border); border-radius:var(--r); padding:.5rem .6rem;
  margin-bottom:.5rem; background:var(--card2); }
body:not(.portal) .pend-row-danger { border-color:var(--amber-line); background:var(--amber-soft); }
body:not(.portal) .pend-warn { font-size:.76rem; line-height:1.45; color:var(--amber); margin-top:.3rem;
  border-left:3px solid var(--amber-line); padding-left:.5rem; }
body:not(.portal) .pend-row-danger .muted { color:var(--text); }
body:not(.portal) .pend-overwrite { border-color:var(--amber-line); color:var(--amber); }
body:not(.portal) .pend-overwrite:hover { background:var(--amber-soft); }
/* Every row carries at least one button, so no row is a dead end. */
body:not(.portal) .pend-acts { display:flex; gap:.4rem; flex-wrap:wrap; margin-top:.35rem; }
body:not(.portal) .pend-acts button { padding:.1rem .5rem; font-size:.75rem; }
body:not(.portal) .pend-discard { color:var(--muted); }
body:not(.portal) .pend-discard:hover { color:var(--red); border-color:var(--red-line); }

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE LAYER (2026-09-03 20:10) - phones and small tablets, every surface.
   ───────────────────────────────────────────────────────────────────────────
   Why this exists, measured before it was written (Chromium, 390x844, iPhone
   viewport, real pages served from this directory):

     spend.html       scrollWidth 863 vs 390  -> +473px of horizontal scroll
     index.html       scrollWidth 884 vs 390  -> +494px
     entitydist.html  scrollWidth 809 vs 390  -> +419px

   One root cause behind all three. `.app-hdr` is a flex row carrying
   `flex-wrap:nowrap` (console) with BOTH children pinned `flex:0 0 auto`
   (.app-hdr-title, .app-hdr-right). Nothing may shrink and nothing may wrap,
   so the header's natural width - a 36px logo, an h1, and a full sentence of
   .meta description - became the page's minimum width and every page inherited
   a horizontal scrollbar. The fix is at that source: the title column shrinks
   and wraps its text, the right cluster wraps under it, and .meta clamps.

   Everything else here follows from a phone actually being 390px wide: the
   220px sticky sidenav becomes a horizontal top bar (it is where the mobile
   section <select> lives, so it cannot simply be hidden), the sticky toolbar
   stops assuming a 56px header, controls grow to a 44px touch target (Apple
   HIG / WCAG 2.5.5), and drawers plus modals go full-bleed.

   Placement is deliberate: appended LAST so it wins on specificity ties
   without editing a single existing desktop rule. Nothing above this line
   changed, so there is no desktop regression surface.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- Tablet and below: let the header shrink instead of setting the page's
        minimum width. This alone removes the overflow on every page. ---- */
@media (max-width:900px) {
  .app-hdr { gap:var(--sp-5); flex-wrap:wrap; row-gap:var(--sp-4); }
  body:not(.portal) .app-hdr { flex-wrap:wrap; }
  /* min-width:0 is the load-bearing part - without it a flex item refuses to
     shrink below its content's intrinsic width no matter what flex-basis says. */
  .app-hdr-title { flex:1 1 auto; min-width:0; }
  /* The title column is itself a flex row wrapping an unnamed <div> holding the
     h1 and .meta. That inner div is a flex item too, so it keeps the default
     min-width:auto - measured 628px wide inside a 373px parent. Without this it,
     not the header, is what sets the page's minimum width. */
  .app-hdr-title > * { min-width:0; }
  .app-hdr-right { flex:0 1 auto; min-width:0; flex-wrap:wrap; justify-content:flex-end; }
  /* The console pins both of these to `white-space:nowrap` with an ellipsis at
     (0,3,2) - `body:not(.portal) .app-hdr-title h1, ... .meta` - which on a
     phone truncated the page's own H1 mid-word ("Spend" survived, the strapline
     became "freelancer payro..."). A title is the page's identity, so it wraps
     in full here; the strapline is context, so it wraps but clamps at 2 lines
     rather than pushing the content below the fold. Matching specificity is
     deliberate - a lower one silently loses. */
  body:not(.portal) .app-hdr-title h1, .app-hdr h1 {
    white-space:normal; overflow:visible; overflow-wrap:anywhere; }
  body:not(.portal) .app-hdr-title .meta, .app-hdr .meta {
    white-space:normal; overflow-wrap:anywhere;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
  /* Also (0,2,0) upstream: `body:not(.portal) .app-hdr-right{flex:0 0 auto}`. */
  body:not(.portal) .app-hdr-right { flex:0 1 auto; min-width:0; flex-wrap:wrap; }
  .toolbar input[type="search"], .pf-search { min-width:0; flex:1 1 180px; }
}

/* ---- Phones ---- */
@media (max-width:640px) {
  /* The console's left rail is a 220px sticky full-height column. On a 390px
     screen that is 56% of the viewport, and it holds the mobile section
     <select>, so it converts to a top bar rather than being hidden. */
  body:not(.portal) #app:has(> .sidenav) { display:block; }
  .sidenav { flex:0 0 auto; width:auto; height:auto; position:static;
    border-right:none; border-bottom:1px solid var(--border); overflow:visible; }
  .sidenav .topnav-inner { flex-direction:row; flex-wrap:wrap; padding:var(--sp-4) var(--sp-5); }
  .sidenav-foot { padding:0 var(--sp-5) var(--sp-4); }
  .topnav-mobile { min-height:44px; }

  /* Gutters: 1.5rem each side costs 48px of a 390px screen. */
  .shell, body:not(.portal) .shell { padding-left:var(--sp-5); padding-right:var(--sp-5); }
  body:not(.portal) .shell { padding-bottom:var(--sp-10); }

  /* The header wraps to two rows on a phone, so a hard 60px/56px sticky offset
     left the toolbar tucked underneath it. Let it sit in flow instead. */
  .toolbar { position:static; top:auto; }
  .toolbar > * { min-width:0; }
  .toolbar input[type="search"] { width:100%; flex:1 1 100%; }

  /* Touch targets: 44px minimum (Apple HIG, WCAG 2.5.5 Target Size). The
     desktop --ctl-h of 34px is a mouse dimension, not a thumb dimension.
     Raising the TOKEN rather than listing class names is deliberate: the
     console's control rule is `body:not(.portal) :is(.btn,.btn-sec,.btn-ghost,
     .iconbtn){min-height:var(--ctl-h)}` at specificity (0,2,1), so a flat
     `.btn-sec{min-height:44px}` here loses to it and silently does nothing -
     measured, the buttons stayed at 34px. Redefining --ctl-h lifts every
     control built on it, including ones not enumerated here. */
  :root { --ctl-h:44px; }
  .btn, .btn-sec, .btn-ghost, .navlink, .tab, .btn-tab, .iconbtn, .ptab,
  .toolbar select, .toolbar input[type="search"], select, .auth-link,
  .auth-google, .pf-btn, .pf-tab { min-height:44px; }
  .btn, .btn-sec, .btn-tab { padding-top:.6rem; padding-bottom:.6rem; }
  .btn-ghost, .iconbtn { min-width:44px; }
  .mode-pill { height:auto; min-height:32px; }
  /* Checkboxes and radios are 13px by default and effectively untappable. */
  input[type="checkbox"], input[type="radio"] { width:20px; height:20px; }

  /* Drawers and modals go full-bleed - a 94vw sheet with a 6vw dead margin
     wastes the only screen dimension a phone is short of. */
  .drawer, body:not(.portal) .drawer.drawer-wide { width:100vw; max-width:100vw; }
  /* `.modal.auth-modal` (two classes, 0-2-0) is listed explicitly because a
     media query adds NO specificity: a bare `.modal` (0-1-0) here loses to it
     and silently does nothing. Measured 2026-09-04 on the Cost Console at
     606px wide - the sign-in dialog kept its 400px desktop width while
     inheriting the bottom-sheet layout below (place-items:end stretch,
     border-radius:0), so it sat flush in the bottom-LEFT corner and read as a
     broken page. Every other modal was fine; only .auth-modal carries a second
     class. Same trap as the --ctl-h note further down: when a rule here has to
     beat a multi-class base rule, it must name it. */
  .modal, .modal.auth-modal { width:100vw; max-width:100vw; max-height:100vh; border-radius:0; }
  .modal-overlay { place-items:end stretch; }

  /* Any grid built on a minmax() track wider than the viewport blows out. */
  .two-col, .comms-wrap, .cdb-grid, .kpi-row, .mini-row,
  .pf-fields, .pf-form-row { grid-template-columns:1fr; }

  /* Wide content scrolls inside its own box, never the page. min-width:0 is the
     half everyone forgets: a grid or flex item defaults to min-width:auto, so
     without it the wrapper grows to its content and the PAGE scrolls sideways
     instead of the table. */
  .tablewrap, .chart-wrap, pre, .codeblock {
    overflow-x:auto; -webkit-overflow-scrolling:touch; min-width:0; max-width:100%; }
  img, svg, canvas, video { max-width:100%; }

  /* Long unbroken strings - wallet addresses, TxIDs, URLs - are the other
     classic source of a phone-width blowout. */
  .mono, code, .addr, .txid, td, th { overflow-wrap:anywhere; }

  /* 16px is the threshold below which iOS Safari zooms the page on focus and
     never zooms back out. */
  input, select, textarea { font-size:16px; }
}


/* ---- Touch devices of ANY width, not just narrow ones (2026-09-03 20:35).
   The 44px block above is keyed on max-width:640px, so a tablet held in
   landscape - a real touch device at 768-1024px - kept the 34px mouse-sized
   controls. Measured at 768px before this: .btn-ghost 34px, .btn-sec 34px.
   `pointer:coarse` is the honest test (is the primary input a finger?) rather
   than inferring it from viewport width, and it leaves every mouse-driven
   desktop, including a narrow window on one, at the compact 34px. ---- */
@media (pointer:coarse) {
  :root { --ctl-h:44px; }
  .btn, .btn-sec, .btn-ghost, .navlink, .tab, .btn-tab, .iconbtn, .ptab,
  .toolbar select, .toolbar input[type="search"], select, .auth-link,
  .auth-google, .pf-btn, .pf-tab { min-height:44px; }
  .btn-ghost, .iconbtn { min-width:44px; }
  input[type="checkbox"], input[type="radio"] { width:20px; height:20px; }
  /* iOS Safari zooms the page on focus of any input under 16px and offers no
     way back out, so this is a usability fix, not a type-scale preference. */
  input, select, textarea { font-size:16px; }
}
