/* ── NiyamKosh ─────────────────────────────────────────────────────────────
   Verification console for Indian Standards cited in government tenders.
   Palette is deliberately narrow: navy carries structure, amber means
   "needs a human", green means verified, red means dead. Nothing decorative.
   ────────────────────────────────────────────────────────────────────────── */

:root {
  --pet-900: #04222E;
  --pet-800: #08303F;
  --pet-700: #0E4054;
  --pet-600: #135A73;
  --pet-400: #2E88A6;

  --amber: #C25A0D;
  --amber-bg: #FCF1E7;
  --green: #1B6E30;
  --green-bg: #E9F4EC;
  --red: #A3231C;
  --red-bg: #FBECEA;
  --blue: #16688A;
  --blue-bg: #E6F2F6;

  --n-0:  #FFFFFF;
  --n-25: #FAFBFC;
  --n-50: #F2F6F8;
  --n-100:#E7EEF1;
  --n-150:#DBE5EA;
  --n-200:#C7D6DD;
  --n-300:#AEBCC9;
  --n-500:#6B7C8D;
  --n-600:#546272;
  --n-700:#3A4653;
  --n-900:#111C27;

  --bg:        var(--n-50);
  --surface:   var(--n-0);
  --surface-2: var(--n-25);
  --surface-3: var(--n-100);
  --line:      var(--n-150);
  --line-soft: var(--n-100);
  --line-hard: var(--n-200);
  --ink:       var(--n-900);
  --ink-2:     var(--n-600);
  --ink-3:     var(--n-500);
  --ink-4:     var(--n-300);

  /* The co-citation graph's edges. They used to borrow --line-hard, which is a
     border colour: #C7D6DD on a white ground is all but invisible once it is
     drawn at the low alpha thousands of overlapping lines require, so the graph
     read as a field of dots with no relationships in it — and the edges are the
     evidence. Its own token, dark enough to see and light enough that 13,000 of
     them do not turn the canvas into a solid block. */
  --graph-edge: #8DA2B2;

  --accent:    var(--amber);
  --accent-bg: var(--amber-bg);
  --ok:        var(--green);
  --ok-bg:     var(--green-bg);
  --bad:       var(--red);
  --bad-bg:    var(--red-bg);
  --info:      var(--blue);
  --info-bg:   var(--blue-bg);
  --brand:     var(--pet-700);

  --nav:        #08303F;
  --nav-line:   #14495D;
  --nav-ink:    #D2E6ED;
  --nav-ink-2:  #83AEBE;

  /* Brutalist: structure is drawn, not implied. A soft shadow suggests an edge
     without committing to one; these are hard offsets in ink, so a raised
     surface reads as a block sitting on the page rather than a card floating
     above it. --sh-3 stays a real shadow because a modal genuinely is in front
     of the page and has to say so. */
  --sh-1: 2px 2px 0 var(--line-hard);
  --sh-2: 3px 3px 0 var(--ink);
  --sh-3: 8px 8px 0 rgba(4,34,46,.28);

  /* No radii. A government form is a set of boxes and this one says so. */
  --r-1: 0px;
  --r-2: 0px;
  --r-3: 0px;

  /* One border weight, used everywhere structure matters. */
  --bw: 2px;

  --bar-h: 52px;
  /* The second row of the masthead, where the sections live. */
  --nav-row-h: 47px;

  --k1:#135A73; --k2:#C25A0D; --k3:#1B6E30; --k4:#0E7078;
  --k5:#6B4C9A; --k6:#96731A; --k7:#A34468; --k8:#5B6B7C;

  /* Motion. Durations and easings live here so every animation in the product
     is timed against the same scale, and so one edit changes all of them.
     The rules that go with them: animate transform and opacity only; enter
     animations run once, never on every scroll; anything with more than a
     couple of hundred elements is drawn on a canvas, not the DOM. */
  --t-fast: 120ms; --t-base: 200ms; --t-slow: 320ms; --t-reveal: 600ms;
  --ease-out: cubic-bezier(.2,.7,.2,1); --ease-in-out: cubic-bezier(.65,0,.35,1);
  --stagger: 40ms;
}

[data-theme="dark"] {
  --bg:        #04121A;
  --surface:   #08202B;
  --surface-2: #0C2836;
  --surface-3: #123340;
  --line:      #17394A;
  --line-soft: #123040;
  --line-hard: #205063;
  --ink:       #E7EEF4;
  --ink-2:     #A0B4C4;
  --ink-3:     #7A8FA1;
  --ink-4:     #55697B;
  /* Lighter than the dark ground, by the same reasoning as the light theme. */
  --graph-edge: #4E7A92;

  --accent:    #F0913E;
  --accent-bg: #33210F;
  --ok:        #4FB86E;
  --ok-bg:     #102A18;
  --bad:       #E8776D;
  --bad-bg:    #2E1614;
  --info:      #62A5E0;
  --info-bg:   #10233A;
  --brand:     #4FB3D1;

  --nav:        #041920;
  --nav-line:   #103240;
  --nav-ink:    #C2DDE6;
  --nav-ink-2:  #6E96A6;

  --sh-1: 2px 2px 0 var(--line-hard);
  --sh-2: 3px 3px 0 #000;
  --sh-3: 8px 8px 0 rgba(0,0,0,.6);

  --k1:#3FA6C4; --k2:#F0913E; --k3:#4FB86E; --k4:#35A9B4;
  --k5:#9C82D4; --k6:#CBA93C; --k7:#DB809B; --k8:#7E93A6;
}

* { box-sizing: border-box; }
html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 13.5px/1.5 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,h2,h3,h4 { font-family: 'Merriweather', Georgia, serif; margin: 0; letter-spacing: -.015em; font-weight: 900; }
h1 { font-size: 21px; line-height: 1.25; }
h2 { font-size: 16px; }
h3 { font-size: 13.5px; font-weight: 700; }
p { margin: 0; }

.mono, code, .num { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace; font-variant-numeric: tabular-nums; }
.num { font-variant-numeric: tabular-nums; }

.eyebrow {
  font-size: 9.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}
.dim { color: var(--ink-2); }
.dimmer { color: var(--ink-3); }
.sm { font-size: 12px; }
.xs { font-size: 11px; }

a { color: var(--brand); text-underline-offset: 2px; }
a:hover { text-decoration: underline; }

svg.i { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; flex: none; display: block; }
svg.i.sm { width: 14px; height: 14px; }
svg.i.lg { width: 20px; height: 20px; }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-thumb { background: var(--line-hard); border: 3px solid transparent; background-clip: content-box; border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: var(--ink-4); background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 3px; }

/* ── Shell ───────────────────────────────────────────────────────────────── */

.shell { display: flex; flex-direction: column; min-height: 100vh; }

/* Brand bar: petrol blue, deliberately cyan-shifted so it doesn't read as
   stock corporate navy. Amber is the only accent allowed against it. */
