/* ============================================================================
   Collabor8 Cadence — UI design system
   ----------------------------------------------------------------------------
   Components below never hardcode a colour; they resolve tokens.css only.
   Depth on dark = surface step + 1px hairline + a faint top highlight.
   Depth on light = hairline + a whisper of shadow.
   Motion is transform/opacity only, ease-out, 120–280ms, and fully disabled
   under prefers-reduced-motion. No decorative icons — hierarchy comes from
   type, colour, space and data-viz.
   ========================================================================== */
@import url("tokens.css");

/* ─────────────────────────── reset & base ─────────────────────────────── */
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{
  font-family:var(--font);
  font-feature-settings:"cv01","cv03","ss03","zero";
  color:var(--text);
  font-size:var(--t-base);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  min-height:100vh;
  background:var(--bg);
  transition:background-color var(--theme-swap) var(--ease-soft),color var(--theme-swap) var(--ease-soft);
}
/* A masked grid, fading down the page. Radial washes were the right instinct and
   the wrong shape — a soft blob still has a visible edge, and you see it. */
.shell::before{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
  background-image:
    linear-gradient(var(--grid-line) 1px,transparent 1px),
    linear-gradient(90deg,var(--grid-line) 1px,transparent 1px);
  background-size:var(--grid-size) var(--grid-size);
  -webkit-mask-image:linear-gradient(180deg,#000,transparent 60%);
  mask-image:linear-gradient(180deg,#000,transparent 60%);
}
.shell > *{position:relative;z-index:1}
a{color:inherit;text-decoration:none}
a.link{color:var(--accent);transition:opacity var(--dur-1) var(--ease)}
a.link:hover{opacity:.78}
::selection{background:var(--accent-soft);color:var(--text)}

/* one focus treatment everywhere. keyboard only. */
:focus{outline:none}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-xs)}

/* label a control for screen readers without showing it */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* scrollbars follow the surface ladder rather than the OS */
*{scrollbar-width:thin;scrollbar-color:var(--muted-line) transparent}
*::-webkit-scrollbar{width:9px;height:9px}
*::-webkit-scrollbar-thumb{background:var(--muted-line);border-radius:var(--r-full);border:2px solid transparent;background-clip:content-box}
*::-webkit-scrollbar-thumb:hover{background:var(--faint);background-clip:content-box}
*::-webkit-scrollbar-track{background:transparent}

/* ─────────────────────────── type utilities ───────────────────────────── */
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;font-feature-settings:"zero"}
.num{font-variant-numeric:tabular-nums}
.muted,.dim{color:var(--muted)}
.faint{color:var(--faint)}
.hint{color:var(--muted);font-size:var(--t-sm);line-height:1.6}
.small{font-size:var(--t-sm)}
.eyebrow{
  font-size:var(--t-2xs);letter-spacing:var(--track-eyebrow);text-transform:uppercase;
  color:var(--accent);font-weight:var(--w-semi);
}
h1,h2,h3{font-weight:var(--w-semi);letter-spacing:var(--track-heading)}

/* ─────────────────────────── shell ────────────────────────────────────── */
.shell{display:grid;grid-template-columns:244px 1fr;min-height:100vh}
.side{
  background:var(--side-bg);border-right:1px solid var(--line);
  padding:var(--s-5) var(--s-3);position:sticky;top:0;height:100vh;
  display:flex;flex-direction:column;gap:var(--s-1);
  transition:background var(--theme-swap) var(--ease-soft),border-color var(--theme-swap) var(--ease-soft);
}
/* The Pulse lockup: mark flush-left, stacked wordmark to its right. */
.brand{display:flex;flex-direction:row;align-items:center;gap:11px;padding:var(--s-2) var(--s-2) var(--s-6)}
.brand-words{display:flex;flex-direction:column;align-items:flex-start;gap:3px;line-height:1}
.brand .by{font-size:9px;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);font-weight:var(--w-semi)}
.brand .wm{font-size:18px;font-weight:var(--w-strong);letter-spacing:-.02em;color:var(--text);line-height:1.1}
.brand .wm em{font-style:normal;color:var(--accent)}

/* "Working" indicator — five bars beating outside-in (pbeat). */
.pulse-working{display:inline-flex;align-items:flex-end;gap:2px;height:15px}
.pulse-working i{width:3px;border-radius:2px;transform-origin:bottom;animation:pbeat 1.15s var(--ease-inout) infinite}
.pulse-working i:nth-child(1){height:7px;background:#33456A;animation-delay:0s}
.pulse-working i:nth-child(2){height:11px;background:#3B7DFF;animation-delay:.18s}
.pulse-working i:nth-child(3){height:15px;background:#2FBF8F;animation-delay:.36s}
.pulse-working i:nth-child(4){height:11px;background:#3B7DFF;animation-delay:.18s}
.pulse-working i:nth-child(5){height:7px;background:#33456A;animation-delay:0s}
@keyframes pbeat{0%,100%{transform:scaleY(.4)}50%{transform:scaleY(1)}}
@media (prefers-reduced-motion:reduce){.pulse-working i{animation:none;transform:scaleY(1)}}

/* Verified seal — all-emerald Pulse inside a circular seal. */
.pulse-seal{border-radius:50%;flex:none;display:grid;place-items:center;color:var(--pass);background:rgba(47,191,143,.12);border:1px solid rgba(47,191,143,.36);box-shadow:0 0 0 6px rgba(47,191,143,.08)}
.pulse-seal-in{display:flex;flex-direction:column;align-items:center;gap:6px}
.pulse-seal-lbl{font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;font-weight:var(--w-semi)}

.nav{display:flex;flex-direction:column;gap:1px}
/* group label sits on a hairline that runs the width of the rail — it separates
   "your work" from "governance" without a heavy divider */
.nav .grp{
  position:relative;font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--faint);margin:var(--s-6) 0 var(--s-2) 10px;font-weight:var(--w-semi);
  padding-top:var(--s-4);
}
.nav .grp::before{content:"";position:absolute;left:-10px;right:-4px;top:0;height:1px;background:var(--line-soft)}
.nav a{
  position:relative;display:flex;align-items:center;justify-content:space-between;
  padding:8px 11px;border-radius:var(--r-sm);color:var(--muted);
  font-weight:var(--w-medium);font-size:var(--t-base);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.nav a .tag{
  font-size:var(--t-2xs);font-weight:var(--w-semi);color:var(--accent-ink);
  background:var(--accent);border-radius:var(--r-full);padding:1px 7px;
}
/* Red count tag — open remediation items that need attention. */
.nav a .tag.bad{background:var(--crit);color:#fff}
.nav a:hover{background:var(--raised);color:var(--text)}
.nav a.on{background:var(--nav-on-bg);color:var(--text);font-weight:var(--w-semi)}
.nav a.on::before{
  content:"";position:absolute;left:-11px;top:8px;bottom:8px;width:2px;
  border-radius:0 2px 2px 0;background:var(--accent);
}
.side .foot{margin-top:auto;border-top:1px solid var(--line);padding-top:var(--s-3);display:flex;align-items:center;gap:10px}
.avatar{
  width:32px;height:32px;border-radius:var(--r-full);display:grid;place-items:center;
  font-weight:var(--w-semi);font-size:var(--t-sm);color:var(--text-2);
  background:var(--inset);border:1px solid var(--line);
  flex:none;text-transform:uppercase;letter-spacing:.02em;
}
.foot .who{font-size:var(--t-sm);font-weight:var(--w-medium);line-height:1.35;min-width:0}
.foot .who small{display:block;color:var(--faint);font-weight:var(--w-normal);font-size:var(--t-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ─────────────────────────── topbar ───────────────────────────────────── */
.main{display:flex;flex-direction:column;min-width:0}
.topbar{
  display:flex;align-items:center;gap:var(--s-3);padding:11px var(--s-6);
  border-bottom:1px solid var(--line);background:var(--topbar-bg);
  backdrop-filter:saturate(160%) blur(12px);-webkit-backdrop-filter:saturate(160%) blur(12px);
  position:sticky;top:0;z-index:20;
  transition:background var(--theme-swap) var(--ease-soft),border-color var(--theme-swap) var(--ease-soft);
}
.topbar .spacer{flex:1}
.topbar .ctx{font-size:var(--t-sm);color:var(--muted)}
.topbar .ctx b{color:var(--text-2);font-weight:var(--w-semi)}
.topbar .ctx .sep{color:var(--faint);margin:0 8px}
/* engine state — emerald only when a target is met */
.engine{display:inline-flex;align-items:center;gap:6px;font-size:var(--t-sm)}
.engine::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.engine.live{color:var(--pass)}
.engine.down{color:var(--crit)}

.seg{display:flex;gap:2px;background:var(--inset);border:1px solid var(--line);border-radius:var(--r-md);padding:2px}
.seg button{
  font:inherit;font-size:var(--t-sm);font-weight:var(--w-medium);color:var(--muted);
  background:none;border:none;padding:5px 11px;border-radius:var(--r-sm);cursor:pointer;
  transition:color var(--dur-1) var(--ease),background var(--dur-1) var(--ease);
}
.seg button:hover{color:var(--text-2)}
.seg button.on{background:var(--surface);color:var(--text);box-shadow:var(--shadow)}
.toplabel{font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);font-weight:var(--w-semi);margin-right:-4px}
.rolechip{
  display:inline-flex;align-items:center;gap:7px;font-size:var(--t-sm);font-weight:var(--w-medium);
  color:var(--text-2);background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-full);padding:5px 12px;
}
.rolechip::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--accent)}

/* ─────────────────────────── content & headers ────────────────────────── */
/* No max-width. The sidebar already constrains the column; capping again left a
   dead third on wide monitors. Long prose is capped individually via `max-width:62ch`. */
.content{padding:var(--s-6) var(--s-8) var(--s-16);width:100%}
.pagehead{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--s-5);margin-bottom:var(--s-6);flex-wrap:wrap}
.pagehead h1{font-size:var(--t-2xl);font-weight:var(--w-strong);letter-spacing:var(--track-display);margin-top:6px}
.pagehead p{color:var(--muted);margin-top:6px;font-size:var(--t-base);max-width:62ch}
.crumb{display:flex;gap:8px;align-items:center;font-size:var(--t-sm);color:var(--muted);margin-bottom:var(--s-3)}
.crumb a{transition:color var(--dur-1) var(--ease)}
.crumb a:hover{color:var(--accent)}
.crumb span{color:var(--faint)}
.crumb b{color:var(--text-2);font-weight:var(--w-medium)}

/* ─────────────────────────── buttons ──────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  border:1px solid transparent;cursor:pointer;font:inherit;
  font-weight:var(--w-semi);font-size:var(--t-base);
  padding:9px 16px;border-radius:var(--r-md);
  color:var(--btn-ink);background:var(--btn-bg);box-shadow:var(--btn-shadow);
  transition:background var(--dur-1) var(--ease),transform var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease);
}
.btn:hover{background:var(--btn-hover)}
.btn:active{background:var(--btn-press);transform:translateY(.5px)}
.btn:disabled{opacity:.42;cursor:not-allowed;transform:none}
.btn.ghost{background:var(--surface);color:var(--text);border-color:var(--line);box-shadow:none}
.btn.ghost:hover{background:var(--raised);border-color:var(--muted-line)}
.btn.ghost:active{background:var(--active)}
.btn.sm{padding:6px 11px;font-size:var(--t-sm);border-radius:var(--r-sm)}
.btn.danger{background:var(--danger);color:#fff;border-color:transparent}
.btn.danger:hover{background:var(--danger-hover)}
.btn.danger:active{background:var(--danger-hover)}
.btn-line{
  display:inline-flex;align-items:center;gap:6px;font-size:var(--t-sm);font-weight:var(--w-medium);
  color:var(--text-2);background:transparent;border:1px solid var(--line);border-radius:var(--r-sm);
  padding:6px 12px;cursor:pointer;font-family:inherit;
  transition:color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease);
}
.btn-line:hover{background:var(--raised);border-color:var(--muted-line);color:var(--text)}
.btn-line.sm{padding:4px 9px;font-size:var(--t-xs)}

/* ─────────────────────────── cards, panels, grid ──────────────────────── */
/* Cards need air. 16px read as one clumped mass at dashboard density. */
.grid{display:grid;gap:var(--s-5)}
.c2{grid-template-columns:repeat(2,minmax(0,1fr))}
.c3{grid-template-columns:repeat(3,minmax(0,1fr))}
.c4{grid-template-columns:repeat(4,minmax(0,1fr))}

.card,.panel{
  position:relative;background:var(--card-bg);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--card-highlight),var(--shadow);
  transition:border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease);
}
/* Hovering a surface brightens its edge. Cheap, and it makes the page feel alive. */
.card:hover,.panel:hover{border-color:var(--muted-line)}
/* clips the table header band to the panel's rounded corners, and stops any
   wide child from bleeding past the panel edge */
.panel{overflow:hidden}

/* ── reticle ────────────────────────────────────────────────────────────
   Accent brackets on the two corners of a primary surface. The console is a
   scope; things under inspection sit inside crosshairs. Applied with `.framed`,
   never to every card — the motif dies the moment it's everywhere. */
.framed{position:relative}
.framed::before,.framed::after{
  content:"";position:absolute;width:14px;height:14px;pointer-events:none;z-index:1;
}
/* inset to 0, not -1px: `.panel` clips overflow, and a bracket hanging outside
   the border would be cut off on every report panel */
.framed::before{top:0;left:0;border-top:2px solid var(--bracket);border-left:2px solid var(--bracket);border-top-left-radius:var(--r-lg)}
.framed::after{bottom:0;right:0;border-bottom:2px solid var(--bracket);border-right:2px solid var(--bracket);border-bottom-right-radius:var(--r-lg)}

/* ── readout strip ──────────────────────────────────────────────────────
   One instrument, divided by hairlines — not N floating boxes. Boxes never
   align because their content differs; a strip cannot misalign. */
.readout{
  display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  background:var(--card-bg);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--card-highlight),var(--shadow);overflow:hidden;
}
.ro{
  position:relative;display:flex;flex-direction:column;gap:7px;
  padding:var(--s-5) var(--s-5) var(--s-4);border-left:1px solid var(--line-soft);min-width:0;
}
.ro:first-child{border-left:none}
/* the channel tick is INSET, so adjacent ticks read as separate marks rather
   than one continuous rainbow bar across the top of the strip */
.ro::before{
  content:"";position:absolute;top:0;left:var(--s-5);right:var(--s-5);height:2px;
  background:var(--ch,var(--accent));border-radius:0 0 2px 2px;
}
.ro.ch-accent{--ch:var(--accent)} .ro.ch-cyan{--ch:var(--accent-2)}
.ro.ch-pass{--ch:var(--pass)}     .ro.ch-crit{--ch:var(--crit)}
.ro.ch-med{--ch:var(--med)}       .ro.ch-muted{--ch:var(--muted-line)}
.ro-l{font-size:var(--t-2xs);letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:var(--w-semi);white-space:nowrap}
.ro-n{
  font-family:var(--mono);font-size:var(--t-2xl);font-weight:var(--w-medium);
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;color:var(--text);line-height:1;
}
.ro-n.ok{color:var(--pass)} .ro-n.bad{color:var(--crit)} .ro-n.warn{color:var(--med)}
@media(max-width:1080px){
  .readout{grid-auto-flow:row;grid-auto-columns:auto}
  .ro{border-left:none;border-top:1px solid var(--line-soft)}
  .ro:first-child{border-top:none}
}

/* score + bar, side by side, in a table cell */
/* domain breakdown — columns at width, so 19 domains don't become a scroll */
.dombars{display:grid;grid-template-columns:repeat(auto-fit,minmax(460px,1fr));gap:var(--s-3) var(--s-8);padding:var(--s-4) var(--s-5) var(--s-5)}
/* the name column fits the longest label we ship — "Dependencies & supply chain"
   and "Secure development lifecycle" — rather than ellipsing it */
.dombar{display:grid;grid-template-columns:58px 214px minmax(56px,1fr) 62px;align-items:center;gap:var(--s-3)}
.dombar .dk{font-family:var(--mono);font-size:var(--t-xs);color:var(--faint);letter-spacing:.02em}
.dombar .dn{font-size:var(--t-sm);color:var(--text-2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dombar b{text-align:right;font-family:var(--mono);font-size:var(--t-sm);font-variant-numeric:tabular-nums;white-space:nowrap}
.dombar b::after{content:"/100";color:var(--faint);font-size:9px;margin-left:2px}
.dombar b.ok{color:var(--pass)} .dombar b.warn{color:var(--med)} .dombar b.bad{color:var(--crit)}

/* a scored zero: no fill to draw, so mark the origin. distinct from n/a. */
.dombar .track.zero{position:relative}
.dombar .track.zero::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  border-radius:var(--r-full);background:var(--crit);
}

/* not applicable: no controls to judge. It must not look like a failing zero —
   the track is a flat hatch, the label is grey, and there is no "/100". */
.dombar.na .dk,.dombar.na .dn{color:var(--faint)}
.dombar .fill.na{
  background:repeating-linear-gradient(-45deg,var(--inset) 0 4px,transparent 4px 8px);
}
.dombar b.na-lab{text-align:right;font-family:var(--mono);font-size:var(--t-xs);color:var(--faint)}
.dombar b.na-lab::after{content:none}
@media(max-width:900px){.dombar{grid-template-columns:62px minmax(60px,1fr) 62px}.dombar .dn{display:none}}

.scorecell{display:flex;align-items:center;gap:10px;min-width:132px}
.scorecell b{font-family:var(--mono);font-size:var(--t-md);font-variant-numeric:tabular-nums;min-width:26px}
.scorecell .track{flex:1}
.scorecell b.ok{color:var(--pass)} .scorecell b.warn{color:var(--med)} .scorecell b.bad{color:var(--crit)}
.search.sm{padding:6px 10px;font-size:var(--t-sm);min-width:200px}
.card{padding:var(--s-5)}
.card + .card{margin-top:var(--s-4)}
.card h2,.panel h2{font-size:var(--t-md);font-weight:var(--w-semi);letter-spacing:-.012em}
.card .sub,.panel .sub{color:var(--muted);font-size:var(--t-sm);margin-top:3px;font-weight:var(--w-normal)}
.cardhead{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:var(--s-4);gap:var(--s-3)}
.panel-head{
  display:flex;justify-content:space-between;align-items:flex-start;gap:var(--s-3);
  padding:var(--s-4) var(--s-5);border-bottom:1px solid var(--line-soft);
}

/* interactive card lift — the only hover transform in the system */
.card.link-card:hover,.panel.link-card:hover{border-color:var(--muted-line);transform:translateY(-1px)}

/* ─────────────────────────── KPI & metrics ────────────────────────────── */
/* A KPI card is a readout. It gets a short accent segment on its top edge —
   the tone says which family the number belongs to (--kpi-tone). */
.kpi{padding:var(--s-4) var(--s-5);position:relative;overflow:hidden}
.kpi::after{
  content:"";position:absolute;left:var(--s-5);top:0;height:2px;width:44px;
  background:var(--kpi-tone,var(--accent));border-radius:0 0 2px 2px;
  transition:width var(--dur-3) var(--ease);
}
.kpi:hover::after{width:72px}
.kpi .lab,.kpi-l{font-size:var(--t-2xs);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:var(--w-semi)}
.kpi .n,.kpi-n{
  font-family:var(--mono);font-size:var(--t-2xl);font-weight:var(--w-medium);letter-spacing:-.02em;
  margin-top:8px;font-variant-numeric:tabular-nums;color:var(--text);line-height:1.1;
}
.kpi .t{font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--faint);margin-top:4px}
.kpi .d{display:inline-flex;align-items:center;gap:5px;font-size:var(--t-sm);font-weight:var(--w-semi);margin-top:8px;padding:2px 8px;border-radius:var(--r-full)}
.d.up{color:var(--pass);background:var(--pass-bg)}
.d.down{color:var(--crit);background:var(--crit-bg)}
.kpi .spark{margin-top:var(--s-3)}