.topnav {
  min-height: 52px; flex: none; position: sticky; top: 0; z-index: 45;
  background: var(--nav); border-bottom: 1px solid var(--nav-line);
  display: flex; align-items: center; gap: 16px; padding: 0 16px;
}
.brand { display: flex; align-items: center; gap: 9px; flex: none; }
.brand .glyph { width: 30px; height: 30px; flex: none; }
.brand .nm { font-family: 'Merriweather', serif; font-weight: 900; font-size: 13.5px; color: #fff; line-height: 1.1; letter-spacing: -.01em; }
.brand .dv { font-size: 9.5px; color: var(--nav-ink-2); letter-spacing: .03em; margin-top: 1px; }
.brand-sep { width: 1px; height: 24px; background: var(--nav-line); flex: none; }

/* ── Navigation ────────────────────────────────────────────────────────────
   Typographic, and grouped. Ten icons in a row carried no information the word
   beside them did not carry better, and an icon-plus-badge strip is the shape
   every generated dashboard has. The labels are the content, so the labels are
   the nav.

   The three group eyebrows are the only structural device here, and they say
   something true: Work is what an officer does, Register is what they look a
   standard up in, Evidence is the system's account of itself. Hairline rules
   separate the groups rather than boxes, because the groups are a reading
   order, not three containers. */

.tabwrap { position: relative; flex: 1; min-width: 0; display: flex; }
.tabwrap::after {
  content: ''; position: absolute; right: 0; top: 0; bottom: 0; width: 28px;
  pointer-events: none; opacity: 0; transition: opacity .18s;
  background: linear-gradient(90deg, transparent, var(--nav));
}
.tabwrap.spill::after { opacity: 1; }
.tabs {
  display: flex; align-items: stretch; flex: 1; min-width: 0;
  overflow-x: auto; scrollbar-width: none; height: 52px;
}
.tabs::-webkit-scrollbar { display: none; }

.navgroup { display: flex; align-items: stretch; position: relative; padding-left: 12px; }
.navgroup + .navgroup { margin-left: 4px; }
/* A hairline, not a border-box: the rule belongs between groups, not around
   them, and it stops short of the bar's full height so it reads as a divider
   rather than a frame. */
.navgroup + .navgroup::before {
  content: ''; position: absolute; left: 0; top: 16px; bottom: 16px;
  width: 1px; background: var(--nav-line);
}
.navgroup-lb {
  position: absolute; left: 12px; top: 7px;
  font: 700 8px/1 'JetBrains Mono', monospace; letter-spacing: .16em;
  text-transform: uppercase; color: var(--nav-ink-2); opacity: .62;
  pointer-events: none; white-space: nowrap;
}

.tab {
  display: flex; align-items: flex-end; gap: 5px; height: 52px;
  padding: 0 7px 11px; color: var(--nav-ink-2); font-size: 12.5px;
  cursor: pointer; white-space: nowrap; user-select: none;
  border-bottom: 2px solid transparent; background: none;
  transition: color .12s, border-color .12s;
}
.tab:first-child { padding-left: 0; }
.tab:hover { color: #fff; }
.tab.on { color: #fff; font-weight: 600; border-bottom-color: var(--accent); }
/* The row counts, inline and mono — a numeral beside its label, not a pill.
   --nav-ink-2 on a 9% chip measured 3.19:1 against the nav, under the 4.5 a
   small numeral needs; plain text on the bar itself is far clearer. */
.tab .ct {
  font: 500 10px/1 'JetBrains Mono', monospace; color: var(--nav-ink-2);
  font-variant-numeric: tabular-nums; opacity: .75;
}
.tab.on .ct { color: #fff; opacity: .8; }

/* Narrow screens: the eyebrows would cost a row of height they cannot pay for,
   so the groups keep their dividers and lose their labels. */
@media (max-width: 860px) {
  .navgroup-lb { display: none; }
  .navgroup { padding-left: 10px; }
  .tab { align-items: center; padding-bottom: 0; }
}

/* The sections are the navigation; the right-hand controls are conveniences,
   so they are what gives ground when the bar runs short. The keyboard hint
   stays because it is the thing the label was advertising. */
/* These labels were dropped to buy width for ten tabs sharing this row. The
   tabs have their own row now, so the identity row keeps its words until a
   screen genuinely cannot hold them. */
@media (max-width: 900px) {
  .navsearch span:not(.kbd) { display: none; }
  .navsearch { padding: 0 8px; }
  .demo-btn span { display: none; }
  .demo-btn { padding: 0 9px; }
}

/* Below this the row counts are what has to go for all ten sections to stay
   reachable without scrolling. Hidden, not abbreviated: "27.7k" would be the
   one rounded number in a project that reports exact counts with their
   denominators everywhere else, and the exact figures are on the Standards,
   Certification and Tenders screens and in the sources footer regardless. */
/* Same reasoning for the row counts: they cost width the tabs no longer have
   to compete for, so they stay down to a small tablet. */
/* The counts cost about 120px across three tabs. With them on, ten labels stop
   fitting a 1000px window and Benchmark falls off the end — so they appear
   where there is room for them and the labels always win. */
@media (max-width: 1150px) {
  .tab .ct { display: none; }
}

/* The last of the slack, spent so all ten sections stay on screen down to a
   1200px laptop. Below that the strip scrolls, which is what the spill shadow
   on the right edge is for. */
@media (max-width: 1100px) {
  .navgroup { padding-left: 11px; }
  .navgroup-lb { left: 11px; }
  .tab { padding-left: 9px; padding-right: 9px; }
}

.role-btn {
  height: 30px; padding: 0 11px; border-radius: 15px; cursor: pointer;
  background: rgba(255,255,255,.07); border: 1px solid var(--nav-line);
  color: var(--nav-ink-2); font: 600 11px/1 'Public Sans', sans-serif;
  letter-spacing: .04em; text-transform: uppercase;
  transition: background .12s, color .12s, border-color .12s;
}
.role-btn:hover { background: rgba(255,255,255,.13); color: #fff; }
.role-btn.admin { background: var(--accent); border-color: var(--accent); color: #fff; }

.nav-right { display: flex; align-items: center; gap: 6px; flex: none; }
.navsearch {
  display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px;
  background: rgba(255,255,255,.07); border: 1px solid var(--nav-line); border-radius: var(--r-1);
  color: var(--nav-ink-2); font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap;
  transition: background .12s, color .12s, border-color .12s;
}
.navsearch:hover { background: rgba(255,255,255,.12); color: #fff; border-color: rgba(255,255,255,.22); }
.nav-ib {
  width: 30px; height: 30px; border-radius: var(--r-1); border: 1px solid transparent;
  background: transparent; color: var(--nav-ink-2); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; position: relative;
  transition: background .12s, color .12s;
}
.nav-ib:hover { background: rgba(255,255,255,.1); color: #fff; }
.nav-ib .badge {
  position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px;
  border-radius: 7px; background: var(--accent); color: #fff;
  font: 700 9px/14px 'JetBrains Mono', monospace; text-align: center;
}

.kbd { font: 500 9.5px/1 'JetBrains Mono', monospace; padding: 3px 5px; border-radius: 4px;
  background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.12); color: inherit; }
.kbd.light { background: var(--surface-3); border-color: var(--line); color: var(--ink-3); }

/* Contextual strip under the brand bar */
.subbar {
  height: 44px; flex: none; position: sticky; top: calc(var(--bar-h) + var(--nav-row-h)); z-index: 35;
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  backdrop-filter: saturate(1.5) blur(9px);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px; padding: 0 20px;
}
.crumbs { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-3); min-width: 0; }
.crumbs b { color: var(--ink); font-weight: 600; }
.crumbs .i { color: var(--ink-4); }
.bar-sp { flex: 1; }
.conn { display: flex; align-items: center; font-size: 11px; color: var(--ink-3); white-space: nowrap; }
.dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; margin-right: 6px; }
.dot.up { background: #22A45D; box-shadow: 0 0 0 3px rgba(34,164,93,.16); }
.dot.down { background: #D4483E; box-shadow: 0 0 0 3px rgba(212,72,62,.16); }

.pins-pop {
  position: fixed; top: 56px; right: 14px; width: 236px; z-index: 55;
  background: var(--surface); border: 1px solid var(--line-hard); border-radius: var(--r-2);
  box-shadow: var(--sh-3); padding: 8px; display: none;
}
.pins-pop.on { display: block; }
.pins-pop .hd { display: flex; align-items: center; gap: 6px; padding: 3px 6px 7px; }
.pin-row {
  display: flex; align-items: center; gap: 7px; padding: 6px 7px; border-radius: var(--r-1);
  font: 500 11.5px/1 'JetBrains Mono', monospace; cursor: pointer; color: var(--ink);
}
.pin-row:hover { background: var(--surface-3); }
.pin-row .rm { margin-left: auto; color: var(--ink-3); opacity: 0; }
.pin-row:hover .rm { opacity: 1; }
.pin-row .rm:hover { color: var(--bad); }

.body { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* ── Page frame ──────────────────────────────────────────────────────────── */

.sheet {
  padding: 20px; max-width: 1520px; width: 100%; margin: 0 auto;
  /* Named so children can size against this column rather than the window. */
  container: sheet / inline-size;
}

.view { display: none; }
.view.on { display: block; animation: rise .24s cubic-bezier(.2,.7,.3,1); }
@keyframes rise { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }

.vh { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.vh h1 { font-size: 19px; }
/* Facts, not prose. Counts, sources and thresholds — what an operator checks. */
.vh .meta {
  font: 400 11px/1.5 'JetBrains Mono', monospace; color: var(--ink-3);
  margin-top: 6px; font-variant-numeric: tabular-nums;
}
.build { font: 400 10.5px/1 'JetBrains Mono', monospace; color: var(--ink-4); white-space: nowrap; }
.vh-act { margin-left: auto; display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }

/* ── Controls ────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  height: 30px; padding: 0 11px; border-radius: var(--r-1);
  background: var(--surface); color: var(--ink); border: 1px solid var(--line-hard);
  font: 600 12px/1 'Public Sans', sans-serif; cursor: pointer;
  transition: background .12s, border-color .12s, transform .08s;
  white-space: nowrap;
}
.btn:hover { background: var(--surface-3); border-color: var(--ink-4); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn.pri { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn.pri:hover { filter: brightness(1.14); background: var(--brand); }
.btn.acc { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.acc:hover { filter: brightness(1.1); background: var(--accent); }
.btn.q { border-color: transparent; background: transparent; color: var(--ink-2); }
.btn.q:hover { background: var(--surface-3); color: var(--ink); }
.btn.wide { width: 100%; height: 36px; font-size: 13px; }
.btn.tiny { height: 24px; padding: 0 8px; font-size: 11px; }
.ibtn {
  width: 30px; height: 30px; border-radius: var(--r-1); display: inline-flex;
  align-items: center; justify-content: center; cursor: pointer;
  background: transparent; border: 1px solid transparent; color: var(--ink-2);
  transition: background .12s, color .12s;
}
.ibtn:hover { background: var(--surface-3); color: var(--ink); }
.ibtn.bordered { border-color: var(--line-hard); background: var(--surface); }

input[type=text], input[type=search], input[type=number], textarea, select {
  width: 100%; height: 32px; padding: 0 10px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line-hard); border-radius: var(--r-1);
  font: 400 12.5px/1 'Public Sans', sans-serif;
  transition: border-color .12s, box-shadow .12s;
}
select { padding-right: 26px; cursor: pointer; }
textarea { height: auto; min-height: 118px; padding: 9px 11px; resize: vertical; line-height: 1.55; font: 400 12px/1.55 'JetBrains Mono', monospace; }
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 14%, transparent);
}
input::placeholder, textarea::placeholder { color: var(--ink-4); }
label.f { display: block; margin-bottom: 5px; }

.seg { display: inline-flex; background: var(--surface-3); border-radius: var(--r-1); padding: 2px; gap: 2px; }
.seg button {
  height: 24px; padding: 0 10px; border: none; background: transparent; cursor: pointer;
  border-radius: 4px; font: 600 11.5px/1 'Public Sans', sans-serif; color: var(--ink-2);
}
.seg button.on { background: var(--surface); color: var(--ink); box-shadow: var(--sh-1); }

/* ── Surfaces ────────────────────────────────────────────────────────────── */

.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); box-shadow: var(--sh-1); margin-bottom: 14px; }
.card > .in { padding: 15px 16px; }
.card > .hd {
  padding: 12px 16px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 10px;
}
.card > .hd h3 { flex: 1; min-width: 0; }
.card > .hd .hint { font-size: 11px; color: var(--ink-3); white-space: nowrap; }
.card > .ft { padding: 9px 16px; border-top: 1px solid var(--line-soft); background: var(--surface-2); font-size: 11px; color: var(--ink-3); border-radius: 0 0 var(--r-2) var(--r-2); }

.grid { display: grid; gap: 14px; }
/* Grid items default to min-width:auto and refuse to shrink below their content,
   so one wide table stretches its card past the track and out of the viewport.
   This belongs at every width, not only on phones. */
.grid > * { min-width: 0; }
.card { min-width: 0; }
.scroll { min-width: 0; max-width: 100%; overflow-x: auto; }
.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)); }
.c21 { grid-template-columns: minmax(0,1.9fr) minmax(0,1fr); }
/* minmax(0,…) not a bare 1fr: a bare fr track is minmax(auto,1fr) and
   refuses to shrink below its content, so one 560px table drags the whole
   page wider than the viewport instead of scrolling inside its own box. */
.c12 { grid-template-columns: minmax(0,1fr) minmax(0,1.9fr); }
@media (max-width:1180px){ .c4{grid-template-columns:repeat(2,minmax(0,1fr));} .c3,.c21,.c12{grid-template-columns:minmax(0,1fr);} }
@media (max-width:840px){ .c2,.c4{grid-template-columns:minmax(0,1fr);} }

/* ── Metrics ─────────────────────────────────────────────────────────────── */

.kpis { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); border: 1px solid var(--line); border-radius: var(--r-2); overflow: hidden; background: var(--surface); box-shadow: var(--sh-1); margin-bottom: 14px; }
@media (max-width:900px){ .kpis{grid-template-columns:repeat(2,minmax(0,1fr));} }
.kpi { padding: 13px 16px; border-right: 1px solid var(--line-soft); position: relative; }
.kpi:last-child { border-right: none; }
@media (max-width:900px){ .kpi:nth-child(2n){border-right:none;} .kpi:nth-child(-n+2){border-bottom:1px solid var(--line-soft);} }
.kpi .lb { display: flex; align-items: center; gap: 6px; font-size: 10.5px; color: var(--ink-3); font-weight: 600; letter-spacing: .02em; }
.kpi .vl { font: 900 25px/1.1 'Merriweather', serif; letter-spacing: -.02em; margin-top: 6px; font-variant-numeric: tabular-nums; }
.kpi .sub { font: 400 10.5px/1.4 'JetBrains Mono', monospace; color: var(--ink-3); margin-top: 4px; }
.kpi .rule { position: absolute; left: 0; top: 13px; bottom: 13px; width: 2px; border-radius: 0 2px 2px 0; }
.kpi.ok .rule { background: var(--ok); } .kpi.ok .vl { color: var(--ok); }
.kpi.warn .rule { background: var(--accent); } .kpi.warn .vl { color: var(--accent); }
.kpi.bad .rule { background: var(--bad); } .kpi.bad .vl { color: var(--bad); }
.kpi.plain .rule { background: var(--line-hard); }

/* ── Pills ───────────────────────────────────────────────────────────────── */

.pill {
  display: inline-flex; align-items: center; gap: 4px; height: 19px; padding: 0 7px;
  border-radius: 10px; font: 700 10.5px/1 'Public Sans', sans-serif; white-space: nowrap;
  border: 1px solid transparent;
}
.pill.ok { background: var(--ok-bg); color: var(--ok); border-color: color-mix(in srgb,var(--ok) 22%,transparent); }
.pill.bad { background: var(--bad-bg); color: var(--bad); border-color: color-mix(in srgb,var(--bad) 22%,transparent); }
.pill.warn { background: var(--accent-bg); color: var(--accent); border-color: color-mix(in srgb,var(--accent) 26%,transparent); }
.pill.info { background: var(--info-bg); color: var(--info); border-color: color-mix(in srgb,var(--info) 22%,transparent); }
.pill.mute { background: var(--surface-3); color: var(--ink-2); border-color: var(--line); }

.chips { display: flex; flex-wrap: wrap; gap: 5px; }
.chip {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 4px 0 9px;
  background: var(--surface-2); border: 1px solid var(--line-hard); border-radius: 12px;
  font: 500 11.5px/1 'JetBrains Mono', monospace; animation: pop .16s ease;
}
.chip.static { padding-right: 9px; }
.chip .x { width: 16px; height: 16px; border: none; background: none; color: var(--ink-3); cursor: pointer; border-radius: 50%; display: grid; place-items: center; padding: 0; }
.chip .x:hover { background: var(--bad-bg); color: var(--bad); }
@keyframes pop { from { opacity:0; transform: scale(.94); } to { opacity:1; transform:none; } }

.fchips { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.fchip {
  display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 4px 0 8px;
  background: var(--info-bg); color: var(--info); border: 1px solid color-mix(in srgb,var(--info) 20%,transparent);
  border-radius: 11px; font-size: 11px; font-weight: 600;
}
.fchip button { border: none; background: none; color: inherit; cursor: pointer; padding: 0 2px; display: grid; place-items: center; }

/* ── Tables ──────────────────────────────────────────────────────────────── */

.tbl { border: 1px solid var(--line); border-radius: var(--r-2); overflow: hidden; background: var(--surface); }
.tbl .scroll { overflow: auto; max-height: 560px; }
.tbl.auto .scroll { max-height: none; }
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
thead th {
  position: sticky; top: 0; z-index: 2; text-align: left; white-space: nowrap;
  background: var(--surface-2); color: var(--ink-3);
  font: 700 10px/1 'Public Sans', sans-serif; letter-spacing: .07em; text-transform: uppercase;
  padding: 9px 12px; border-bottom: 1px solid var(--line);
}
thead th.sortable { cursor: pointer; user-select: none; }
thead th.sortable:hover { color: var(--ink); }
thead th .sarr { display: inline-block; margin-left: 4px; opacity: .35; }
thead th.sorted .sarr { opacity: 1; color: var(--accent); }
thead th.r, tbody td.r { text-align: right; }
tbody td { padding: 8px 12px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
tbody tr:last-child td { border-bottom: none; }
tbody tr.hit { cursor: pointer; }
tbody tr.hit:hover { background: var(--surface-2); }
tbody tr.hit:hover .rowgo { opacity: 1; }
.rowgo { opacity: 0; color: var(--ink-3); transition: opacity .12s; }
td.mono, th.mono { font-family: 'JetBrains Mono', monospace; font-size: 11.5px; font-variant-numeric: tabular-nums; }
.tbl .toolbar { padding: 11px 12px; border-bottom: 1px solid var(--line-soft); display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.tbl .toolbar input[type=search] { flex: 1; min-width: 190px; }
.tbl .toolbar select { width: auto; min-width: 138px; }
.tbl .status { padding: 7px 12px; border-bottom: 1px solid var(--line-soft); font-size: 11px; color: var(--ink-3); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ── Charts ──────────────────────────────────────────────────────────────── */

.legend { display: flex; flex-direction: column; gap: 6px; font-size: 12px; min-width: 0; }
.legend .r { display: flex; align-items: center; gap: 8px; }
.legend .sw { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.legend .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legend .vv { margin-left: auto; padding-left: 12px; font: 500 11.5px/1 'JetBrains Mono', monospace; color: var(--ink-2); font-variant-numeric: tabular-nums; }

.bars { display: flex; flex-direction: column; gap: 8px; }
.brow { display: grid; grid-template-columns: minmax(84px,32%) 1fr auto; gap: 10px; align-items: center; font-size: 12px; }
.brow .bl { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.btrack { display: block; height: 8px; background: var(--surface-3); border-radius: 4px; overflow: hidden; }
.bfill { display: block; height: 100%; width: 0; border-radius: 4px; transition: width .7s cubic-bezier(.2,.8,.3,1); }
.brow .bv { font: 500 11.5px/1 'JetBrains Mono', monospace; color: var(--ink-2); min-width: 30px; text-align: right; font-variant-numeric: tabular-nums; }

.histo { display: flex; align-items: flex-end; gap: 6px; min-height: 148px; }
.hcol { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 5px; }
.hbar { display: block; width: 100%; height: 0; min-height: 2px; background: var(--k1); border-radius: 3px 3px 0 0; transition: height .7s cubic-bezier(.2,.8,.3,1); }
.hcol:hover .hbar { background: var(--accent); }
.hval, .hlab { font: 500 9.5px/1 'JetBrains Mono', monospace; color: var(--ink-3); }

.meter { display: flex; height: 22px; border-radius: var(--r-1); overflow: hidden; background: var(--surface-3); }
.meter > span { display: block; width: 0; transition: width .8s cubic-bezier(.2,.8,.3,1); }

.dnut .v { font: 900 20px/1 'Merriweather', serif; fill: var(--ink); }
.dnut .l { font: 700 8.5px/1 'Public Sans', sans-serif; fill: var(--ink-3); letter-spacing: .09em; text-transform: uppercase; }
svg .sg { transition: opacity .14s; }
svg .sg:hover { opacity: .78; }

/* ── Notices ─────────────────────────────────────────────────────────────── */

.note {
  display: flex; gap: 10px; align-items: flex-start; padding: 10px 13px;
  border-radius: var(--r-2); font-size: 12.5px; margin-bottom: 13px;
  border: 1px solid; line-height: 1.5;
}
.note .i { margin-top: 1px; flex: none; }
.note.warn { background: var(--accent-bg); border-color: color-mix(in srgb,var(--accent) 28%,transparent); color: var(--ink); }
.note.warn .i { color: var(--accent); }
.note.bad { background: var(--bad-bg); border-color: color-mix(in srgb,var(--bad) 28%,transparent); color: var(--ink); }
.note.bad .i { color: var(--bad); }
.note.ok { background: var(--ok-bg); border-color: color-mix(in srgb,var(--ok) 24%,transparent); color: var(--ink); }
.note.ok .i { color: var(--ok); }
.note.info { background: var(--info-bg); border-color: color-mix(in srgb,var(--info) 22%,transparent); color: var(--ink); }
.note.info .i { color: var(--info); }

.blank { padding: 34px 20px; text-align: center; color: var(--ink-3); }
.blank .i { width: 26px; height: 26px; margin: 0 auto 9px; color: var(--ink-4); stroke-width: 1.3; }
.blank .t { font-size: 13px; color: var(--ink-2); font-weight: 600; }
.blank .s { font-size: 11.5px; margin-top: 3px; }

.skel { background: linear-gradient(90deg,var(--surface-2) 25%,var(--surface-3) 50%,var(--surface-2) 75%); background-size: 200% 100%; animation: sh 1.25s infinite linear; border-radius: var(--r-1); }
@keyframes sh { from { background-position: 200% 0; } to { background-position: -200% 0; } }

.spin { width: 13px; height: 13px; border: 2px solid color-mix(in srgb,currentColor 25%,transparent); border-top-color: currentColor; border-radius: 50%; animation: rot .65s linear infinite; display: inline-block; }
@keyframes rot { to { transform: rotate(360deg); } }

/* ── Toasts ──────────────────────────────────────────────────────────────── */

.toasts { position: fixed; bottom: 18px; right: 18px; z-index: 90; display: flex; flex-direction: column; gap: 8px; }
.toast {
  display: flex; align-items: center; gap: 9px; padding: 9px 13px; min-width: 220px;
  background: var(--pet-900); color: #E6F2F6; border-radius: var(--r-2);
  box-shadow: var(--sh-3); font-size: 12.5px; animation: tin .2s cubic-bezier(.2,.8,.3,1);
}
[data-theme="dark"] .toast { background: var(--surface-3); border: 1px solid var(--line-hard); }
.toast.ok .i { color: #56C97A; } .toast.bad .i { color: #EE8279; } .toast.info .i { color: #74B4EC; }
@keyframes tin { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }

/* ── Dropzone ────────────────────────────────────────────────────────────── */

.drop {
  border: 1.5px dashed var(--line-hard); border-radius: var(--r-2); padding: 22px 16px;
  text-align: center; cursor: pointer; background: var(--surface-2);
  transition: border-color .14s, background .14s;
}
.drop:hover { border-color: var(--brand); background: var(--surface-3); }
.drop.over { border-color: var(--accent); background: var(--accent-bg); }
.drop .i { width: 22px; height: 22px; margin: 0 auto 7px; color: var(--ink-3); }
.drop .t { font-size: 12.5px; font-weight: 600; }
.drop .s { font-size: 11px; color: var(--ink-3); margin-top: 3px; }

/* ── Drawer ──────────────────────────────────────────────────────────────── */

.scrim { position: fixed; inset: 0; background: rgba(4,28,38,.4); z-index: 60; opacity: 0; pointer-events: none; transition: opacity .2s; }
.scrim.on { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; inset: 0 0 0 auto; width: min(580px,94vw); z-index: 61;
  background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: var(--sh-3); transform: translateX(100%);
  transition: transform .26s cubic-bezier(.22,.8,.26,1);
  display: flex; flex-direction: column;
}
.drawer.on { transform: none; }
.drawer .hd { padding: 14px 16px; border-bottom: 1px solid var(--line); display: flex; align-items: flex-start; gap: 10px; }
.drawer .bd { padding: 16px; overflow-y: auto; flex: 1; }
.drawer .ft { padding: 11px 16px; border-top: 1px solid var(--line); display: flex; gap: 7px; background: var(--surface-2); }

dl.kv { display: grid; grid-template-columns: 122px minmax(0,1fr); gap: 6px 14px; font-size: 12.5px; margin: 0; }
dl.kv dt { font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-3); padding-top: 2px; }
dl.kv dd { margin: 0; word-break: break-word; }

.ev { border-left: 2px solid var(--line-hard); padding: 6px 0 6px 11px; margin-bottom: 8px; }
.ev:hover { border-left-color: var(--accent); }
.ev .t { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.ev .s { font-size: 11.5px; color: var(--ink-2); margin-top: 3px; }
.jump { color: var(--brand); cursor: pointer; font-weight: 600; }
.jump:hover { text-decoration: underline; }

.sect { display: flex; align-items: center; gap: 8px; margin: 18px 0 8px; }
.sect h3 { font-size: 12.5px; }
.sect .ln { flex: 1; height: 1px; background: var(--line); }

/* ── Palette ─────────────────────────────────────────────────────────────── */

.pal-bg { position: fixed; inset: 0; background: rgba(4,28,38,.45); z-index: 80; display: none; justify-content: center; padding-top: 11vh; backdrop-filter: blur(2px); }
.pal-bg.on { display: flex; }
.pal { width: min(640px,93vw); max-height: 62vh; background: var(--surface); border: 1px solid var(--line-hard); border-radius: var(--r-3); box-shadow: var(--sh-3); display: flex; flex-direction: column; overflow: hidden; animation: pin .16s cubic-bezier(.2,.8,.3,1); }
@keyframes pin { from { opacity: 0; transform: translateY(-7px) scale(.985); } to { opacity: 1; transform: none; } }
.pal .top { display: flex; align-items: center; gap: 9px; padding: 0 14px; border-bottom: 1px solid var(--line); }
.pal .top .i { color: var(--ink-3); }
.pal input { border: none; height: 46px; padding: 0; font-size: 14px; background: transparent; }
.pal input:focus { box-shadow: none; }
.pal .list { overflow-y: auto; padding: 6px; }
.pal .gl { font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); padding: 8px 10px 4px; }
.pal .it { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--r-1); cursor: pointer; font-size: 12.5px; }
.pal .it .i { color: var(--ink-3); }
.pal .it.on { background: var(--surface-3); }
.pal .it.on .i { color: var(--accent); }
.pal .it .sub { margin-left: auto; font-size: 10px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; }
.pal .ft { border-top: 1px solid var(--line); padding: 7px 13px; display: flex; gap: 14px; font-size: 10.5px; color: var(--ink-3); }

/* ── Graph ───────────────────────────────────────────────────────────────── */

.gwrap { position: relative; height: 660px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); overflow: hidden; }
#gcanvas { width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
#gcanvas.grab { cursor: grabbing; }
.gnode circle { stroke: var(--surface); stroke-width: 1.5; }
.gnode text { font: 500 8.5px/1 'JetBrains Mono', monospace; fill: var(--ink-2); pointer-events: none; }
.gnode { cursor: pointer; }
.gnode.off { opacity: .09; }
.gnode.pick circle { stroke: var(--accent); stroke-width: 2.5; }
.gnode.path circle { stroke: var(--info); stroke-width: 3; }
.gedge { stroke: var(--ink-4); }
.gedge.off { opacity: .035 !important; }
.gedge.lit { stroke: var(--accent) !important; opacity: .85 !important; }
.gedge.path { stroke: var(--info) !important; opacity: .95 !important; stroke-width: 3 !important; }

.gpanel { position: absolute; z-index: 4; }
.gtools { top: 11px; left: 11px; display: flex; gap: 5px; }
.gtools button { width: 29px; height: 29px; border-radius: var(--r-1); border: 1px solid var(--line-hard); background: var(--surface); color: var(--ink-2); cursor: pointer; display: grid; place-items: center; box-shadow: var(--sh-1); }
.gtools button:hover { color: var(--ink); background: var(--surface-3); }
.gside { top: 11px; right: 11px; width: 232px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); box-shadow: var(--sh-1); padding: 11px; }
.gside .grp { margin-bottom: 11px; }
.gside .grp:last-child { margin-bottom: 0; }
.gkey { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line); font-size: 10.5px;
        max-height: 168px; overflow-y: auto; }
.gkey .r { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; color: var(--ink-2); }
.gkey .sw { width: 8px; height: 8px; border-radius: 50%; }
.gstat { bottom: 11px; right: 11px; display: flex; gap: 15px; background: color-mix(in srgb,var(--surface) 93%,transparent); border: 1px solid var(--line); border-radius: var(--r-2); padding: 7px 13px; }
.gstat .lb { font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 700; }
.gstat .vl { font: 500 12.5px/1.3 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; }
.gtip { position: absolute; z-index: 6; pointer-events: none; display: none; background: var(--pet-900); color: #E6F2F6; border-radius: var(--r-1); padding: 7px 10px; font-size: 11px; box-shadow: var(--sh-2); max-width: 250px; }
[data-theme="dark"] .gtip { background: var(--surface-3); border: 1px solid var(--line-hard); color: var(--ink); }
.gtip .a { font: 600 11.5px/1.3 'JetBrains Mono', monospace; }
.gtip .b { opacity: .78; font-size: 10px; margin-top: 2px; }

input[type=range] { width: 100%; height: 20px; accent-color: var(--accent); padding: 0; border: none; background: none; }
input[type=range]:focus { box-shadow: none; }
label.ck { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--ink-2); cursor: pointer; }
label.ck input { width: auto; height: auto; accent-color: var(--brand); }

/* ── Hero ────────────────────────────────────────────────────────────────────
   The co-citation graph is the whole argument of this project, so it opens the
   console rather than hiding on a tab. Live data, not artwork.
   ────────────────────────────────────────────────────────────────────────── */

.hero {
  position: relative; overflow: hidden; margin-bottom: 16px;
  border-radius: var(--r-3); border: 1px solid var(--nav-line);
  background:
    radial-gradient(120% 140% at 78% 10%, #10516B 0%, transparent 58%),
    radial-gradient(90% 120% at 8% 92%, #0A3B4E 0%, transparent 62%),
    linear-gradient(150deg, #06222E 0%, #041A24 100%);
  min-height: 320px; display: flex; align-items: center;
}
.hero-canvas { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .85; }
.hero-canvas .he { stroke: #2E88A6; fill: none; }
/* One fade for the whole figure. Fading each line and node separately meant
   thousands of concurrent animations competing for the compositor. */
.hero-canvas .he-g { opacity: 0; animation: fadeUp .8s .15s ease forwards; }
.hero-canvas .hn-g { opacity: 0; animation: fadeUp .5s .5s ease forwards; }
.hero-canvas .hn { fill: #47A9C7; }
.hero-canvas .hn.hot { fill: var(--accent); }
.hero-veil {
  position: absolute; inset: 0;
  background: linear-gradient(100deg, #04222E 26%, rgba(4,34,46,.86) 46%, rgba(4,34,46,.15) 78%);
}
.hero-in { position: relative; z-index: 2; padding: 30px 34px; width: 100%; }
.hero-eyebrow { font: 700 9.5px/1 'JetBrains Mono', monospace; letter-spacing: .22em; text-transform: uppercase; color: #6FB6CE; }
.hero-h {
  font-family: 'Merriweather', serif; font-weight: 900; color: #fff;
  font-size: clamp(26px, 3.4vw, 44px); line-height: 1.08; letter-spacing: -.03em;
  margin: 13px 0 0; max-width: 15ch;
}
.hero-h em { font-style: normal; color: var(--accent); }
.hero-sub { color: #A7C8D6; font-size: 13px; margin-top: 12px; max-width: 46ch; line-height: 1.55; }
.hero-figs { display: flex; gap: 34px; margin-top: 26px; flex-wrap: wrap; }
.hero-fig .n {
  font-family: 'Merriweather', serif; font-weight: 900; font-size: 27px; color: #fff;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.hero-fig .l { font: 500 10px/1 'JetBrains Mono', monospace; color: #7FB2C6; letter-spacing: .08em; text-transform: uppercase; margin-top: 7px; }
.hero-fig.hot .n { color: var(--accent); }
@media (max-width: 700px) { .hero-in { padding: 22px 20px; } .hero-veil { background: linear-gradient(180deg, rgba(4,34,46,.9), rgba(4,34,46,.75)); } }

/* ── Unit chart, removed ─────────────────────────────────────
   It was one cell per cited standard. At 488 that reads; at 1,986 the cells are
   below the size where two of them can be told apart, so all it said was "a lot,
   mostly green" — a percentage drawn the long way round. The ratio is one
   number, and one number gets the dial in .gg below.
   ─────────────────────────────────────────────────────────────────────── */

/* ── Dead-citation reveal ────────────────────────────────────────────────── */

.strike { position: relative; display: inline-block; }
.strike::after {
  content: ''; position: absolute; left: 0; top: 52%; height: 2px; width: 0;
  background: var(--bad); animation: cut .5s .25s cubic-bezier(.3,.8,.3,1) forwards;
}
@keyframes cut { to { width: 100%; } }
.succ { display: inline-flex; align-items: center; gap: 7px; opacity: 0; animation: fadeUp .45s .6s ease forwards; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ── Presenter mode ──────────────────────────────────────────────────────── */

.demo-btn {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px;
  border-radius: var(--r-1); border: 1px solid var(--accent); background: transparent;
  color: var(--accent); font: 600 12px/1 'Public Sans', sans-serif; cursor: pointer;
  white-space: nowrap; transition: background .13s, color .13s;
}
.demo-btn:hover { background: var(--accent); color: #fff; }
.demo-btn.live { background: var(--accent); color: #fff; }

.demobar {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%) translateY(140%);
  width: min(760px, calc(100vw - 32px)); z-index: 85;
  background: var(--pet-900); color: #E6F2F6; border: 1px solid var(--nav-line);
  border-radius: var(--r-3); box-shadow: var(--sh-3);
  transition: transform .3s cubic-bezier(.2,.8,.26,1);
  overflow: hidden;
}
[data-theme="dark"] .demobar { background: var(--surface-3); border-color: var(--line-hard); color: var(--ink); }
.demobar.on { transform: translateX(-50%) translateY(0); }
.demobar .track { height: 2px; background: rgba(255,255,255,.12); }
.demobar .track > i { display: block; height: 100%; background: var(--accent); width: 0; transition: width .25s linear; }
.demobar .row { display: flex; align-items: center; gap: 14px; padding: 12px 15px; }
.demobar .step {
  font: 600 10px/1 'JetBrains Mono', monospace; letter-spacing: .08em;
  color: var(--accent); flex: none; padding-top: 2px;
}
.demobar .txt { flex: 1; min-width: 0; }
.demobar .txt .h { font-family: 'Merriweather', serif; font-weight: 900; font-size: 13.5px; }
.demobar .txt .p { font-size: 12px; opacity: .82; margin-top: 3px; line-height: 1.45; }
.demobar .ctl { display: flex; gap: 4px; flex: none; }
.demobar .ctl button {
  width: 30px; height: 30px; border-radius: var(--r-1); cursor: pointer;
  background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.13);
  color: inherit; display: grid; place-items: center;
}
.demobar .ctl button:hover { background: rgba(255,255,255,.18); }
.demobar .ctl button.wide { width: auto; padding: 0 10px; font: 600 11.5px/1 'Public Sans', sans-serif; gap: 5px; display: flex; align-items: center; }

/* Spotlight: a fixed veil blurs the page, and the lit panel is raised above it
   so it stays sharp. The panel needs its own solid background or the blurred
   page shows through it. */
.demo-veil {
  position: fixed; inset: 0; z-index: 70; pointer-events: none;
  backdrop-filter: blur(5px) saturate(.72);
  -webkit-backdrop-filter: blur(5px) saturate(.72);
  background: color-mix(in srgb, var(--pet-900) 34%, transparent);
  opacity: 0; transition: opacity .32s ease;
}
.demo-veil.on { opacity: 1; }
[data-theme="dark"] .demo-veil { background: rgba(0,0,0,.5); }

.spot {
  position: relative; z-index: 71;
  background: var(--surface); border-radius: var(--r-2);
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 9px color-mix(in srgb, var(--accent) 18%, transparent),
              0 28px 70px -14px rgba(4,34,46,.55);
  /* The lit panel used to appear at full strength the instant the class
     landed, which read as a cut rather than a move. It now rises into the
     light over --t-slow, so the eye follows it from the previous target. */
  transition: box-shadow var(--t-slow) var(--ease-out),
              transform var(--t-slow) var(--ease-out);
  animation: spot-in var(--t-slow) var(--ease-out) both;
}
@keyframes spot-in {
  from { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent),
                     0 0 0 0 transparent, 0 10px 24px -14px rgba(4,34,46,.3);
         transform: scale(.994); }
}
@media (prefers-reduced-motion: reduce) {
  .spot { animation: none; }
}

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

/* ── Misc ────────────────────────────────────────────────────────────────── */

.copyable { display: inline-flex; align-items: center; gap: 5px; }
.copyable .cp { opacity: 0; color: var(--ink-3); cursor: pointer; transition: opacity .12s; }
.copyable:hover .cp { opacity: 1; }
.copyable .cp:hover { color: var(--brand); }

.prov { max-width: 1520px; margin: 0 auto; width: 100%; border-top: 1px solid var(--line); padding: 13px 20px 28px; font-size: 10.5px; line-height: 1.7; color: var(--ink-3); }
.prov b { color: var(--ink-2); }

.menu-btn { display: none; }

@media (max-width:1100px) {
  .brand .dv { display: none; }
  .navsearch span:not(.kbd) { display: none; }
}
@media (max-width:900px) {
  .tab span:not(.ct) { display: none; }
  .tab { padding: 0 13px; }
  .sheet { padding: 14px; }
  .subbar { padding: 0 14px; }
  .gside { position: static; width: auto; margin: 10px; }
}

@media print {
  .topnav, .subbar, .vh-act, .no-print, .toasts, .pins-pop { display: none !important; }
  body { background: #fff; }
  .card { box-shadow: none; break-inside: avoid; }
  .view { display: none !important; }
  .view.on { display: block !important; }
  .tbl .scroll { max-height: none; overflow: visible; }
}

/* ── findings ───────────────────────────────────────────────────────────────
   One card per finding. The left rule carries severity so a page of them is
   scannable at arm's length; everything else stays in the existing palette. */

.find {
  border: 1px solid var(--line); border-left: 3px solid var(--ink-4);
  border-radius: 8px; background: var(--surface); padding: 13px 15px;
  display: flex; flex-direction: column; gap: 8px;
}
.find + .find { margin-top: 9px; }
.find.high { border-left-color: var(--bad); }
.find.medium { border-left-color: var(--accent); }
.find.low { border-left-color: var(--ink-4); }
.find .top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.find .hl { font-weight: 600; font-size: 13.5px; color: var(--ink); flex: 1; min-width: 200px; }
.find .dt { font-size: 12.5px; line-height: 1.62; color: var(--ink-2); }
.find .act {
  font-size: 12.5px; color: var(--ink); background: var(--surface-2);
  border: 1px solid var(--line-soft); border-radius: 6px; padding: 7px 10px;
  display: flex; gap: 7px; align-items: flex-start;
}
.find .act b { font-weight: 600; }
.find .src {
  font-size: 11px; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ink-3); display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.find .btns { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.find.done { opacity: .62; }
.find .verdict { font-size: 12px; font-weight: 600; }
.find .verdict.acc { color: var(--ok); }
.find .verdict.ovr { color: var(--accent); }

.verdict-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 13px 16px; border-radius: 9px; margin-top: 16px;
  border: 1px solid var(--line);
}
.verdict-bar.blocking { background: var(--bad-bg); border-color: color-mix(in srgb,var(--bad) 24%,transparent); }
.verdict-bar.review { background: var(--accent-bg); border-color: color-mix(in srgb,var(--accent) 26%,transparent); }
.verdict-bar.clean { background: var(--ok-bg); border-color: color-mix(in srgb,var(--ok) 22%,transparent); }
.verdict-bar.unreadable { background: var(--surface-3); }
.verdict-bar .vt { font-size: 15px; font-weight: 650; letter-spacing: -.01em; }
.verdict-bar .vs { font-size: 12.5px; color: var(--ink-2); flex: 1; min-width: 220px; line-height: 1.6; }

/* ── narrow screens ─────────────────────────────────────────────────────────
   A procurement officer checking a tender on a phone is a real case, and the
   desktop grid collapses badly below ~700px: KPIs squeeze to two illegible
   columns, tables force the page to scroll sideways, and the drawer covers the
   screen with no way back. Each rule below fixes one of those. */

@media (max-width: 700px) {
  .kpis { grid-template-columns: minmax(0,1fr); }
  .kpi { border-right: none; border-bottom: 1px solid var(--line-soft); }
  .kpi:last-child { border-bottom: none; }

  .vh { flex-direction: column; align-items: flex-start; gap: 10px; }
  .vh-act { width: 100%; flex-wrap: wrap; }
  .sheet { padding: 12px 11px; }
  .subbar { padding: 0 11px; }

  /* Tables scroll inside their own box; the page itself never does. A grid
     track defaults to min-width:auto, so without this the 560px table pushes
     the whole layout wider than the screen instead of scrolling in place. */
  .grid > *, .grid { min-width: 0; }
  /* overflow:hidden makes the card a formatting context of its own, so a wide
     table inside it can no longer stretch the card — and through it the whole
     document — past the viewport. min-width:0 alone does not do this. */
  .card { min-width: 0; overflow: hidden; }
  .scroll { min-width: 0; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  table { min-width: 560px; }

  .drawer { width: 100%; max-width: none; }

  .find { padding: 11px 12px; }
  .find .hl { min-width: 0; font-size: 13px; }
  .find .top { gap: 6px; }
  .verdict-bar { padding: 11px 12px; gap: 8px; }
  .verdict-bar .vt { font-size: 14px; }

  .hero-h { font-size: 30px; line-height: 1.16; }

  /* Bar charts put the label in a 32% column, which is about 100px on a phone —
     "Electrical cables and wiring" truncates to three words and a dash. Stack
     the label over its bar instead of shrinking it. */
  .brow { grid-template-columns: 1fr auto; row-gap: 3px; }
  .brow .bl { grid-column: 1 / -1; white-space: normal; overflow: visible; }
  .chips { max-height: 168px; overflow-y: auto; }

  /* The tab strip becomes the only navigation, so keep the labels. It already
     scrolls horizontally on its own. */
  .tab span:not(.ct) { display: inline; }
  .tab { padding: 0 11px; font-size: 12.5px; }

  /* Without this the top bar's own contents set a ~560px min-content width for
     the whole document, and every view below stretches to match it — the page
     then renders 560px wide inside a 390px screen. The bar has to be allowed to
     shrink before anything else can. */
  html, body { overflow-x: hidden; }
  .topnav { min-width: 0; gap: 6px; padding: 0 10px; }
  .brand .nm { font-size: 12px; }
  .brand-sep, .navsearch, #pins-btn { display: none; }
  .demo-btn span, .role-btn span { display: none; }
  .crumbs { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sheet { max-width: 100%; }
}

/* Anything the keyboard reaches must be visible when it gets there. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
.tab:focus-visible { outline-offset: -3px; }

/* A discarded generation, shown rather than hidden: it is the only way to see
   the guard working, and the only way to tell an over-strict rule from a real
   catch. Struck through so it can never be mistaken for the clause itself. */
blockquote.rejected {
  margin: 0; padding: 9px 12px; border-left: 3px solid var(--bad);
  background: var(--surface-2); border-radius: 0 6px 6px 0;
  font-size: 12.5px; line-height: 1.65; color: var(--ink-2);
  text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--bad) 45%, transparent);
}

/* ── language switcher ──────────────────────────────────────────────────────
   A Government of India console has to work in Hindi. Devanagari has taller
   ascenders and a continuous headline stroke, so it needs a little more line
   height than Latin at the same size or the shirorekha collides with the row
   above it. */

.lang-wrap { position: relative; display: flex; }
.lang-btn { display: flex; align-items: center; gap: 5px; padding: 0 9px; width: auto; }
.lang-btn span { font-size: 11px; font-weight: 600; letter-spacing: .04em; }
.lang-pop {
  position: absolute; top: calc(100% + 7px); right: 0; min-width: 158px;
  background: var(--surface); border: 1px solid var(--line-hard);
  border-radius: var(--r-2); box-shadow: var(--sh-3); padding: 5px;
  display: none; z-index: 70;
}
.lang-pop.on { display: block; }
.lang-pop button {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 8px 10px; background: none; border: 0; cursor: pointer;
  border-radius: var(--r-1); font-size: 13px; color: var(--ink); text-align: left;
}
.lang-pop button:hover { background: var(--surface-3); }
.lang-pop button[aria-selected="true"] { color: var(--accent); font-weight: 600; }
.lang-pop button .en { font-size: 11px; color: var(--ink-3); }

/* Devanagari alongside the Latin stack, everywhere. */
:root[lang="hi"] body,
:root[lang="hi"] .tab, :root[lang="hi"] .btn, :root[lang="hi"] h1,
:root[lang="hi"] h2, :root[lang="hi"] h3 {
  font-family: 'Public Sans', 'Noto Sans Devanagari', -apple-system, system-ui, sans-serif;
}
:root[lang="hi"] { --lh-bump: 1.12; }
:root[lang="hi"] h1, :root[lang="hi"] h3, :root[lang="hi"] .tab { line-height: 1.45; }
:root[lang="hi"] .vh h1 { font-size: 24px; }
:root[lang="hi"] .eyebrow, :root[lang="hi"] .lb { letter-spacing: .02em; }

/* IS numbers, standard titles and notification references stay in the register's
   own language whatever the interface is set to — they are cited text. */
.src-text { font-family: 'Public Sans', system-ui, sans-serif; }

/* Allied standards, grouped by the role each one plays in a tender. */
.rel { padding: 8px 0 9px; border-bottom: 1px solid var(--line-soft); display: flex;
       flex-wrap: wrap; align-items: center; gap: 7px; }
.rel:last-child { border-bottom: none; }
.rel .s { flex-basis: 100%; font-size: 12.5px; color: var(--ink-2); line-height: 1.55; }
.rel .xs { flex-basis: 100%; }

/* One suggested edit to the tender. Not a decision to approve — a line the
   officer either acts on in their own document or does not. */
.edit { padding: 12px 0 13px; border-bottom: 1px solid var(--line-soft); }
.edit:first-child { padding-top: 2px; }
.edit:last-child { border-bottom: none; padding-bottom: 2px; }
.edit .top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.edit .top .mono { font-size: 13.5px; font-weight: 600; }
.edit .why { margin-top: 5px; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); }
.edit .src { margin-top: 6px; font-size: 11px; color: var(--ink-3); }
blockquote.clause-suggest {
  margin: 9px 0 0; padding: 10px 12px; background: var(--surface-2);
  border-left: 3px solid var(--accent); border-radius: 0 6px 6px 0;
  font-size: 12.5px; line-height: 1.62; color: var(--ink);
}
.edit .btn.tiny { margin-top: 8px; }

/* Paged tables: the control that fetches the next page. Centred under the
   table so it reads as "there is more", not as a toolbar action. */
.loadmore { display: flex; justify-content: center; padding: 11px 0 3px; }
.loadmore:empty { display: none; }
.loadmore .dimmer { margin-left: 6px; font-size: 11px; }


/* ── retrieval trace rail ────────────────────────────────────────────────────
   The path an answer took, drawn before the answer itself. Every number on it
   is read from the response: how deep each retriever went, how many candidates
   the fusion produced, which filters demoted something and how many, and what
   the gate compared. It is the system's own explanation, not a decoration —
   if a stage cannot state what it did, it does not get a pill. */

.trace { display: flex; align-items: stretch; gap: 0; flex-wrap: wrap;
         margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--line);
         border-radius: var(--r-2); background: var(--surface-2); }
.trace .tstep { display: flex; align-items: center; gap: 8px;
                animation-delay: inherit; }
.trace .tstep > .tpill, .trace .tstep .tpill { animation-delay: inherit; }
.trace .tsep { width: 16px; height: 1px; background: var(--line-hard); align-self: center;
               margin: 0 3px; flex: 0 0 auto; }
.trace .tpill { display: inline-flex; flex-direction: column; gap: 1px;
                padding: 5px 9px; border-radius: var(--r-1); border: 1px solid var(--line);
                background: var(--surface); min-width: 0;
                opacity: 0; transform: translateY(4px);
                animation: traceIn var(--t-base) var(--ease-out) forwards; }
.trace .tpill .tk { font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase;
                    color: var(--ink-3); font-weight: 700; white-space: nowrap; }
.trace .tpill .tv { font: 500 11.5px/1.25 'JetBrains Mono', ui-monospace, monospace;
                    font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap; }
.trace .tpill.acted { border-color: var(--amber); background: var(--amber-bg); }
.trace .tpill.acted .tk { color: var(--amber); }
.trace .tpill.stop { border-color: var(--bad); background: var(--bad-bg); }
.trace .tpill.stop .tk { color: var(--bad); }
.trace .tpill.ok { border-color: var(--ok); background: var(--ok-bg); }
.trace .tpill.ok .tk { color: var(--ok); }
.trace .tpill.par { border-style: dashed; }
.trace .tnote { flex-basis: 100%; margin-top: 9px; font-size: 11px; color: var(--ink-3); }

@keyframes traceIn { to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .trace .tpill { animation: none; opacity: 1; transform: none; }
}

@media (max-width: 860px) {
  .trace { gap: 6px; }
  .trace .tsep { display: none; }
}


/* ── document x-ray ──────────────────────────────────────────────────────────
   The tender's own text, with each citation underlined where it occurs and
   coloured by what the register says. The underline is a border rather than a
   background so the words stay readable and the page does not turn into a
   highlighter test. */

.xray-card { margin-bottom: 16px; }
.xray { max-height: 260px; overflow-y: auto; padding: 12px 14px;
        background: var(--surface-2); border: 1px solid var(--line);
        border-radius: var(--r-1); white-space: pre-wrap; word-break: break-word;
        font: 400 12.5px/1.75 ui-monospace, 'JetBrains Mono', monospace;
        color: var(--ink-2); }
.xcite { background: none; color: inherit; padding: 1px 0 2px;
         border-bottom: 2px solid var(--ink-4); cursor: pointer;
         font-weight: 600; border-radius: 0;
         opacity: 0; animation: xciteIn var(--t-base) var(--ease-out) forwards; }
.xcite:hover, .xcite:focus-visible { background: var(--surface-3); outline: none; }
.xcite:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
.xcite.x-ok     { border-bottom-color: var(--ok);    color: var(--ok); }
.xcite.x-super  { border-bottom-color: var(--amber); color: var(--amber); }
.xcite.x-dead   { border-bottom-color: var(--bad);   color: var(--bad); }
.xcite.x-unres  { border-bottom-style: dotted; border-bottom-color: var(--ink-3); color: var(--ink-3); }

@keyframes xciteIn { to { opacity: 1; } }

/* The finding the reader was sent to, briefly lit so the jump is legible. */
.edit.flash { animation: findingFlash 1.4s var(--ease-out); }
@keyframes findingFlash {
  0%, 100% { background: transparent; }
  12%      { background: var(--amber-bg); }
}

@media (prefers-reduced-motion: reduce) {
  .xcite { animation: none; opacity: 1; }
  .edit.flash { animation: none; background: var(--amber-bg); }
}

@media print {
  .xray { max-height: none; overflow: visible; }
}


/* ── confidence arc ──────────────────────────────────────────────────────────
   The score read against the thresholds the gate compares it to, so "0.721"
   is legible as a decision rather than a decimal. */

.gov-grid { display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: start; }
.gov-main { min-width: 0; }
@media (max-width: 900px) { .gov-grid { grid-template-columns: 1fr; } }

.carc { display: flex; flex-direction: column; align-items: center; gap: 4px;
        min-width: 172px; }
.carc svg { width: 120px; height: 86px; overflow: visible; }
.carc-n { font: 600 17px 'JetBrains Mono', ui-monospace, monospace; fill: var(--ink);
          font-variant-numeric: tabular-nums; }
.carc-l { font-size: 8.5px; letter-spacing: .1em; text-transform: uppercase; fill: var(--ink-3);
          font-weight: 700; }
.carc-fill { stroke-dasharray: var(--arc-len); stroke-dashoffset: var(--arc-len);
             animation: arcSweep var(--t-reveal) var(--ease-out) forwards; }
@keyframes arcSweep { to { stroke-dashoffset: 0; } }

/* The officer's verdict, on the admin arc. The percentage leads because that
   is the number the officer was shown; the raw score sits under it because a
   complaint is argued in the score. */
.carc-n { font-variant-numeric: tabular-nums; }
.carc-p { font-size: 11px; fill: var(--ink-3); }
.carc-v { font: 700 11px/1.3 'Public Sans', sans-serif; letter-spacing: .04em;
  text-transform: uppercase; margin-bottom: 3px; }
.carc-v.vd-yes { color: var(--ok); }
.carc-v.vd-maybe { color: var(--accent); }
.carc-v.vd-no { color: var(--bad); }
.carc-act { display: block !important; font-size: 11px; line-height: 1.45; color: var(--ink-2);
  margin-bottom: 6px; }
.carc-raw { font-size: 10px; color: var(--ink-3); padding-top: 6px;
  border-top: 1px solid var(--line-soft); }
.carc-key { font-size: 10px; color: var(--ink-3); text-align: left; width: 100%; }
.carc-key > div { display: flex; align-items: center; gap: 5px; margin-bottom: 2px; }
.carc-key .sw { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
.carc-key .carc-cal { display: block; margin-top: 6px; padding-top: 6px;
                      border-top: 1px solid var(--line); line-height: 1.45; color: var(--ink-2); }

@media (prefers-reduced-motion: reduce) {
  .carc-fill { animation: none; stroke-dashoffset: 0; }
}


/* ── health index charts ─────────────────────────────────────────────────────
   Two dots on one absolute axis: slate is the documents read, red is the ones
   citing a standard BIS has withdrawn, and the distance between them is the
   finding. It was a bar inside a bar, which asks the eye to compare two lengths
   sharing a start — the comparison it is worst at. The counts stay printed
   beside the row: a share alone hides whether it was measured over eleven
   documents or five hundred. */

.db { display: flex; flex-direction: column; gap: 10px; }
.db-key { display: flex; gap: 18px; font-size: 11px; color: var(--ink-2); margin-bottom: 2px; }
.db-key span { display: inline-flex; align-items: center; gap: 6px; }
.db-key i { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.db-r { display: grid; grid-template-columns: 148px 1fr 92px; gap: 12px; align-items: center;
        opacity: 0; animation: barIn var(--t-base) var(--ease-out) forwards; }
.db-l { font-size: 11.5px; color: var(--ink-2); overflow: hidden;
        text-overflow: ellipsis; white-space: nowrap; }
.db-t { position: relative; height: 13px; }
.db-t::before {
  content: ''; position: absolute; left: 0; right: 0; top: 6px;
  border-top: 1px dotted var(--line-hard);
}
.db-line { position: absolute; top: 5.5px; height: 2px; background: var(--ink-4); }
.db-d { position: absolute; top: 1px; width: 11px; height: 11px; border-radius: 50%;
        transform: translateX(-50%); box-shadow: 0 0 0 2px var(--surface); }
.db-r:hover .db-d { outline: 2px solid var(--accent); outline-offset: 1px; }
.db-n { font: 500 11px 'JetBrains Mono', ui-monospace, monospace; color: var(--ink-3);
        font-variant-numeric: tabular-nums; text-align: right; }
.db-n b { color: var(--bad); font-weight: 600; }
.db-ax { display: flex; justify-content: space-between; margin-left: 160px; margin-right: 104px;
         font: 500 10px 'JetBrains Mono', monospace; color: var(--ink-4); }
.db-ax em { font-style: normal; }

/* One square per document. */
.dotarr { display: flex; flex-direction: column; gap: 7px; }
.da-r { display: grid; grid-template-columns: 148px 1fr 34px; gap: 12px; align-items: center; }
.da-l { font-size: 11.5px; color: var(--ink-2); overflow: hidden;
        text-overflow: ellipsis; white-space: nowrap; }
.da-c { display: flex; flex-wrap: wrap; gap: 3px; align-items: center; }
.da-c i { display: block; width: 11px; height: 11px; flex: none; }
.da-more { font: 600 10px 'JetBrains Mono', monospace; color: var(--ink-3); margin-left: 4px; }
.da-n { font: 600 11px 'JetBrains Mono', monospace; color: var(--ink);
        font-variant-numeric: tabular-nums; text-align: right; }

.ycols { display: flex; align-items: flex-end; gap: 12px; height: 150px; padding-top: 6px; }
.ycol { flex: 1; display: flex; flex-direction: column; align-items: center; height: 100%;
        opacity: 0; animation: barIn var(--t-base) var(--ease-out) forwards; }
.yc-bar { width: 100%; max-width: 46px; background: var(--k8); border-radius: 0;
          display: flex; align-items: flex-end; margin-top: auto;
          transform-origin: bottom center; animation: colGrow var(--t-reveal) var(--ease-out) both;
          animation-delay: inherit; }
.yc-dead { width: 100%; background: var(--bad); }
.yc-lb { font-size: 10.5px; color: var(--ink-2); margin-top: 6px; }
.yc-n { font: 500 9.5px 'JetBrains Mono', monospace; color: var(--ink-3); font-variant-numeric: tabular-nums; }

@keyframes barIn { to { opacity: 1; } }
@keyframes barGrow { from { transform: scaleX(0); } to { transform: none; } }
@keyframes colGrow { from { transform: scaleY(0); } to { transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .db-r, .ycol { animation: none; opacity: 1; }
  .yc-bar { animation: none; transform: none; }
}

@media (max-width: 760px) {
  .db-r, .da-r { grid-template-columns: 104px 1fr 72px; }
  .db-ax { margin-left: 116px; margin-right: 84px; }
  .db-ax em { display: none; }
  .da-r { grid-template-columns: 104px 1fr 30px; }
}

/* A focused row must be as obvious as a hovered one — the keyboard path
   through the tables is the same path the mouse takes. Outline sits inside
   the row because a table row clips an outward offset in some engines. */
tr.hit:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  background: var(--surface-2);
}
tr.hit:focus { outline: none; }

/* ── view and theme transitions (H7) ──────────────────────────────────────
   Both are feature-detected in app.js and both are skipped entirely under
   reduced motion, so this block only ever runs for a browser that asked for
   it. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vt-out var(--t-base) var(--ease-out) both;
  }
  ::view-transition-new(root) {
    animation: vt-in var(--t-base) var(--ease-out) both;
  }
  @keyframes vt-out { to { opacity: .4; transform: translateY(-6px); } }
  @keyframes vt-in { from { opacity: 0; transform: translateY(6px); } }

  /* The theme wipe replaces the cross-fade: the incoming theme is revealed by
     a circle growing from the toggle, and the outgoing one simply waits
     underneath rather than fading, or the two would show through each other. */
  .wiping::view-transition-old(root) { animation: none; }
  .wiping::view-transition-new(root) {
    animation: theme-wipe 400ms var(--ease-out) both;
    transform: none;
  }
  @keyframes theme-wipe {
    from { clip-path: circle(0 at var(--wipe-x) var(--wipe-y)); }
    to { clip-path: circle(var(--wipe-r) at var(--wipe-x) var(--wipe-y)); }
  }
}

/* ── Draft, two columns (H1) ───────────────────────────────────────────────
   The officer's own words on the left, the answer on the right. Sticky only
   where there is room to be sticky: on a narrow screen a stuck column eats
   the viewport, so below 1200px this is one stack with the query first. */
.split { display: grid; gap: 14px; }
/* A grid item's default min-width is auto, which means min-content, which means
   one non-wrapping child sets the floor for the whole column. On a phone the
   trace rail and a nowrap card hint pushed both columns to 611px inside a 375px
   sheet, and because the sheet clips rather than scrolls, the right-hand third
   of every answer was simply unreachable — the page reported no horizontal
   overflow. The rail already wraps; it simply never got the chance. */
.split > * { min-width: 0; }
/* A container query, not a viewport one. The left rail takes 216px at desktop
   width, so a viewport breakpoint measured the wrong thing: at 1440px the
   content column is about 1184px and the two-column layout silently stopped
   applying on exactly the screens it was built for. This asks the column it
   actually lives in. */
@container sheet (min-width: 940px) {
  .split { grid-template-columns: minmax(340px, 34%) 1fr; align-items: start; }
  .split-q { position: sticky; top: 14px; }
  /* A sticky column must never be taller than the viewport or its bottom
     becomes unreachable — the presets and the run button live down there. */
  .split-q { max-height: calc(100vh - 28px); overflow-y: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .split-q { scroll-behavior: auto; }
}

/* ── Run demo, as a film (H9) ──────────────────────────────────────────────
   The step counter said "3 / 7", which is a fact about a list. The dots say
   the same thing as a shape you can read without counting, and the clock says
   the one thing a presenter with a four-minute slot actually needs to know. */
.demobar .dots { display: flex; gap: 5px; flex: none; align-items: center; }
.demobar .dots i {
  width: 6px; height: 6px; border-radius: 50%; display: block;
  background: rgba(255,255,255,.26); transition: background .2s, transform .2s;
}
[data-theme="dark"] .demobar .dots i { background: var(--line-hard); }
.demobar .dots i.done { background: rgba(255,255,255,.5); }
.demobar .dots i.now { background: var(--accent); transform: scale(1.5); }
.demobar .clock {
  flex: none; font: 500 11px/1 'JetBrains Mono', monospace;
  opacity: .62; font-variant-numeric: tabular-nums;
}
/* The caret only exists while the caption is still being typed. */
.demobar .txt .p.typing::after {
  content: ''; display: inline-block; width: 6px; height: 1em;
  margin-left: 1px; vertical-align: -2px; background: var(--accent);
  animation: caret 1s steps(2) infinite;
}
@keyframes caret { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .demobar .txt .p.typing::after { display: none; }
}

/* How far a dead citation reaches beyond the document in front of you. */
.edit .blast { margin-top: 4px; color: var(--ink-2); line-height: 1.5; }
.edit .blast:empty { display: none; }
.edit .blast b { color: var(--bad); }

/* The Draft answer column before there is an answer. Deliberately not a
   skeleton: a skeleton promises a shape that is about to arrive, and this is
   the resting state of a screen waiting for input, which is a different thing. */
.card.resting { border-style: dashed; box-shadow: none; }
.resting-list { margin: 0; padding-left: 20px; color: var(--ink-2); font-size: 12.5px; line-height: 1.6; }
.resting-list li { margin-bottom: 8px; }
.resting-list li b { color: var(--ink); font-weight: 600; }
.resting-list li::marker { color: var(--accent); font-family: 'JetBrains Mono', monospace; font-size: 11px; }

/* ── Keyboard shortcuts ────────────────────────────────────────────────────
   Opened with "?", closed with Escape or the button. A list, not a grid of
   cards: it is read once and dismissed. */
/* The hidden attribute has to win. `.keys-scrim { display: grid }` outranks the
   user-agent rule for [hidden], so this overlay was visible from page load —
   empty, covering the page, and un-closable, because the close button sets
   `hidden` and `hidden` was doing nothing. Declared globally rather than only
   here: any element this page hides with the attribute has the same problem the
   moment it is given a display of its own. */
[hidden] { display: none !important; }

.keys-scrim {
  position: fixed; inset: 0; z-index: 95; display: grid; place-items: center;
  background: color-mix(in srgb, var(--pet-900) 46%, transparent);
  padding: 20px;
}
.keys-card {
  width: min(560px, 100%); max-height: 82vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line-hard);
  border-radius: var(--r-3); box-shadow: var(--sh-3);
}
.keys-card .hd { display: flex; align-items: center; padding: 13px 16px 0; }
.keys-card .hd .eyebrow { flex: 1; }
.keys-card .in { padding: 10px 16px 16px; }
.keys-group { margin-top: 12px; }
.keys-group:first-child { margin-top: 2px; }
.keys-group h4 {
  font: 700 8.5px/1 'JetBrains Mono', monospace; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 6px;
}
.keys-row {
  display: flex; align-items: baseline; gap: 12px; padding: 5px 0;
  border-bottom: 1px solid var(--line); font-size: 12.5px; color: var(--ink-2);
}
.keys-row:last-child { border-bottom: none; }
.keys-row kbd {
  flex: none; min-width: 58px; text-align: center;
  font: 600 11px/1.7 'JetBrains Mono', monospace;
  background: var(--surface-3); border: 1px solid var(--line-hard);
  border-bottom-width: 2px; border-radius: var(--r-1); padding: 1px 7px;
  color: var(--ink);
}

/* Co-citation suggestions, grouped by the citation that pulled them in. */
.addgroup { margin-bottom: 14px; }
.addgroup:last-child { margin-bottom: 0; }
.addgroup-lb {
  font-size: 11.5px; color: var(--ink-3); margin-bottom: 6px;
  padding-bottom: 5px; border-bottom: 1px solid var(--line);
}
.addgroup-lb .mono { color: var(--ink); font-size: 12px; }

/* ── Brutalist treatment ───────────────────────────────────────────────────
   Bigger, heavier, squarer. A procurement console is an administrative
   instrument and the closer it reads to a government form the more legible its
   authority is — so: one grotesque at heavy weights, structure drawn in 2px
   rules rather than implied by shadow, no rounded corners anywhere, and a type
   scale large enough to read across a room during a demo.

   The palette does not change. Petrol carries structure and amber still means
   "needs a human"; what changes is how hard the edges are.

   This block sits last so it wins on cascade order without needing !important
   or raised specificity — the rules above stay readable as the base design. */

body { font-size: 16px; line-height: 1.6; }

h1, h2, h3, h4 {
  font-family: 'Public Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  font-weight: 800; letter-spacing: -.02em;
}
h1 { font-size: 30px; line-height: 1.15; }
h2 { font-size: 22px; }
h3 { font-size: 16.5px; letter-spacing: .01em; }

/* Section labels are structure, so they are set like structure: uppercase,
   tracked out, and in the mono face that carries every other machine-read
   value on the page. */
.eyebrow, .navgroup-lb, .keys-group h4, .bars .bl, .lb {
  font-family: 'JetBrains Mono', monospace; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
}
.eyebrow { font-size: 9.5px; }

.vh h1 { font-size: 34px; }
.vh .meta { font-size: 14px; }

/* Structure, drawn. */
.card, .tbl, .drawer, .pal, .keys-card, .pins-pop, .demobar {
  border-width: var(--bw); border-style: solid; border-color: var(--ink);
}
[data-theme="dark"] .card, [data-theme="dark"] .tbl, [data-theme="dark"] .drawer,
[data-theme="dark"] .pal, [data-theme="dark"] .keys-card,
[data-theme="dark"] .pins-pop, [data-theme="dark"] .demobar {
  border-color: var(--line-hard);
}
.card .hd, .tbl .toolbar {
  border-bottom: var(--bw) solid var(--ink);
  background: var(--surface-3);
}
[data-theme="dark"] .card .hd, [data-theme="dark"] .tbl .toolbar { border-bottom-color: var(--line-hard); }

/* Controls read as pressable slabs rather than soft chips. */
.btn, .navsearch, .role-btn, .demo-btn, input[type=text], input[type=search],
input[type=number], textarea, select {
  border-width: var(--bw); border-radius: 0; font-weight: 600;
}
.btn { font-size: 14px; padding: 0 15px; height: 38px; }
.btn.acc, .btn.pri { box-shadow: var(--sh-1); }
.btn.acc:active, .btn.pri:active { box-shadow: none; transform: translate(2px, 2px); }
.btn.wide { height: 40px; font-size: 14px; }

/* Tables: heavier header rule, bigger figures, squarer cells. */
table th {
  font-family: 'JetBrains Mono', monospace; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; font-size: 10px;
  border-bottom: var(--bw) solid var(--ink);
}
[data-theme="dark"] table th { border-bottom-color: var(--line-hard); }
table td { font-size: 14.5px; }

/* Status pills become tags: square, bordered, uppercase. */
.pill {
  border-radius: 0; border: 1.5px solid currentColor; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em; font-size: 10px;
}

/* The numbers are the point of this product, so they are set like it. */
.kpi .v, .hero-fig .n, .gstat .vl { font-weight: 900; letter-spacing: -.03em; }
.mono { font-weight: 500; }

/* The nav is a masthead. */
/* The nav is a masthead: an amber rule under the whole bar, and a heavier one
   under the section you are in. */
.topnav { border-bottom: 3px solid var(--accent); }
.tab { font-weight: 600; font-size: 13px; padding-left: 5px; padding-right: 5px; }
.tab.on { border-bottom-width: 3px; }
/* Heavier type costs width, and ten labels plus a brand and six controls have
   to fit one bar. Measured after the type change: 803px wanted against 792
   available at 1440, so the space comes back out of padding rather than out of
   the type — the point of the change was the type. */
/* Ten section labels at a readable size will not share a row with a brand and
   six controls — the fit was 792px of 792 before the type grew, which is not a
   fit, it is a coincidence. So the sections get their own full-width band under
   the masthead, which is how a government portal is laid out anyway: identity
   and tools on top, navigation beneath it, both spanning the page.

   The bar is two rows now, so the sticky offset below it is computed rather
   than typed: --bar-h drives both. */
/* The masthead is a grid, not a wrapping row. Identity sits top-left, the
   sections run along the bottom, and the controls occupy a block on the right
   that spans both rows — so the tools stay in one place the eye can return to
   instead of being strung along the top edge. The block wraps onto a second
   line of its own when it needs to, which is what buys the sections their
   width back. */
.topnav {
  display: grid; height: auto; padding: 0 16px; row-gap: 0;
  grid-template-columns: auto auto 1fr auto;
  grid-template-rows: auto auto;
  align-items: center;
}
.brand { grid-column: 1; grid-row: 1; min-height: 52px; }
.brand-sep { grid-column: 2; grid-row: 1; }
/* The controls take two lines of their own on the right of the identity row,
   rather than spanning both rows of the masthead. Spanning looked right and
   measured wrong: the block is 320px, and taking that out of the sections row
   left 912px for labels that need 987, so Evidence, Coverage and Benchmark
   fell off a 1280px screen. On its own row the block costs height, which the
   masthead has, instead of width, which the sections do not. */
/* The two control rows belong to different rows of the masthead: the actions
   sit beside the identity, the settings sit beside the sections. `display:
   contents` dissolves their wrapper so each becomes a grid item of the bar
   itself and can be placed on its own row — otherwise both are trapped in
   whichever cell the wrapper occupies. */
.nav-right { display: contents; }
.nav-row { display: flex; align-items: center; gap: 6px; justify-self: end; }
.nav-row:first-child { grid-column: 4; grid-row: 1; padding-left: 16px; }
.nav-row:last-child {
  grid-column: 4; grid-row: 2; padding-left: 16px;
  border-top: 1px solid var(--nav-line); align-self: stretch;
}
.tabwrap {
  grid-column: 1 / 4; grid-row: 2;
  border-top: 1px solid var(--nav-line);
}

/* Settings beside the sections costs the sections about 215px, which they can
   afford at 1280 and cannot below it: at 1000 they came up 169px short and
   Coverage and Benchmark fell off the end. So under 1200 the settings move up
   beside the actions — both right-aligned on the identity row — and the
   sections take the whole width back. Labels people click beat a tidier
   arrangement of controls. */
@media (max-width: 1199.98px) {
  .nav-row:last-child {
    grid-column: 3; grid-row: 1;
    border-top: none; align-self: center; padding-left: 0;
  }
  .tabwrap { grid-column: 1 / 5; }
}

/* On a phone the four columns cannot hold a brand and two control groups on one
   line — placing them there pushed the bar past the viewport and every view
   scrolled sideways. Below this the masthead stops being a grid and simply
   wraps: identity, controls, then the sections on their own full-width line. */
@media (max-width: 780px) {
  .topnav { display: flex; flex-wrap: wrap; align-items: center; column-gap: 8px; }
  .brand { flex: 1 1 auto; min-width: 0; }
  .brand-sep { display: none; }
  .nav-row { flex: 0 0 auto; border-top: none; padding-left: 0; }
  .tabwrap { flex-basis: 100%; }
}
.tabs { height: 46px; }
.tab { height: 46px; padding: 0 12px 10px; font-size: 14.5px; }
.navgroup { padding-left: 16px; }
.navgroup-lb { top: 5px; left: 16px; font-size: 8.5px; }
.navgroup + .navgroup { margin-left: 6px; }
.navgroup + .navgroup::before { top: 12px; bottom: 12px; }
.tab .ct { font-size: 11px; }

.note { border-left-width: 5px; border-radius: 0; }

/* ── The finding, and the statement it answers ─────────────────────────────
   The hero headline is now a number with a denominator rather than a count of
   what we hold, so it is set at display scale and the figure is the loudest
   thing on the page. */
.hero-h .big {
  font-size: clamp(56px, 7vw, 92px); line-height: .92; display: inline-block;
  letter-spacing: -.035em; color: var(--accent);
}
.hero-h .of {
  font-family: 'JetBrains Mono', monospace; font-weight: 500;
  font-size: clamp(15px, 1.5vw, 20px); letter-spacing: 0; opacity: .72;
  margin-left: 8px;
}
.hero-h em { font-style: normal; color: var(--accent); }

/* The six expected features. A numbered list because the statement is a list
   and the order is its order — the one structural device here that carries
   information rather than decoration. */
.asks { margin-top: 18px; }
.asks-hd { margin-bottom: 12px; }
.asks-hd h2 {
  font-family: 'Public Sans', sans-serif; font-weight: 800;
  font-size: clamp(20px, 2.2vw, 28px); letter-spacing: -.02em; margin-top: 3px;
}
.asks-grid { display: grid; gap: 0; border-top: var(--bw) solid var(--ink); }
.ask {
  display: grid; grid-template-columns: 44px 1fr auto; gap: 14px;
  align-items: start; text-align: left; width: 100%;
  padding: 14px 10px; background: none; border: 0;
  border-bottom: 1px solid var(--line); cursor: pointer; color: inherit;
  font: inherit; transition: background var(--t-fast);
}
.ask:hover { background: var(--surface-2); }
.ask-n {
  font: 800 15px/1.2 'JetBrains Mono', monospace; color: var(--ink-4);
  font-variant-numeric: tabular-nums; padding-top: 1px;
}
.ask-b { display: block; min-width: 0; }
.ask-t { display: block; font-weight: 700; font-size: 14.5px; line-height: 1.35; }
.ask-h {
  display: block; margin-top: 4px; font-size: 12.5px; line-height: 1.5;
  color: var(--ink-2); max-width: 82ch;
}
.ask-s {
  font: 700 9.5px/1 'JetBrains Mono', monospace; letter-spacing: .1em;
  text-transform: uppercase; padding: 5px 8px; white-space: nowrap;
  border: 1px solid transparent;
}
.ask-s.met { color: var(--ok); border-color: var(--ok); }
/* "Partly" is a claim about us, so it is marked as plainly as the others. */
.ask-s.partial { color: var(--accent); border-color: var(--accent); }

@media (max-width: 720px) {
  .ask { grid-template-columns: 30px 1fr; }
  .ask-s { grid-column: 2; justify-self: start; margin-top: 8px; }
}

/* ── Folds: the overview as four sections, not fourteen cards ───────────────
   Fourteen cards of equal weight is a dashboard, and a dashboard makes the
   reader work out what matters. These are named, numbered and ordered by how
   much they are worth reading; the two that are supporting evidence start
   closed, and every section remembers its own state.
   ────────────────────────────────────────────────────────────────────────── */

.fold { border: var(--bw) solid var(--ink); background: var(--surface); margin-bottom: 14px; box-shadow: var(--sh-2); }
.fold > summary {
  display: flex; align-items: center; gap: 14px; padding: 15px 17px;
  cursor: pointer; list-style: none; user-select: none; background: var(--surface-2);
}
.fold > summary::-webkit-details-marker { display: none; }
.fold[open] > summary { border-bottom: var(--bw) solid var(--ink); }
.fold > summary:hover { background: var(--surface-3); }
.fold > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }
.fold-n {
  font: 800 14px/1 'JetBrains Mono', monospace; color: var(--surface);
  background: var(--brand); padding: 7px 8px; flex: none; font-variant-numeric: tabular-nums;
}
.fold-b { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.fold-t { font: 800 19px/1.2 'Public Sans', sans-serif; letter-spacing: -.012em; color: var(--ink); text-wrap: balance; }
.fold-h { font-size: 12.5px; line-height: 1.4; color: var(--ink-3); }
.fold-c {
  width: 22px; height: 22px; flex: none; fill: none; stroke: var(--ink-2);
  stroke-width: 2.4; stroke-linecap: square; transition: transform .22s ease;
}
.fold[open] > summary .fold-c { transform: rotate(180deg); }
.fold-in { padding: 15px 16px 1px; }
.fold-in > .in.nopad { padding: 0 0 14px; }
@media (prefers-reduced-motion: reduce) { .fold-c { transition: none; } }
@media (max-width: 640px) {
  .fold-t { font-size: 16px; }
  .fold-h { display: none; }
  .fold > summary { padding: 12px 13px; gap: 10px; }
  .fold-in { padding: 12px 12px 1px; }
}

/* ── Gauge: one ratio ──────────────────────────────────────────────────────
   A half-dial rather than a ring, so it cannot be read as a second copy of the
   register-status donut sitting beside it.
   ────────────────────────────────────────────────────────────────────────── */

/* A fold inside a fold: the working behind a finding. Quieter than a section
   fold, so the hierarchy reads at a glance. */
.fold.sub { margin-top: 14px; border: 1px solid var(--line); background: var(--surface-2); }
.fold.sub > summary { padding: 11px 14px; }
.fold.sub .fold-t { font-size: 14px; }
.fold.sub .fold-in { padding: 0 14px 14px; }

/* Graph arrangement switch. */
.gseg { display: flex; border: 1px solid var(--line-hard); overflow: hidden; }
.gseg button { flex: 1; border: 0; background: var(--surface); color: var(--ink-2); cursor: pointer;
  padding: 6px 8px; font: 600 12px/1 'Public Sans', sans-serif; letter-spacing: .03em; }
.gseg button + button { border-left: 1px solid var(--line-hard); }
.gseg button.on { background: var(--brand); color: #fff; }

/* Coverage lens: true-scale rail, funnel, magnified panel. */
.lens { --fan: 46px; }
.lens-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 7px; }
.lens-t { font: 700 13px/1 'Public Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; color: var(--ok); }
.lens-t.bad { color: var(--bad); }
.lens-rail { display: flex; height: 18px; background: var(--surface-3); overflow: hidden; }
.lr-ok { background: var(--ok); }
.lr-gap { background: var(--bad); min-width: 3px; }
.lens-sub { font-size: 12px; color: var(--ink-3); margin-top: 6px; }
.lens-fan { display: block; width: 100%; height: var(--fan); margin-top: 8px; }
.lens-fan polygon { fill: var(--bad); fill-opacity: .09; stroke: var(--bad); stroke-opacity: .32; stroke-width: 1; vector-effect: non-scaling-stroke; }
.lens-panel { border: 1px solid var(--line); border-top: 2px solid var(--bad); background: var(--surface-2); padding: 14px 16px 16px; }
.lens-panel-h { font: 700 11px/1 'Public Sans', sans-serif; letter-spacing: .12em; text-transform: uppercase; color: var(--bad); margin-bottom: 12px; }
.lens-dots { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-height: 44px; }
.lens-dot { border: 0; padding: 0; border-radius: 50%; background: var(--bad); opacity: .82; cursor: pointer; flex: none; transition: transform .12s ease, opacity .12s ease; }
.lens-dot:hover, .lens-dot:focus-visible { opacity: 1; transform: scale(1.14); outline: none; box-shadow: 0 0 0 3px var(--bad-bg), 0 0 0 4px var(--bad); }
.lens-foot { font-size: 12px; color: var(--ink-3); margin-top: 12px; }
@media (prefers-reduced-motion: reduce) { .lens-dot { transition: none; } }

.cov { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.cov-r { flex: 1; min-width: 172px; display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.cov-f .eyebrow { display: flex; align-items: center; gap: 6px; }
.cov-sw { width: 9px; height: 9px; flex: none; }
.cov-n { font-size: 20px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; }
.gg { flex: none; max-width: 100%; height: auto; }
.gg-t line { stroke: var(--line-hard); stroke-width: 1.5; }
.gg-v { font: 900 34px/1 'Merriweather', serif; fill: var(--ink); font-variant-numeric: tabular-nums; }
.gg-u { font-size: 17px; fill: var(--ink-3); }
.gg-l { font: 700 9px/1 'Public Sans', sans-serif; fill: var(--ink-3); letter-spacing: .1em; text-transform: uppercase; }

/* ── Stacked strip: one composition on one track ───────────────────────────*/

.sbar { display: flex; height: 30px; border: 1px solid var(--ink); overflow: hidden; background: var(--surface-3); }
.sseg { display: block; width: 0; height: 100%; transition: width .7s cubic-bezier(.2,.8,.3,1); }
.sseg + .sseg { border-left: 1px solid var(--surface); }
.skey { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 11px; font-size: 12px; color: var(--ink-2); }
.skr { display: inline-flex; align-items: center; gap: 7px; }
.skr i { width: 10px; height: 10px; flex: none; }
.skr b { font: 600 12px/1 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; color: var(--ink); }

/* ── Area: a quantity across an ordered axis ───────────────────────────────*/

.areawrap { --a-t: 12px; --a-h: 150px; position: relative; padding: var(--a-t) 6px 0 38px; }
.areabox { position: relative; height: var(--a-h); }
.area { display: block; width: 100%; height: 100%; overflow: visible; }
.area-s { stroke-width: 2.2; stroke-linejoin: round; }
.ax-g { stroke: var(--line-soft); }
.area-p {
  position: absolute; width: 9px; height: 9px; border-radius: 50%;
  transform: translate(-50%, -50%); box-shadow: 0 0 0 2px var(--surface);
}
.area-p:hover { outline: 2px solid var(--accent); outline-offset: 2px; }
.ay {
  position: absolute; left: 0; transform: translateY(-50%);
  font: 500 10px/1 'JetBrains Mono', monospace; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.ax {
  display: flex; margin: 8px 0 0; padding-left: 0;
  font: 500 10px/1 'JetBrains Mono', monospace; color: var(--ink-3);
}
.ax span { flex: 1; text-align: center; min-width: 0; }
.ax span:first-child { text-align: left; }
.ax span:last-child { text-align: right; }
@media (max-width: 520px) { .ax span:nth-child(even) { visibility: hidden; } }

/* ── Treemap: parts of a whole, drawn at their real share ──────────────────*/

.tmap { position: relative; width: 100%; height: clamp(230px, 30vw, 330px); }
.tm {
  position: absolute; overflow: hidden; border: 2px solid var(--surface);
  transition: opacity .15s; color: #fff;
}
.tmap:hover .tm { opacity: .5; }
.tmap .tm:hover { opacity: 1; }
.tm-in { display: block; padding: 7px 9px; }
.tm-t {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font: 700 12.5px/1.25 'Public Sans', sans-serif; letter-spacing: -.005em;
}
.tm-n { display: block; margin-top: 3px; font: 600 11px/1 'JetBrains Mono', monospace; opacity: .84; font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .tm { transition: none; } }

/* ── Dot plot: a ranking on a shared axis ──────────────────────────────────
   Length still carries the value, but the weight sits at the end of it, so ten
   near-equal values stay ten distinguishable marks instead of one grey block.
   ────────────────────────────────────────────────────────────────────────── */

.lol { display: flex; flex-direction: column; gap: 9px; }
.lrow { display: grid; grid-template-columns: minmax(74px, 30%) 1fr auto; gap: 11px; align-items: center; font-size: 12px; }
.lrow .ll { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; }
.ltrack { position: relative; height: 12px; border-bottom: 1px dotted var(--line-hard); }
.lstem { position: absolute; left: 0; top: 5px; height: 2px; opacity: .45; }
.ldot { position: absolute; top: 1px; width: 11px; height: 11px; border-radius: 50%; transform: translateX(-50%); }
.lrow:hover .ldot { outline: 2px solid var(--accent); outline-offset: 1px; }
.lrow .lv { font: 600 12px/1 'JetBrains Mono', monospace; color: var(--ink); min-width: 28px; text-align: right; font-variant-numeric: tabular-nums; }

/* ── Ranked list: a shortlist where the order is the finding ───────────────*/

.rank { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.rank li {
  display: grid; grid-template-columns: auto minmax(84px, auto) 1fr auto; gap: 11px;
  align-items: center; padding: 7px 0; border-bottom: 1px solid var(--line-soft);
}
.rank li:last-child { border-bottom: 0; }
.rk { font: 700 10px/1 'JetBrains Mono', monospace; color: var(--ink-4); font-variant-numeric: tabular-nums; }
.rn { font-size: 12.5px; }
.rbar { height: 7px; background: var(--surface-3); }
.rbar i { display: block; height: 100%; }
.rank .rv { font: 600 12px/1 'JetBrains Mono', monospace; color: var(--ink); min-width: 26px; text-align: right; font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
  .rank li { grid-template-columns: auto 1fr auto; }
  .rbar { display: none; }
}

/* Dark mode lightens the categorical ramp, so white label text on a treemap
   tile stops carrying. The tiles are light there; the labels go dark. */
[data-theme="dark"] .tm { color: #0B1A22; }
[data-theme="dark"] .fold-n { color: #0B1A22; background: var(--pet-400); }
[data-theme="dark"] .sseg + .sseg { border-left-color: var(--surface); }

/* ── Precedent ─────────────────────────────────────────────────────────────
   The documents the officer was about to copy from, with the bad ones marked.
   It carries a warning, so it is allowed the one accent rail on this screen.
   ────────────────────────────────────────────────────────────────────────── */

.prec.hot { border-color: var(--bad); box-shadow: 3px 3px 0 var(--bad); }
.prec.hot > .hd { background: var(--bad-bg); border-bottom-color: var(--bad); }
.prec-lede { font-size: 15.5px; line-height: 1.55; margin: 0 0 14px; }
.prec-lede em { font-style: normal; color: var(--ink-2); }
.prec-n { font: 800 26px/1 'Merriweather', serif; color: var(--bad); vertical-align: -2px; }

.prec-list { display: flex; flex-direction: column; gap: 9px; }
.prec-doc { border: 1px solid var(--line); border-left: 3px solid var(--bad); padding: 10px 12px; background: var(--surface-2); }
.prec-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.prec-id { font-size: 12px; font-weight: 600; }
.prec-buyer { font-size: 12px; color: var(--ink-2); }
.prec-src { font-size: 11.5px; margin-left: auto; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
.prec-cat { font-size: 12px; color: var(--ink-3); margin-top: 4px; line-height: 1.45; }
.prec-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.chip.prec-dead { border-color: var(--bad); color: var(--bad); background: var(--bad-bg); }
.prec-row-dead td:first-child { font-weight: 600; }
tr.prec-row-dead { background: var(--bad-bg); }
[data-theme="dark"] tr.prec-row-dead { background: rgba(163,35,28,.14); }
[data-theme="dark"] .prec-doc { background: var(--surface-3); }
@media (max-width: 560px) {
  .prec-src { margin-left: 0; }
  .prec-lede { font-size: 14.5px; }
}

/* ── Readable sizes ────────────────────────────────────────────────────────
   The body was raised to 16px when the brutalist pass went in, but the small
   end of the scale was not: captions at 11px, table cells at 12.5px, column
   heads at 10px, pills at 11px. Those are most of the page, so the page read
   small however large the headings were — and this is a government console
   read all day, often on a desk monitor at arm's length.

   Nothing here changes a layout: the sizes go up, the structures already wrap.
   This block sits last so it wins on cascade order without !important.
   ────────────────────────────────────────────────────────────────────────── */

body { font-size: 17px; line-height: 1.6; }
h1 { font-size: 32px; }
h2 { font-size: 23px; }
h3 { font-size: 18px; }
.vh h1 { font-size: 36px; }
.vh .meta { font-size: 15px; }

.sm { font-size: 14px; }
.xs { font-size: 13px; }
.eyebrow { font-size: 11px; letter-spacing: .1em; }

.card > .hd .hint { font-size: 13px; }
.card > .ft { font-size: 13.5px; padding: 11px 16px; }

table { font-size: 14.5px; }
thead th { font-size: 11.5px; padding: 11px 12px; }
tbody td { padding: 10px 12px; }
td.mono, th.mono { font-size: 13.5px; }
.tbl .status { font-size: 13px; }

.pill { font-size: 12.5px; height: 22px; }
.chip { font-size: 13px; }
.fchip { font-size: 12.5px; height: 24px; }

.btn { font-size: 14.5px; }
.btn.wide { height: 42px; font-size: 15.5px; }
.btn.tiny { height: 28px; padding: 0 10px; font-size: 12.5px; }
input[type=text], input[type=search], input[type=number], select { font-size: 15px; }
textarea { font-size: 14px; line-height: 1.6; }

.legend { font-size: 13.5px; }
.legend .vv { font-size: 12.5px; }
.brow, .lrow, .db-r, .da-r { font-size: 13.5px; }
.db-l, .da-l, .lrow .ll, .brow .bl { font-size: 13px; }
.db-n, .lrow .lv, .rank .rv, .da-n, .rn { font-size: 13px; }
.crumbs { font-size: 13.5px; }
.conn { font-size: 12.5px; }
.blank .t { font-size: 15px; }

@media (max-width: 640px) {
  body { font-size: 16px; }
  h1 { font-size: 26px; }
  .vh h1 { font-size: 28px; }
}

/* ── Officer view ──────────────────────────────────────────────────────────
   Bigger than the admin console and much quieter. One decision per block, the
   verdict before the evidence, and no element on the screen that describes how
   the answer was produced. The type runs large because this is read while
   drafting a document, not while auditing a pipeline.
   ────────────────────────────────────────────────────────────────────────── */

.vd {
  display: inline-flex; align-items: center; gap: 8px; padding: 7px 13px;
  border: 2px solid; font: 700 14px/1 'Public Sans', sans-serif;
  letter-spacing: .01em; white-space: nowrap;
}
.vd b { font: 800 18px/1 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; }
.vd-yes   { color: var(--ok);     border-color: var(--ok);     background: var(--ok-bg); }
.vd-maybe { color: var(--accent); border-color: var(--accent); background: var(--accent-bg); }
.vd-no    { color: var(--bad);    border-color: var(--bad);    background: var(--bad-bg); }

.ocard {
  border: var(--bw) solid var(--ink); background: var(--surface);
  box-shadow: var(--sh-2); padding: 22px 24px; margin-bottom: 16px;
}
.ocard-yes   { border-color: var(--ok);  box-shadow: 3px 3px 0 var(--ok); }
.ocard-maybe { border-color: var(--accent); box-shadow: 3px 3px 0 var(--accent); }
.ocard-no    { border-color: var(--bad); box-shadow: 3px 3px 0 var(--bad); }
.ocard-mark  { border-color: var(--accent); box-shadow: 3px 3px 0 var(--accent); background: var(--accent-bg); }
.ocard-plain { box-shadow: var(--sh-1); border-color: var(--line-hard); }

.overdict { margin-bottom: 15px; }
.oh { font-size: 34px; line-height: 1.15; font-weight: 800; letter-spacing: -.02em; margin: 0; text-wrap: balance; }
.oh .mono { font-size: 34px; font-weight: 700; }
.oh3 { font-size: 21px; line-height: 1.25; font-weight: 800; margin: 0; text-wrap: balance; }
.otitle { font-size: 18px; line-height: 1.5; color: var(--ink-2); margin: 11px 0 0; max-width: 62ch; }
.oact { font-size: 17px; line-height: 1.5; font-weight: 600; margin: 14px 0 0; }
.osub { font-size: 16px; line-height: 1.55; color: var(--ink-2); margin: 9px 0 0; max-width: 64ch; }

.ofacts { display: flex; flex-wrap: wrap; gap: 10px 18px; margin-top: 15px; align-items: center; }
.ofact { font-size: 14.5px; color: var(--ink-2); }
.ofact b { color: var(--ink); font-weight: 700; }

.osec { margin: 26px 0 16px; }
.osec > .oh3 + .osub { margin-bottom: 14px; }
.olist { display: flex; flex-direction: column; gap: 10px; margin-top: 13px; }

.orow { border: 1px solid var(--line-hard); border-left: 5px solid var(--ink-4); padding: 13px 16px; background: var(--surface); }
.orow-yes   { border-left-color: var(--ok); }
.orow-maybe { border-left-color: var(--accent); }
.orow-no    { border-left-color: var(--bad); background: var(--surface-2); }
.orow-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.orow-is { font-size: 19px; font-weight: 700; }
.orow-t { font-size: 15.5px; line-height: 1.45; color: var(--ink-2); margin-top: 8px; max-width: 66ch; }
.orow-a { font-size: 15px; font-weight: 600; margin-top: 8px; }
.orow-x { font-size: 13.5px; color: var(--ink-3); margin-top: 6px; }

.ogroup { margin-top: 18px; }
.ogroup-h {
  font: 700 12.5px/1.3 'JetBrains Mono', monospace; text-transform: uppercase;
  letter-spacing: .12em; color: var(--ink-2); padding-bottom: 9px;
  border-bottom: 2px solid var(--line-hard); display: flex; gap: 14px;
  align-items: baseline; justify-content: space-between; flex-wrap: wrap;
}
.ogroup-h .dimmer { letter-spacing: .06em; font-weight: 500; white-space: nowrap; }

.ocard-clause { background: var(--surface-2); }
.oclause-h { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.oclause-h .oh3 { flex: 1; min-width: 0; }
.oclause {
  font-size: 16.5px; line-height: 1.75; margin-top: 15px; padding: 16px 18px;
  background: var(--surface); border: 1px solid var(--line-hard); max-width: 74ch;
}

@media (max-width: 640px) {
  .ocard { padding: 17px 16px; }
  .oh, .oh .mono { font-size: 25px; }
  .oh3 { font-size: 18.5px; }
  .otitle { font-size: 16px; }
  .oact, .osub { font-size: 15px; }
  .orow-is { font-size: 17px; }
  .oclause { font-size: 15.5px; padding: 13px 14px; }
}

/* Three destinations, no filing system. The group labels above the nav are
   wayfinding for a ten-screen console; over "Find standards / Check a document
   / Look up a standard" they are decoration, and they push the labels down. */
body.officer .navgroup-lb { display: none; }
body.officer .navgroup { padding-top: 0; }
body.officer .tab { font-size: 16px; }

/* ── Document repair ───────────────────────────────────────────────────────
   Before and after, what changed and on whose authority, and the two files.
   The scoreboard is the only place on the officer's side that puts two big
   numbers side by side, because this is the one screen where the comparison
   is the finding.
   ────────────────────────────────────────────────────────────────────────── */

.fx-score {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 18px; align-items: center;
  border: var(--bw) solid var(--ink); background: var(--surface);
  box-shadow: var(--sh-2); padding: 20px 24px; margin-bottom: 16px;
}
.fx-col { min-width: 0; }
.fx-mid { font: 700 26px/1 'JetBrains Mono', monospace; color: var(--ink-4); }
.fx-n { font: 900 46px/1 'Merriweather', serif; margin-top: 9px; font-variant-numeric: tabular-nums; }
.fx-bad { color: var(--bad); }
.fx-warn { color: var(--accent); }
.fx-ok { color: var(--ok); }
.fx-l { font-size: 15px; font-weight: 600; margin-top: 5px; }
.fx-sm { font-size: 13.5px; color: var(--ink-3); margin-top: 3px; }

.fx-prov {
  font-size: 14.5px; line-height: 1.55; color: var(--ink-2);
  border-left: 3px solid var(--line-hard); padding: 2px 0 2px 13px; margin: 0 0 18px;
}

.fx-list { display: flex; flex-direction: column; gap: 9px; margin-top: 13px; }
.fx-row {
  display: grid; grid-template-columns: 116px minmax(0, 1fr) minmax(0, 250px);
  gap: 16px; align-items: start;
  border: 1px solid var(--line-hard); border-left: 5px solid var(--ink-4);
  padding: 13px 16px; background: var(--surface);
}
.fx-replace { border-left-color: var(--ok); }
.fx-add     { border-left-color: var(--info); }
.fx-flag    { border-left-color: var(--bad); background: var(--surface-2); }
.fx-clause  { border-left-color: var(--accent); }
.fx-act {
  font: 700 12px/1.3 'JetBrains Mono', monospace; text-transform: uppercase;
  letter-spacing: .1em; color: var(--ink-2); padding-top: 3px;
}
.fx-sub { font-size: 16px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 9px; }
.fx-old { text-decoration: line-through; color: var(--bad); font-weight: 600; }
.fx-new { color: var(--ok); font-weight: 700; }
.fx-arrow { color: var(--ink-4); }
.fx-title { flex-basis: 100%; font-size: 14px; color: var(--ink-3); line-height: 1.45; }
.fx-basis { font-size: 13px; }
.fx-check { color: var(--accent); font-weight: 600; margin-top: 6px; }

.fx-dl { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 13px; margin-top: 13px; }
.fx-file {
  display: flex; gap: 15px; align-items: center; padding: 17px 18px;
  border: var(--bw) solid var(--line-hard); background: var(--surface);
  color: inherit; text-decoration: none;
}
.fx-file:hover { background: var(--surface-2); text-decoration: none; }
.fx-file-main { border-color: var(--ok); box-shadow: 3px 3px 0 var(--ok); }
.fx-ext {
  font: 800 15px/1 'JetBrains Mono', monospace; color: var(--surface);
  background: var(--brand); padding: 11px 9px; flex: none;
}
.fx-file-main .fx-ext { background: var(--ok); }
.fx-file-b { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.fx-file-t { font-size: 16px; font-weight: 700; }
.fx-file-s { font-size: 13.5px; color: var(--ink-2); line-height: 1.45; }
.drop.over { border-color: var(--accent); background: var(--accent-bg); }

@media (max-width: 720px) {
  .fx-score { grid-template-columns: 1fr; gap: 10px; text-align: left; }
  .fx-mid { transform: rotate(90deg); width: 26px; }
  .fx-n { font-size: 38px; }
  .fx-row { grid-template-columns: 1fr; gap: 9px; }
  .fx-act { padding-top: 0; }
}

/* A basis is a sentence, not a tag: "The replacement says it supersedes this
   one" has to wrap inside its column rather than run off the row. */
.fx-basis .pill {
  white-space: normal; height: auto; line-height: 1.35; padding: 5px 9px;
  display: inline-block; text-align: left;
}

/* A standing caveat is not a finding. It folds, so the screen opens on the
   result and the reasoning stays one click away for whoever wants to argue. */
.bm-why { border: 1px solid var(--line-hard); background: var(--surface-2); margin: 14px 0; }
.bm-why > summary {
  cursor: pointer; padding: 12px 15px; font-weight: 600; font-size: 14.5px;
  list-style: none;
}
.bm-why > summary::-webkit-details-marker { display: none; }
.bm-why > summary::before { content: '\25B8 '; color: var(--ink-3); }
.bm-why[open] > summary::before { content: '\25BE '; }
.bm-why > summary:hover { background: var(--surface-3); }
.bm-why p { padding: 0 15px 13px; font-size: 14px; line-height: 1.55; color: var(--ink-2); max-width: 78ch; }

/* A card's hint is a caption, not a label: it may wrap. `white-space: nowrap`
   kept "standards cited by real tenders but not yet held · tick to claim" on
   one 387px line inside a 375px phone, pushing it off the screen. It stays on
   one line wherever there is room for one. */
@media (max-width: 720px) {
  .card > .hd { flex-wrap: wrap; }
  .card > .hd .hint { white-space: normal; }
  /* A pill is a badge and badges do not wrap — but "BIS Product Certification
     (ISI Mark, Scheme I)" is a scheme name, not a badge, and at 365px it ran
     past the edge of a 375px screen. Where there is no room for one line, it
     takes two rather than leaving the room. */
  .pill { white-space: normal; height: auto; min-height: 22px; line-height: 1.35; padding: 3px 9px; }
}

/* Technical term beside the officer's plain heading. */
.otech { font-weight: 400; font-size: .72em; color: var(--ink-3); white-space: nowrap; }
/* The governing-standard card, one size down so it no longer dominates the page. */
.ocard-gov { padding: 16px 20px; }
.ocard-gov .overdict { margin-bottom: 10px; }
.ocard-gov .oh, .ocard-gov .oh .mono { font-size: 26px; }
.ocard-gov .otitle { font-size: 16px; margin-top: 7px; }
.ocard-gov .oact { font-size: 15px; margin-top: 10px; }
.ocard-gov .ofacts { margin-top: 11px; }
@media (max-width: 700px) { .ocard-gov .oh, .ocard-gov .oh .mono { font-size: 21px; } }