/* one very large figure — credits balance, and nothing else */
.bignum{font-family:var(--mono);font-size:var(--t-3xl);font-weight:var(--w-medium);letter-spacing:-.03em;color:var(--text);font-variant-numeric:tabular-nums;line-height:1}

.metricrow{display:flex;gap:var(--s-3);flex-wrap:wrap}
.metric{
  flex:1;min-width:150px;background:var(--card-bg);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:var(--s-4);box-shadow:var(--card-highlight),var(--shadow);
}
.metric .v{font-family:var(--mono);font-size:var(--t-lg);font-weight:var(--w-medium);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.metric .l{color:var(--muted);font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.07em;margin-top:4px;font-weight:var(--w-medium)}

/* ─────────────────────────── score ring ───────────────────────────────── */
.ring-wrap{display:flex;align-items:center;gap:var(--s-5);flex-wrap:wrap}
.ring{position:relative;width:128px;height:128px;flex:none}
/* the dial graticule inside the gauge — reads as an instrument, not a donut */
.dial line{stroke:var(--dial);stroke-width:1}
.dial line.maj{stroke:var(--muted);stroke-width:1.25}
/* the badge threshold, marked on the dial itself. applications only. */
.badge-tick{stroke:var(--pass);stroke-width:3}
.ring .val{position:absolute;inset:0;display:grid;place-content:center;text-align:center}
.ring .val b{font-family:var(--mono);font-size:var(--t-3xl);font-weight:var(--w-medium);letter-spacing:-.035em;line-height:1;font-variant-numeric:tabular-nums}
.ring .val small{display:block;font-size:var(--t-2xs);letter-spacing:.13em;text-transform:uppercase;color:var(--faint);margin-top:6px;font-weight:var(--w-medium)}
/* the trend card shares a row with the (taller) gauge card; its chart absorbs
   the slack rather than leaving dead space under the plot */
.trendcard{display:flex;flex-direction:column}
.trendcard svg{flex:1;min-height:150px;max-height:230px;height:auto}

.ring-stats{flex:1;min-width:150px;display:flex;flex-direction:column;gap:10px}
.ring-stats .row{display:flex;justify-content:space-between;align-items:baseline;font-size:var(--t-base)}
.ring-stats .row b{font-variant-numeric:tabular-nums;font-weight:var(--w-semi)}

/* legacy conic seal (_macros.seal) */
.seal-score{display:inline-grid;place-items:center;position:relative;width:148px;height:148px;border-radius:50%}
.seal-score .ring{position:absolute;inset:0;border-radius:50%;width:auto;height:auto}
.seal-score .inner{width:112px;height:112px;border-radius:50%;background:var(--surface);display:grid;place-items:center;text-align:center;border:1px solid var(--line)}
.seal-score .val{font-size:var(--t-2xl);font-weight:var(--w-strong);color:var(--text);line-height:1;font-variant-numeric:tabular-nums}
.seal-score .unit{font-size:var(--t-xs);color:var(--muted);letter-spacing:.1em;text-transform:uppercase;margin-top:3px}

/* ─────────────────────────── severity tiles ───────────────────────────── */
.sevgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s-3)}
.sevtile{
  --tone:var(--low);--tint:var(--surface-2);
  border:1px solid var(--line);border-radius:var(--r-md);padding:13px 15px;
  position:relative;overflow:hidden;background:var(--tint);
  transition:border-color var(--dur-1) var(--ease);
}
.sevtile:hover{border-color:var(--muted-line)}
.sevtile .bar{position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--tone)}
.sevtile .n{font-family:var(--mono);font-size:var(--t-xl);font-weight:var(--w-medium);font-variant-numeric:tabular-nums;letter-spacing:var(--track-heading);color:var(--tone)}
.sevtile .l{font-size:var(--t-xs);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);font-weight:var(--w-medium);margin-top:2px}
/* only critical and high earn a tint. medium and low are counts, not alarms. */
.sevtile.crit{--tone:var(--crit);--tint:var(--crit-bg)}
.sevtile.high{--tone:var(--high);--tint:var(--high-bg)}
.sevtile.med{--tone:var(--med)}
.sevtile.low{--tone:var(--low)} .sevtile.low .n{color:var(--text-2)}

/* ─────────────────────────── pills & status ───────────────────────────── */
.pill{
  display:inline-flex;align-items:center;gap:6px;font-size:var(--t-xs);font-weight:var(--w-semi);
  letter-spacing:.01em;padding:3px 9px;border-radius:var(--r-full);
  border:1px solid var(--line);color:var(--text-2);background:var(--inset);white-space:nowrap;
}
.pill::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--muted);flex:none}

.pill.ok,.pill.complete,.pill.issued,.pill.active,.pill.PASS{color:var(--pass);background:var(--pass-bg);border-color:var(--pass-line)}
.pill.ok::before,.pill.complete::before,.pill.issued::before,.pill.active::before,.pill.PASS::before{background:var(--pass)}

.pill.warn,.pill.PARTIAL{color:var(--med);background:var(--med-bg);border-color:var(--med-line)}
.pill.warn::before,.pill.PARTIAL::before{background:var(--med)}

.pill.bad,.pill.failed,.pill.failed_config,.pill.revoked,.pill.FAIL{color:var(--crit);background:var(--crit-bg);border-color:var(--crit-line)}
.pill.bad::before,.pill.failed::before,.pill.failed_config::before,.pill.revoked::before,.pill.FAIL::before{background:var(--crit)}

.pill.run,.pill.queued,.pill.staging,.pill.assessing,.pill.scoring,.pill.reporting{color:var(--running);background:var(--running-bg);border-color:var(--running-line)}
.pill.run::before,.pill.queued::before,.pill.staging::before,.pill.assessing::before,.pill.scoring::before,.pill.reporting::before{background:var(--running);animation:pulse 1.6s var(--ease-inout) infinite}

.pill.neutral,.pill.expired,.pill.suspended,.pill.archived,.pill.N_A,.pill.EXCLUDED{color:var(--muted);background:var(--na-bg);border-color:var(--line)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.3}}

.sev{font-weight:var(--w-semi);font-size:var(--t-sm)}
.sev.critical{color:var(--crit)} .sev.high{color:var(--high)} .sev.medium{color:var(--med)} .sev.low{color:var(--low)} .sev.info{color:var(--faint)}

/* check verdict text used inside tables */
.v-fail{color:var(--crit);font-weight:var(--w-medium);font-size:var(--t-sm);text-transform:capitalize}
.v-part{color:var(--med);font-weight:var(--w-medium);font-size:var(--t-sm);text-transform:capitalize}

/* compact chips (app_detail severity counts) */
.chips{display:inline-flex;gap:6px;flex-wrap:wrap;align-items:center}
.chip{
  font-size:var(--t-xs);font-weight:var(--w-medium);padding:3px 8px;border-radius:var(--r-sm);
  color:var(--muted);background:var(--inset);border:1px solid transparent;font-variant-numeric:tabular-nums;
}
.chip.c{color:var(--crit);background:var(--crit-bg);border-color:var(--crit-line)}
.chip.h{color:var(--high);background:var(--high-bg);border-color:var(--high-line)}
.chip.z{color:var(--muted);background:var(--inset)}

/* ─────────────────────────── tables ───────────────────────────────────── */
table{width:100%;border-collapse:collapse}
th{
  text-align:left;font-size:var(--t-2xs);letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);font-weight:var(--w-semi);padding:10px var(--s-4);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--surface-2);
}
/* the header band is inset from the panel's rounded corners */
.panel table thead th:first-child{padding-left:var(--s-5)}
.panel table thead th:last-child{padding-right:var(--s-5)}
.panel table tbody td:first-child{padding-left:var(--s-5)}
.panel table tbody td:last-child{padding-right:var(--s-5)}
/* Findings text can contain long unbroken tokens (hashes, paths, and — when a
   decrypt is missed — ciphertext). Without this a single token blows the layout
   out past the viewport instead of wrapping. */
td{padding:12px var(--s-4);border-bottom:1px solid var(--line-soft);font-size:var(--t-base);vertical-align:middle;overflow-wrap:anywhere}
td b{font-weight:var(--w-semi)}
td small{overflow-wrap:anywhere}
tbody tr{transition:background var(--dur-1) var(--ease)}
tbody tr:hover td{background:var(--raised)}
tbody tr:last-child td{border-bottom:none}

.appcell{display:flex;align-items:center;gap:11px}
.appcell .mk{
  width:32px;height:32px;border-radius:var(--r-md);display:grid;place-items:center;
  font-weight:var(--w-semi);font-size:var(--t-xs);color:var(--text-2);
  background:var(--inset);border:1px solid var(--line);flex:none;text-transform:uppercase;
}
.appcell .mk.v{color:var(--accent);background:var(--accent-soft);border-color:var(--accent-line)}
.appcell b{font-size:var(--t-base);font-weight:var(--w-semi)}
.appcell small{display:block;color:var(--faint);font-size:var(--t-xs)}

.track{height:5px;border-radius:var(--r-full);background:var(--inset);overflow:hidden;min-width:90px}
.track .fill{height:100%;border-radius:var(--r-full);background:var(--accent);transition:width var(--dur-4) var(--ease)}
.track .fill.warn{background:var(--med)}
.track .fill.bad{background:var(--crit)}

/* ─────────────────────────── tabs ─────────────────────────────────────── */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin-bottom:var(--s-5);flex-wrap:wrap}
.tabs button{
  font:inherit;font-size:var(--t-base);font-weight:var(--w-medium);color:var(--muted);
  background:none;border:none;cursor:pointer;padding:10px 14px;position:relative;
  transition:color var(--dur-1) var(--ease);
}
.tabs button:hover{color:var(--text-2)}
.tabs button.on{color:var(--text);font-weight:var(--w-semi)}
.tabs button.on::after{content:"";position:absolute;left:14px;right:14px;bottom:-1px;height:2px;border-radius:2px 2px 0 0;background:var(--accent)}
/* anchor-based tab strip (same look as .tabs button, for navigable tabs) */
.tabs a{font:inherit;font-size:var(--t-base);font-weight:var(--w-medium);color:var(--muted);text-decoration:none;padding:10px 14px;position:relative;transition:color var(--dur-1) var(--ease)}
.tabs a:hover{color:var(--text-2)}
.tabs a.on{color:var(--text);font-weight:var(--w-semi)}
.tabs a.on::after{content:"";position:absolute;left:14px;right:14px;bottom:-1px;height:2px;border-radius:2px 2px 0 0;background:var(--accent)}
.tabpane{display:none}
.tabpane.on{display:block;animation:rise var(--dur-3) var(--ease) both}

/* ─────────────────────────── lists ────────────────────────────────────── */
.att{display:flex;align-items:center;gap:var(--s-3);padding:12px 2px;border-bottom:1px solid var(--line-soft)}
.att:last-child{border-bottom:none}
.att .dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--muted)}
.att .dot.c{background:var(--crit)} .att .dot.h{background:var(--high)}
.att .dot.a{background:var(--accent)} .att .dot.b{background:var(--running)} .att .dot.v{background:var(--insufficient)}
.att b{font-size:var(--t-base);font-weight:var(--w-semi)}
.att small{color:var(--muted);font-size:var(--t-sm);display:block;margin-top:1px}

.delta{font-size:var(--t-sm);font-weight:var(--w-semi);font-variant-numeric:tabular-nums}
.delta.up{color:var(--pass)} .delta.down{color:var(--crit)} .delta.flat{color:var(--faint)}

.metarow{display:flex;gap:var(--s-6);flex-wrap:wrap;margin-top:10px}
.metarow div{font-size:var(--t-sm);color:var(--text-2);display:flex;align-items:center;gap:7px}
.metarow b{color:var(--faint);font-weight:var(--w-medium);text-transform:uppercase;font-size:var(--t-2xs);letter-spacing:.08em}
.row-between{display:flex;justify-content:space-between;align-items:center;gap:var(--s-4);flex-wrap:wrap}

/* ─────────────────────────── forms ────────────────────────────────────── */
label{display:block;font-size:var(--t-base);font-weight:var(--w-medium);color:var(--text-2);margin-bottom:6px}
input,select,textarea{
  width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:var(--r-md);
  font-size:var(--t-base);font-family:inherit;background:var(--field-bg);color:var(--text);
  transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease),background var(--dur-1) var(--ease);
}
input::placeholder,textarea::placeholder{color:var(--faint)}
input:hover,select:hover,textarea:hover{border-color:var(--muted-line)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
input[type=checkbox]{width:auto;accent-color:var(--accent)}
select{
  appearance:none;-webkit-appearance:none;padding-right:30px;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:calc(100% - 15px) calc(50% + 1px),calc(100% - 10px) calc(50% + 1px);
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
.field{margin-bottom:var(--s-4)}
.field small.hint{display:block;margin-top:5px}
/* checkbox + label row (attestation, opt-ins) — mirrors .toggle */
.check{display:flex;align-items:flex-start;gap:8px;font-size:var(--t-sm);color:var(--text-2);cursor:pointer;margin:0;line-height:1.45}
.check input{margin:2px 0 0;flex:none}

/* ─────────────────────────── verdict / lineage / badge ────────────────── */
.verdict{padding:var(--s-4);border-radius:var(--r-md);font-size:var(--t-base);border:1px solid var(--line);border-left:2px solid var(--accent);background:var(--surface)}
.verdict.GREEN{border-left-color:var(--pass);background:var(--pass-bg);border-color:var(--pass-line)}
.verdict.AMBER{border-left-color:var(--med);background:var(--med-bg);border-color:var(--med-line)}
.verdict.RED{border-left-color:var(--crit);background:var(--crit-bg);border-color:var(--crit-line)}

.lineage{
  font-family:var(--mono);font-size:var(--t-sm);color:var(--text-2);background:var(--field-bg);
  border:1px solid var(--line);border-radius:var(--r-md);padding:11px 13px;word-break:break-all;line-height:1.7;
}

/* the verification seal — the product's one moment of ceremony */
/* The seal is emerald: it means a target was met. Applications earn it; the
   organization never does. */
.badge-seal{
  width:96px;height:96px;border-radius:50%;flex:none;display:grid;place-items:center;text-align:center;
  color:var(--pass);background:var(--pass-bg);
  border:1px solid var(--pass-line);
  box-shadow:0 0 0 6px var(--pass-bg);
  position:relative;
}
.badge-seal::after{
  content:"";position:absolute;inset:-1px;border-radius:50%;border:1px solid var(--pass);
  opacity:0;animation:seal-ping 2.4s var(--ease) .35s;
}
@keyframes seal-ping{0%{opacity:.55;transform:scale(1)}70%,100%{opacity:0;transform:scale(1.24)}}
.badge-seal .tick{font-size:30px;font-weight:var(--w-strong);line-height:1}
.badge-seal .lbl{font-size:9px;letter-spacing:.12em;text-transform:uppercase;margin-top:3px;font-weight:var(--w-semi)}

/* ─────────────────────────── stepper & upload ─────────────────────────── */
.steps{display:flex;align-items:center;gap:10px;margin-bottom:var(--s-5);flex-wrap:wrap}
.step{display:flex;align-items:center;gap:9px;font-size:var(--t-sm);color:var(--muted);font-weight:var(--w-medium)}
.step .num{
  width:22px;height:22px;border-radius:50%;display:grid;place-items:center;
  font-size:var(--t-xs);font-weight:var(--w-semi);background:var(--inset);color:var(--muted);
  border:1px solid var(--line);flex:none;
  transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease);
}
.step.on{color:var(--text)}
.step.on .num{background:var(--accent);color:var(--accent-ink);border-color:transparent}
.step.done{color:var(--text-2)}
.step.done .num{background:var(--pass-bg);color:transparent;border-color:var(--pass-line);position:relative}
.step.done .num::after{content:"✓";position:absolute;inset:0;display:grid;place-items:center;color:var(--pass);font-size:var(--t-xs)}
.step .bar{width:26px;height:1px;background:var(--line)}

.dropzone{
  border:1px dashed var(--muted-line);border-radius:var(--r-lg);padding:var(--s-8) var(--s-5);
  text-align:center;background:var(--field-bg);
  transition:border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease);
}
.dropzone.drag{border-color:var(--accent);background:var(--accent-soft)}
.uploadbar{height:4px;background:var(--inset);border-radius:var(--r-full);margin:var(--s-3) auto 0;max-width:360px;overflow:hidden}
.uploadbar .fill{height:100%;width:0;background:var(--accent);transition:width var(--dur-2) var(--ease-soft)}

/* ─────────────────────────── flashes / banners / empty ────────────────── */
.flash{padding:11px 14px;border-radius:var(--r-md);margin-bottom:var(--s-4);font-size:var(--t-base);border:1px solid transparent;animation:rise var(--dur-3) var(--ease) both}
.flash.ok{background:var(--pass-bg);color:var(--pass);border-color:var(--pass-line)}
.flash.err{background:var(--crit-bg);color:var(--crit);border-color:var(--crit-line)}
.banner-warn{
  background:var(--crit-bg);color:var(--crit);border:1px solid var(--crit-line);
  border-radius:var(--r-md);padding:11px 14px;margin-bottom:var(--s-4);font-size:var(--t-base);
}
.banner-warn strong{color:var(--crit);font-weight:var(--w-semi)}
.banner-info{
  background:var(--surface);color:var(--text-2);border:1px solid var(--line);
  border-radius:var(--r-md);padding:11px 14px;margin-bottom:var(--s-4);font-size:var(--t-base);
}

.empty{text-align:center;padding:var(--s-12) var(--s-5);color:var(--muted)}
.empty .big{font-size:var(--t-md);color:var(--text);font-weight:var(--w-semi);margin-bottom:6px;letter-spacing:var(--track-heading)}
.empty p{max-width:46ch;margin:0 auto;font-size:var(--t-base)}

/* ─────────────────────────── auth screens ─────────────────────────────── */
.auth-wrap{min-height:100vh;display:grid;place-items:center;padding:var(--s-6);background:var(--bg);position:relative;overflow:hidden}

/* Measurement grid, tinted with the verification accent. Security tooling is an
   instrument; an instrument has a graticule. Fine 28px cells inside coarse 140px
   ones, so the eye reads a scale rather than wallpaper. */
.auth-wrap::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:
    linear-gradient(var(--grid-major) 1px,transparent 1px),
    linear-gradient(90deg,var(--grid-major) 1px,transparent 1px),
    linear-gradient(var(--grid-minor) 1px,transparent 1px),
    linear-gradient(90deg,var(--grid-minor) 1px,transparent 1px);
  background-size:140px 140px,140px 140px,28px 28px,28px 28px;
  -webkit-mask-image:radial-gradient(ellipse 65% 60% at 50% 45%,#000 0%,transparent 72%);
  mask-image:radial-gradient(ellipse 65% 60% at 50% 45%,#000 0%,transparent 72%);
}

/* The seal, at architectural scale: range rings centred behind the card, with a
   slow sweep passing over them. Assessment is a scan; the sign-in screen is the
   scope idling. This is the one flourish on the page — everything else stays quiet. */
.auth-wrap::after{
  content:"";position:absolute;left:50%;top:45%;width:min(148vh,1180px);aspect-ratio:1;
  transform:translate(-50%,-50%);pointer-events:none;border-radius:50%;
  background:
    conic-gradient(from 0deg,var(--sweep) 0deg,transparent 58deg,transparent 360deg),
    radial-gradient(circle,var(--seal-wash) 0%,transparent 58%),
    repeating-radial-gradient(circle,transparent 0 78px,var(--seal-ring) 78px 79px);
  -webkit-mask-image:radial-gradient(circle,#000 18%,transparent 62%);
  mask-image:radial-gradient(circle,#000 18%,transparent 62%);
  animation:sweep 14s linear infinite;
}
@keyframes sweep{to{transform:translate(-50%,-50%) rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.auth-wrap::after{animation:none}}

.auth-card{
  position:relative;z-index:1;width:100%;max-width:424px;background:var(--card-bg);
  border:1px solid var(--line);border-radius:var(--r-xl);padding:var(--s-8);
  box-shadow:var(--card-highlight),var(--overlay);
}
/* a single accent hairline across the top edge of the card — the "seal is intact" line */
.auth-card::before{
  content:"";position:absolute;left:22%;right:22%;top:-1px;height:1px;
  background:linear-gradient(90deg,transparent,var(--accent),transparent);
  opacity:.7;
}
.auth-card .brand{justify-content:center;align-items:center;text-align:center;padding:0 0 var(--s-2)}
.auth-card .brand .wm{font-size:var(--t-xl)}
.authhead{text-align:center;margin:var(--s-1) 0 var(--s-5)}
.auth-divider{display:flex;align-items:center;gap:10px;margin:var(--s-5) 0;color:var(--faint);font-size:var(--t-xs);letter-spacing:.1em;text-transform:uppercase}
.auth-divider::before,.auth-divider::after{content:"";flex:1;height:1px;background:var(--line)}

/* ─────────────────────────── skeletons ────────────────────────────────── */
.skel{border-radius:var(--r-sm);background:var(--skeleton);background-size:200% 100%;animation:shimmer 1.4s linear infinite}
.skel.line{height:11px;margin:7px 0}
.skel.line.w60{width:60%} .skel.line.w40{width:40%}
@keyframes shimmer{to{background-position:-200% 0}}

/* ─────────────────────────── motion ───────────────────────────────────── */
@keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes draw{to{stroke-dashoffset:var(--to,0)}}

/* staged entrance. `--i` on the element = its place in the stagger. */
.reveal{opacity:0;animation:rise var(--dur-3) var(--ease) forwards;animation-delay:calc(var(--i,0) * 45ms)}

/* score arcs draw themselves once, on load. an arc encodes its value in its
   length — it does not need to also be lit. */
.arc{stroke-dasharray:var(--len,415);stroke-dashoffset:var(--len,415);animation:draw var(--dur-4) var(--ease) forwards 120ms}
.dash{stroke-dasharray:var(--len);stroke-dashoffset:var(--len);animation:draw 1.2s var(--ease) forwards .15s}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  .reveal{opacity:1}
  .arc,.dash{stroke-dashoffset:var(--to,0)}
}

/* ══════════════════════════════════════════════════════════════════════════
   REPORT — the assessment result view.
   Same tokens, same vocabulary, themes correctly. Status colours come from the
   status ramp; severity from the severity ramp; the accent appears only on the
   score arc, citations and the focus ring.
   ═══════════════════════════════════════════════════════════════════════ */
.rpt{max-width:none}
.rpt .bad{color:var(--crit)} .rpt .warn{color:var(--med)} .rpt .ok{color:var(--pass)}

/* status colour map — single source of truth, consumed via var(--c) */
.rpt .PASS{--c:var(--pass)}                     .rpt .FAIL{--c:var(--fail)}
.rpt .PARTIAL{--c:var(--partial)}               .rpt .MITIGATED{--c:var(--mitigated)}
.rpt .INSUFFICIENT_EVIDENCE{--c:var(--insufficient)}
.rpt .N_A{--c:var(--na)}                        .rpt .DEFERRED_DYNAMIC{--c:var(--deferred)}
.rpt .EXCLUDED{--c:var(--na)}

.rpt-head{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--s-5);margin-bottom:var(--s-5);flex-wrap:wrap}
.rpt-head h1{font-size:var(--t-2xl);font-weight:var(--w-strong);letter-spacing:var(--track-display);margin:6px 0}
.rpt-head .sub{color:var(--muted);font-size:var(--t-sm);margin:0}
.head-actions{display:flex;align-items:center;gap:10px;white-space:nowrap}
.verdict-chip{font-size:var(--t-sm);font-weight:var(--w-semi);padding:6px 13px;border-radius:var(--r-full);border:1px solid}
.verdict-chip.GREEN{color:var(--pass);border-color:var(--pass-line);background:var(--pass-bg)}
.verdict-chip.AMBER{color:var(--med);border-color:var(--med-line);background:var(--med-bg)}
.verdict-chip.RED{color:var(--crit);border-color:var(--crit-line);background:var(--crit-bg)}

.rpt .panel{padding:var(--s-5);margin-bottom:var(--s-4)}
.rpt .panel-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:var(--s-4);padding:0}
.rpt .panel-head .hint{font-size:var(--t-xs);color:var(--faint);letter-spacing:.03em}

.overview{display:grid;grid-template-columns:320px minmax(0,1fr);gap:var(--s-4);margin-bottom:var(--s-4)}
.overview .panel{margin-bottom:0}
.score-panel{display:flex;flex-direction:column;align-items:center;gap:var(--s-4)}
.donut-wrap{position:relative;width:180px;height:180px}
.donut-track{fill:none;stroke:var(--ring-track);stroke-width:14}
#donut-segs circle{fill:none;stroke-width:14;stroke-linecap:butt}
.donut-center{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.donut-center .score{font-family:var(--mono);font-size:var(--t-3xl);font-weight:var(--w-medium);line-height:1;letter-spacing:-.035em;font-variant-numeric:tabular-nums}
.donut-center .score .pct{font-size:var(--t-lg);font-weight:var(--w-medium);color:var(--faint)}
.donut-center .score.GREEN{color:var(--pass)} .donut-center .score.AMBER{color:var(--med)} .donut-center .score.RED{color:var(--crit)}
.score-cap{font-size:var(--t-sm);color:var(--text-2);margin-top:8px;font-weight:var(--w-medium)}
.score-sub{font-size:var(--t-2xs);color:var(--faint);letter-spacing:.05em}
.legend{list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:6px var(--s-4);width:100%}
.legend li{display:flex;align-items:center;gap:8px;font-size:var(--t-sm);color:var(--muted)}
.legend .dot{width:8px;height:8px;border-radius:2px;flex:none}
.legend b{color:var(--text-2);margin-left:auto;font-variant-numeric:tabular-nums;font-weight:var(--w-semi)}

.verdict-panel{display:flex;flex-direction:column;gap:var(--s-4)}
.kpis{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}
.rpt .kpi{background:var(--field-bg);border:1px solid var(--line-soft);border-radius:var(--r-md);padding:12px}
.rpt .kpi-n{font-size:var(--t-xl);font-weight:var(--w-strong);letter-spacing:var(--track-heading);line-height:1;margin:0}
.rpt .kpi-n.bad{color:var(--crit)} .rpt .kpi-n.warn{color:var(--med)}
.rpt .kpi-l{font-size:var(--t-2xs);color:var(--faint);text-transform:uppercase;letter-spacing:.05em;margin-top:7px;line-height:1.35;font-weight:var(--w-medium)}
.verdict-text{font-size:var(--t-base);line-height:1.6;padding:13px 15px;border-radius:var(--r-md);background:var(--field-bg);border:1px solid var(--line-soft);border-left:2px solid var(--c,var(--accent))}
.verdict-text.GREEN{--c:var(--pass)} .verdict-text.AMBER{--c:var(--med)} .verdict-text.RED{--c:var(--crit)}
.gate-note{font-size:var(--t-sm);color:var(--muted);line-height:1.6;margin:0}
.btn-solid{align-self:flex-start;background:var(--btn-bg);color:var(--btn-ink);font-weight:var(--w-semi);font-size:var(--t-base);padding:9px 16px;border-radius:var(--r-md);transition:background var(--dur-1) var(--ease)}
.btn-solid:hover{background:var(--btn-hover)}

.grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-4);margin-bottom:var(--s-4)}
.grid-2 .panel{margin-bottom:0}

.strong-lead{font-size:var(--t-base);color:var(--muted);margin:0 0 var(--s-3)}
.strong-chips{display:flex;flex-wrap:wrap;gap:7px}
.strong-chip{
  font-size:var(--t-sm);color:var(--pass);background:var(--pass-bg);border:1px solid var(--pass-line);
  padding:4px 10px;border-radius:var(--r-full);display:inline-flex;gap:7px;align-items:center;
}
.strong-chip b{color:var(--text-2);font-family:var(--mono);font-variant-numeric:tabular-nums}
.legend-note{font-size:var(--t-xs);color:var(--faint);line-height:1.8;margin:0 0 var(--s-3);padding:10px 12px;background:var(--field-bg);border:1px solid var(--line-soft);border-radius:var(--r-sm)}
.legend-note b{color:var(--muted);font-weight:var(--w-semi)}

/* framework ranking */
.rank{list-style:none;display:flex;flex-direction:column;gap:7px}
.rank-row{display:grid;grid-template-columns:130px minmax(0,1fr) 96px;align-items:center;gap:var(--s-3);cursor:pointer;padding:4px;border-radius:var(--r-sm);transition:background var(--dur-1) var(--ease)}
.rank-row:hover{background:var(--raised)}
.rank-label{font-size:var(--t-xs);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-bar{height:6px;background:var(--inset);border-radius:var(--r-full);overflow:hidden}
.rank-bar span{display:block;height:100%;background:var(--crit);border-radius:var(--r-full)}
.rank-meta{font-size:var(--t-xs);text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums}
.rank-meta b{color:var(--crit)} .rank-meta span{color:var(--faint);margin-left:4px}

/* section breakdown */
.sections{list-style:none;display:flex;flex-direction:column;gap:9px;max-height:330px;overflow:auto;padding-right:4px}
.sect-row{cursor:pointer;padding:8px;border-radius:var(--r-md);border:1px solid transparent;transition:background var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.sect-row:hover{background:var(--raised);border-color:var(--line)}
.sect-top{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:7px;gap:10px}
.sect-name{font-size:var(--t-base);font-weight:var(--w-medium)}
.sect-name .dim{font-weight:var(--w-normal);font-size:var(--t-xs)}
.sect-score{font-size:var(--t-base);font-weight:var(--w-semi);font-variant-numeric:tabular-nums;white-space:nowrap}
.sect-score.bad{color:var(--crit)} .sect-score.warn{color:var(--med)} .sect-score.ok{color:var(--pass)}
.sect-score small{font-size:var(--t-2xs);color:var(--faint);font-weight:var(--w-normal)}
.stack{display:flex;height:6px;border-radius:var(--r-full);overflow:hidden;background:var(--inset)}
.stack .seg{height:100%}
.stack .seg.PASS{background:var(--pass)} .stack .seg.FAIL{background:var(--fail)}
.stack .seg.PARTIAL{background:var(--partial)} .stack .seg.MITIGATED{background:var(--mitigated)}
.stack .seg.INSUFFICIENT_EVIDENCE{background:var(--insufficient)}
.stack .seg.N_A{background:var(--na)} .stack .seg.DEFERRED_DYNAMIC{background:var(--deferred)}
.sect-meta{font-size:var(--t-xs);color:var(--faint);margin-top:6px}

/* cve table */
table.cve{font-size:var(--t-sm)}
table.cve th{padding:0 10px 8px}
table.cve td{padding:9px 10px;vertical-align:top;border-bottom:1px solid var(--line-soft)}

.sev-tag{font-family:var(--mono);font-size:var(--t-2xs);font-weight:var(--w-semi);padding:2px 6px;border-radius:var(--r-xs);letter-spacing:.03em;white-space:nowrap}
.sev-tag.critical{color:var(--crit);background:var(--crit-bg)}
.sev-tag.high{color:var(--high);background:var(--high-bg)}
.sev-tag.medium{color:var(--med);background:var(--med-bg)}
.sev-tag.low{color:var(--low);background:var(--low-bg)}
.sev-tag.info{color:var(--info);background:var(--info-bg)}
.st-pill{font-size:var(--t-xs);font-weight:var(--w-semi);padding:3px 8px;border-radius:var(--r-sm);color:var(--c);background:color-mix(in srgb,var(--c) 14%,transparent);white-space:nowrap}

/* findings explorer */
.toolbar{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin-bottom:var(--s-3)}
.toolbar .spacer{flex:1}
.toolbar .search{flex:1;min-width:220px}
.toolbar .sel{width:auto;font-size:var(--t-sm);padding:8px 30px 8px 10px}
.toggle{display:flex;align-items:center;gap:7px;font-size:var(--t-sm);color:var(--muted);cursor:pointer;margin:0;white-space:nowrap}
.toggle input{margin:0}

/* the report's filter chips are buttons — distinct from the compact .chip above */
#statusChips{display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin-bottom:var(--s-4)}
#statusChips .chip{cursor:pointer;padding:4px 10px;border-radius:var(--r-full);border:1px solid var(--line);background:transparent;color:var(--muted);display:inline-flex;gap:6px;align-items:center;font-family:inherit;transition:border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
#statusChips .chip b{color:var(--text-2)}
#statusChips .chip:hover{border-color:var(--c,var(--muted-line))}
#statusChips .chip.active{background:color-mix(in srgb,var(--c,var(--accent)) 16%,transparent);border-color:var(--c,var(--accent));color:var(--text)}
#statusChips .chip.sev.critical{--c:var(--crit)} #statusChips .chip.sev.high{--c:var(--high)}
#statusChips .chip.sev.medium{--c:var(--med)}   #statusChips .chip.sev.low{--c:var(--low)}
.chip-sep{width:1px;height:16px;background:var(--line);margin:0 4px}

.fsection{border-top:1px solid var(--line-soft)}
.fsection-head{display:flex;align-items:center;gap:10px;padding:11px 4px;cursor:pointer;user-select:none;border-radius:var(--r-sm)}
.fsection-head .caret{color:var(--faint);font-size:10px;transition:transform var(--dur-2) var(--ease);width:12px;display:inline-block}
.fsection.collapsed .fsection-head .caret{transform:rotate(-90deg)}
.fsection.collapsed .fsection-body{display:none}
.fs-name{font-size:var(--t-base);font-weight:var(--w-semi)}
.fs-name .dim{font-weight:var(--w-normal);font-size:var(--t-xs)}
.fs-count{margin-left:auto;font-size:var(--t-xs);color:var(--faint)}

.finding{border-top:1px solid var(--line-soft)}
.finding:first-child{border-top:none}
.finding-row{display:grid;grid-template-columns:auto auto 150px minmax(0,1fr) auto;gap:11px;align-items:center;padding:10px 4px;cursor:pointer;border-radius:var(--r-sm);transition:background var(--dur-1) var(--ease)}
.finding-row:hover{background:var(--raised)}
.finding .ck{font-size:var(--t-xs);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono)}
.finding .stmt{font-size:var(--t-sm);color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.finding .exp{color:var(--faint);font-size:15px;width:16px;text-align:center;transition:transform var(--dur-2) var(--ease)}
.finding.open .exp{transform:rotate(45deg)}
.finding.open .stmt{white-space:normal}
.finding-detail{display:none;padding:4px 16px 14px 26px;border-left:2px solid var(--c);margin:0 4px 8px}
.finding.open .finding-detail{display:block;animation:fade var(--dur-2) var(--ease) both}
.dl{display:grid;grid-template-columns:110px minmax(0,1fr);gap:12px;padding:7px 0;font-size:var(--t-sm);border-top:1px solid var(--line-soft)}
.dl:first-child{border-top:none}
.dt{color:var(--faint);font-size:var(--t-2xs);text-transform:uppercase;letter-spacing:.05em;padding-top:2px}
.dl p{color:var(--muted);line-height:1.6}
.cites,.fwchips{display:flex;flex-wrap:wrap;gap:6px}
.cite{font-size:var(--t-xs);color:var(--accent);background:var(--accent-soft);padding:2px 7px;border-radius:var(--r-xs);font-family:var(--mono)}
.fwchip{font-size:var(--t-2xs);color:var(--muted);background:var(--inset);padding:2px 7px;border-radius:var(--r-xs);font-family:var(--mono)}
.empty-state{text-align:center;color:var(--faint);padding:var(--s-10);font-size:var(--t-base)}

/* lineage */
.lineage-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-3) var(--s-6);margin-bottom:var(--s-3)}
.lineage-grid>div{display:flex;flex-direction:column;gap:3px;min-width:0}
.ll{font-size:var(--t-2xs);color:var(--faint);text-transform:uppercase;letter-spacing:.05em}
.lv{font-size:var(--t-base);color:var(--text-2);overflow-wrap:anywhere;word-break:break-word}
/* ══════════════════════════ 2a — dashboard v2 ═════════════════════════════ */
/* Posture band: one framed instrument — gauge + month delta, org sparkline, and
   the severity tiles — replacing the old readout + gauge + trend + metric row. */
.postureband{display:grid;grid-template-columns:168px 1fr auto;gap:var(--s-6);align-items:center;padding:var(--s-5) var(--s-6)}
.pb-gauge{display:flex;flex-direction:column;align-items:center;gap:9px}
.pb-gauge .ring{width:104px;height:104px}
.pb-gauge .ring .val b{font-size:var(--t-2xl)}
.pb-delta{display:inline-flex;align-items:center;gap:5px;font-size:var(--t-sm);font-weight:var(--w-semi);font-variant-numeric:tabular-nums}
.pb-delta.up{color:var(--pass)} .pb-delta.down{color:var(--crit)} .pb-delta.flat{color:var(--faint)}
.pb-mid{min-width:0;display:flex;flex-direction:column;gap:8px}
.pb-mid .pb-h{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-4)}
.pb-mid .pb-h .sub{color:var(--muted);font-size:var(--t-sm)}
.pb-mid .pb-stats{display:flex;gap:var(--s-6);font-size:var(--t-sm);color:var(--muted)}
.pb-mid .pb-stats b{color:var(--text-2);font-variant-numeric:tabular-nums;font-weight:var(--w-semi)}
.pb-tiles{display:flex;gap:var(--s-3)}
.pb-tiles .sevtile{min-width:96px}
@media(max-width:1080px){.postureband{grid-template-columns:1fr}.pb-tiles{flex-wrap:wrap}}

/* Applications table — per-app standing (posture, trend, findings, badge). */
.spark{display:block}
.badgecell{display:inline-flex;align-items:center;gap:8px;white-space:nowrap}
.badgecell .away{font-size:var(--t-xs);color:var(--pass);font-variant-numeric:tabular-nums}

/* ── badge verify (7b) — stats ledger + mini window timeline ── */
.vledger{display:flex;flex-direction:column;margin-top:14px}
.vledger .vrow{display:flex;justify-content:space-between;align-items:baseline;gap:16px;padding:9px 0;border-top:1px solid var(--line-soft);font-size:var(--t-sm)}
.vledger .vrow:first-child{border-top:none}
.vledger .vk{color:var(--muted)}
.vledger .vv{font-family:var(--mono);color:var(--text);text-align:right;font-variant-numeric:tabular-nums}
.wtimeline{display:inline-flex;gap:5px;align-items:center}
.wnode{width:14px;height:14px;border-radius:50%;border:1px solid var(--line);background:var(--inset)}
.wnode.met{background:var(--pass-bg);border-color:var(--pass-line)}
.wnode.missed{background:var(--crit-bg);border-color:var(--crit-line)}
.wnode.open{background:var(--running-bg);border-color:var(--running-line)}

/* ── modal dialogs (Projects / Project detail / Users) ── */
.modal-overlay{position:fixed;inset:0;z-index:100;background:rgba(0,0,0,.55);display:flex;align-items:flex-start;justify-content:center;padding-top:14vh}
.modal-overlay[hidden]{display:none}
.modal-dialog{width:min(480px,92vw);box-shadow:var(--overlay)}
.modal-foot{display:flex;gap:10px;justify-content:flex-end;border-top:1px solid var(--line-soft);padding-top:16px;margin-top:4px}
@media(prefers-reduced-motion:no-preference){.modal-overlay:not([hidden]) .modal-dialog{animation:rise var(--dur-3) var(--ease)}}

/* ── ⌘K command palette ── */
.kbd{font-family:var(--mono);font-size:var(--t-2xs);border:1px solid var(--line);border-bottom-width:2px;border-radius:5px;padding:0 5px;color:var(--muted);background:var(--inset);margin-left:4px}
.cmdk-overlay{position:fixed;inset:0;z-index:100;background:rgba(0,0,0,.5);display:flex;align-items:flex-start;justify-content:center;padding-top:12vh}
.cmdk-overlay[hidden]{display:none}
.cmdk-box{width:min(620px,92vw);max-height:70vh;display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow),0 24px 64px rgba(0,0,0,.45);overflow:hidden}
.cmdk-input{border:none;border-bottom:1px solid var(--line);background:none;color:var(--text);font-size:var(--t-md);padding:16px 18px;outline:none;width:100%}
.cmdk-input::placeholder{color:var(--faint)}
.cmdk-results{overflow-y:auto;padding:6px}
.cmdk-group{font-size:var(--t-2xs);text-transform:uppercase;letter-spacing:.1em;color:var(--faint);padding:10px 12px 4px}
.cmdk-item{display:flex;align-items:baseline;gap:10px;padding:9px 12px;border-radius:var(--r-md);text-decoration:none;color:var(--text-2)}
.cmdk-item.sel{background:var(--nav-on-bg);color:var(--text)}
.cmdk-lbl{font-weight:var(--w-medium)}
.cmdk-sub{font-family:var(--mono);font-size:var(--t-xs);color:var(--faint);margin-left:auto}
.cmdk-empty{padding:20px 14px;color:var(--muted);text-align:center;font-size:var(--t-sm)}
.cmdk-foot{display:flex;gap:16px;padding:9px 14px;border-top:1px solid var(--line-soft);color:var(--faint);font-size:var(--t-2xs)}
.cmdk-foot .kbd{margin-left:0}

/* ── evidence tab (6d) — document-adjusted score instrument ── */
.ev-bar{position:relative;height:14px;border-radius:var(--r-full);background:var(--inset);border:1px solid var(--line)}
.ev-verified{position:absolute;top:0;left:0;height:100%;background:var(--accent);border-radius:var(--r-full) 0 0 var(--r-full)}
.ev-adjusted{position:absolute;top:0;height:100%;background:repeating-linear-gradient(45deg,var(--accent-2) 0 3px,transparent 3px 6px)}
.ev-tick{position:absolute;top:-4px;width:2px;height:22px;background:var(--pass);border-radius:1px}

/* ── cadence window timeline ── */
/* v3: each node carries its open date under the pip; a 2×2 segmented interval control. */
.cnode{display:flex;flex-direction:column;align-items:center;gap:6px;position:relative;z-index:1}
.cnode-date{font-family:var(--mono);font-size:9.5px;color:var(--faint);white-space:nowrap}
.segctl2{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.segctl2 .segopt{display:flex;align-items:center;justify-content:center;padding:9px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--inset);color:var(--muted);cursor:pointer;font-size:var(--t-sm);text-align:center;transition:color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease)}
.segctl2 .segopt input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}
.segctl2 .segopt:hover{color:var(--text-2)}
.segctl2 .segopt:has(input:checked){background:var(--surface);border-color:var(--accent);color:var(--text);box-shadow:var(--shadow)}
.cadence-line{display:flex;align-items:flex-start;justify-content:space-between;position:relative;padding:20px 10px 8px}
.cadence-line::before{content:"";position:absolute;left:18px;right:18px;top:30px;height:2px;background:var(--line-soft)}
.cwin{position:relative;z-index:1;width:22px;height:22px;border-radius:50%;display:grid;place-items:center;font-size:11px;font-weight:var(--w-strong);border:1px solid var(--line);background:var(--inset);color:var(--faint)}
.cwin.met{color:var(--pass);background:var(--pass-bg);border-color:var(--pass-line)}
.cwin.missed{color:var(--crit);background:var(--crit-bg);border-color:var(--crit-line)}
.cwin.open{background:var(--running-bg);border-color:var(--running-line)}
.cwin.open i{width:8px;height:8px;border-radius:50%;background:var(--running);animation:pulse 1.6s var(--ease-inout) infinite}
.cadence-legend{display:flex;flex-wrap:wrap;gap:var(--s-5);padding:2px 10px 14px;font-size:var(--t-sm);color:var(--muted)}
.cadence-legend span{display:inline-flex;align-items:center;gap:5px}
.cadence-legend b{font-family:var(--mono);font-weight:var(--w-strong);margin-right:2px}
.cadence-legend b.met{color:var(--pass)}
.cadence-legend b.missed{color:var(--crit)}
.cadence-legend b.open{color:var(--running)}
.cadence-legend b.pending{color:var(--faint)}
.cadence-legend b.met{color:var(--pass)} .cadence-legend b.missed{color:var(--crit)}
.cadence-legend b.open{color:var(--running)} .cadence-legend b.pending{color:var(--faint)}

/* ═══════════════════════════════════════════════════════════════════════════
   NAVIGATION SHELL — account menu, mobile drawer, responsive collapse
   Added in the IA/responsive pass. The sidebar is a fixed 244px rail on
   desktop; below 900px it becomes an off-canvas drawer toggled from the topbar.
   =========================================================================== */

/* Sidebar can scroll internally if the nav ever outgrows the viewport. */
.side{overflow-y:auto}

/* ── account menu (sidebar foot) ──────────────────────────────────────────
   The avatar row is now a menu button revealing personal settings + sign out,
   so those leave the primary nav. */
.acct{margin-top:auto;position:relative;padding-top:var(--s-3);border-top:1px solid var(--line)}
.acct-btn{
  width:100%;display:flex;align-items:center;gap:10px;text-align:left;
  background:none;border:none;cursor:pointer;font:inherit;color:var(--text);
  padding:6px;border-radius:var(--r-md);
  transition:background var(--dur-1) var(--ease);
}
.acct-btn:hover{background:var(--raised)}
.acct-btn:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.acct-btn .who{flex:1;min-width:0;font-size:var(--t-sm);font-weight:var(--w-medium);line-height:1.35}
.acct-btn .who small{display:block;color:var(--faint);font-weight:var(--w-normal);font-size:var(--t-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct-caret{color:var(--faint);flex:none;transition:transform var(--dur-2) var(--ease)}
.acct-btn[aria-expanded="true"] .acct-caret{transform:rotate(180deg)}
.acct-menu{
  position:absolute;bottom:calc(100% + 6px);left:0;right:0;z-index:40;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  box-shadow:var(--overlay);padding:5px;display:flex;flex-direction:column;gap:1px;
}
/* Progressive enhancement: visible by default so Security + Sign out are reachable with no
   JS; when JS is present (html.js, set pre-paint) it collapses to a toggle opened via .open,
   with no flash-of-open-menu on load. */
html.js .acct-menu{display:none}
html.js .acct-menu.open{display:flex}
.acct-menu a{
  display:block;padding:8px 11px;border-radius:var(--r-sm);color:var(--text-2);
  font-size:var(--t-base);font-weight:var(--w-medium);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.acct-menu a:hover{background:var(--raised);color:var(--text)}
.acct-menu a.on{color:var(--accent)}

/* ── hamburger (topbar) — hidden on desktop, shown when the rail collapses ── */
.navtoggle{
  display:none;align-items:center;justify-content:center;flex:none;
  width:38px;height:38px;margin-left:-6px;
  background:none;border:1px solid transparent;border-radius:var(--r-md);
  color:var(--text-2);cursor:pointer;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.navtoggle:hover{background:var(--raised);color:var(--text)}
.navtoggle:focus-visible{outline:2px solid var(--focus);outline-offset:2px}

/* ── scrim behind the open drawer ── */
.scrim{
  position:fixed;inset:0;z-index:49;background:rgba(3,6,12,.55);
  opacity:0;pointer-events:none;transition:opacity var(--dur-2) var(--ease);
}
.scrim.show{opacity:1;pointer-events:auto}
@media(min-width:901px){.scrim{display:none}}
@media(prefers-reduced-motion:reduce){.scrim{transition:none}}

/* ── responsive collapse ── */
@media(max-width:900px){
  .shell{grid-template-columns:1fr}
  .navtoggle{display:inline-flex}
  .topbar-new{display:none}          /* keep the narrow topbar uncluttered — Register stays in-page */
  .side{
    position:fixed;top:0;left:0;z-index:50;width:min(84vw,280px);height:100vh;
    transform:translateX(-100%);transition:transform var(--dur-3) var(--ease);
    box-shadow:var(--overlay);
  }
  .side.open{transform:translateX(0)}
  body.nav-open{overflow:hidden}
  .content{padding:var(--s-5) var(--s-5) var(--s-12)}
}
@media(max-width:900px) and (prefers-reduced-motion:reduce){
  .side{transition:none}
}

/* ═══════════════════════════════════════════════════════════════════════════
   TABLE TOOLS — sortable headers, inline filter box, show-more
   Behaviour in app.js (tableTools). All progressive: no attribute, no change.
   =========================================================================== */
th.th-sort{cursor:pointer;user-select:none;white-space:nowrap}
th.th-sort:hover{color:var(--text)}
th.th-sort::after{
  content:"";display:inline-block;width:0;height:0;margin-left:6px;vertical-align:middle;
  border-left:4px solid transparent;border-right:4px solid transparent;
  border-top:4px solid currentColor;opacity:.28;
}
th.th-sort[aria-sort=ascending]::after{border-top:0;border-bottom:5px solid currentColor;opacity:.95}
th.th-sort[aria-sort=descending]::after{border-bottom:0;border-top:5px solid currentColor;opacity:.95}
th.th-sort:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}

.table-more{display:flex;justify-content:center;padding:12px var(--s-5) var(--s-5)}

/* Compact filter input that sits in a panel head next to the title. */
.filterbox{
  height:32px;padding:0 12px;font:inherit;font-size:var(--t-sm);
  color:var(--text);background:var(--field-bg);border:1px solid var(--line);
  border-radius:var(--r-md);min-width:200px;
  transition:border-color var(--dur-1) var(--ease);
}
.filterbox::placeholder{color:var(--faint)}
.filterbox:focus{outline:none;border-color:var(--accent-line)}

/* ═══════════════════════════════════════════════════════════════════════════
   UTILITIES — atomic layout / spacing / text helpers.
   Prefer these over inline style= on new or edited markup; existing templates
   migrate incrementally. NOTE: .grid, .grid-2, .stack, .row-between, .chips are
   pre-existing COMPONENTS with specific meaning — they are not part of this set.
   All spacing maps to the 4px token scale so nothing drifts off-grid.
   =========================================================================== */
.u-flex{display:flex}
.u-iflex{display:inline-flex}
.u-col{flex-direction:column}
.u-wrap{flex-wrap:wrap}
.u-grow{flex:1;min-width:0}
.u-center{align-items:center}
.u-start{align-items:flex-start}
.u-end{align-items:flex-end}
.u-baseline{align-items:baseline}
.u-between{justify-content:space-between}
.u-jcenter{justify-content:center}
.u-jend{justify-content:flex-end}
.u-gap-1{gap:var(--s-1)} .u-gap-2{gap:var(--s-2)} .u-gap-3{gap:var(--s-3)}
.u-gap-4{gap:var(--s-4)} .u-gap-5{gap:var(--s-5)} .u-gap-6{gap:var(--s-6)}
.u-mt-2{margin-top:var(--s-2)} .u-mt-3{margin-top:var(--s-3)} .u-mt-4{margin-top:var(--s-4)}
.u-mt-5{margin-top:var(--s-5)} .u-mt-6{margin-top:var(--s-6)} .u-mt-auto{margin-top:auto}
.u-mb-2{margin-bottom:var(--s-2)} .u-mb-3{margin-bottom:var(--s-3)} .u-mb-4{margin-bottom:var(--s-4)}
.u-mb-5{margin-bottom:var(--s-5)} .u-mb-6{margin-bottom:var(--s-6)}
.u-full{width:100%}
.u-right{text-align:right} .u-tcenter{text-align:center}
.u-nowrap{white-space:nowrap}

/* Component: a footer action strip pinned to the bottom of a panel (open-window
   bars, form foots). Recurs as inline flex across app_detail/pentest templates. */
.panel-foot{
  display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap;
  background:var(--surface-2);border-top:1px solid var(--line-soft);
  padding:14px var(--s-5);
}
