/* ============================================================================
   VALMO design system — 29-ux-design-spec.md
   ----------------------------------------------------------------------------
   The product is an instrument for deciding whether public money is well spent,
   used by engineers and quantity surveyors under a legal clock. It should read
   as precise and calm, with the figures doing the work: tabular numerals
   everywhere digits align, hairline rules instead of boxes-within-boxes, and
   one accent spent on the things that carry consequence.

   Typography is a system stack by necessity and by choice — the application
   ships no webfont, because it must work offline and under a strict CSP, and a
   font that fails to load silently is worse than one chosen deliberately. The
   serif carries documents and headings (a certificate should feel like one),
   the sans carries interface, the mono carries every figure and identifier.

   Semantic colour is defined separately from the accent and is always paired
   with a word or an icon, so an outcome survives colour blindness (NFR-152).
   ========================================================================= */

:root {
  /* ---- ground and ink --------------------------------------------------- */
  --paper: #f5f7f4;
  --paper-sunk: #ecefe9;
  --surface: #ffffff;
  --surface-2: #f2f5f1;
  --surface-3: #e7ebe5;
  --ink: #131a16;
  --ink-soft: #4a574f;
  --ink-faint: #75837a;
  --rule: #dce2da;
  --rule-firm: #c2cbc0;

  /* ---- accent: ledger green, spent sparingly ---------------------------- */
  --accent: #145c42;
  --accent-ink: #0d3c2b;
  --accent-soft: #e2eee8;
  --accent-line: #9ec7b4;

  /* ---- semantic, never the accent --------------------------------------- */
  --ok: #1d6b4c;
  --ok-soft: #e3efe8;
  --warn: #8a6212;
  --warn-soft: #f7efdc;
  --bad: #96322d;
  --bad-soft: #f8e7e5;
  --info: #2c5578;
  --info-soft: #e5edf4;
  --paused: #5b5566;
  --paused-soft: #eeebf1;

  /* ---- type ------------------------------------------------------------- */
  --f-display:
    ui-serif, 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, 'Times New Roman', serif;
  --f-ui: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --f-mono:
    ui-monospace, 'SF Mono', SFMono-Regular, 'JetBrains Mono', 'Cascadia Mono', Menlo, Consolas,
    monospace;

  --t-xs: 0.6875rem; /* 11px — eyebrows, meta */
  --t-sm: 0.8125rem; /* 13px — table body, captions */
  --t-base: 0.9375rem; /* 15px — interface default */
  --t-md: 1.0625rem; /* 17px — lede */
  --t-lg: 1.375rem;
  --t-xl: 1.875rem;
  --t-2xl: 2.5rem;

  /* ---- space and shape --------------------------------------------------- */
  /* The scale is deliberately generous. An interface this dense — tables,
     chips, figures — reads as clumped at tighter values, and the fix is space
     between groups rather than smaller type. */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 14px;
  --s-4: 20px;
  --s-5: 28px;
  --s-6: 40px;
  --s-7: 56px;
  --s-8: 80px;
  --r-sm: 3px;
  --r-md: 5px;
  --r-lg: 8px;

  --shadow-1: 0 1px 2px rgb(19 26 22 / 6%);
  --shadow-2: 0 1px 2px rgb(19 26 22 / 5%), 0 10px 28px -20px rgb(19 26 22 / 45%);
  --shadow-3: 0 2px 6px rgb(19 26 22 / 8%), 0 24px 48px -28px rgb(19 26 22 / 55%);

  --rail-w: 232px;
  --tap: 44px;

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --paper: #0d1210;
    --paper-sunk: #090d0b;
    --surface: #141b17;
    --surface-2: #1a231e;
    --surface-3: #223028;
    --ink: #e6ece7;
    --ink-soft: #a6b4ab;
    --ink-faint: #7a887f;
    --rule: #25312a;
    --rule-firm: #36473d;
    --accent: #5cb693;
    --accent-ink: #8fd4b6;
    --accent-soft: #14241d;
    --accent-line: #2f5c48;
    --ok: #5cb693;
    --ok-soft: #14241d;
    --warn: #cfa252;
    --warn-soft: #2a2211;
    --bad: #dd8079;
    --bad-soft: #2e1917;
    --info: #7fa9cf;
    --info-soft: #14202b;
    --paused: #a79dba;
    --paused-soft: #1e1a24;
    --shadow-1: 0 1px 2px rgb(0 0 0 / 40%);
    --shadow-2: 0 1px 2px rgb(0 0 0 / 45%), 0 10px 28px -20px rgb(0 0 0 / 90%);
    --shadow-3: 0 2px 6px rgb(0 0 0 / 50%), 0 24px 48px -28px rgb(0 0 0 / 95%);
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-ui);
  font-size: var(--t-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.012em;
  text-wrap: balance;
}
h1 {
  font-family: var(--f-display);
  font-size: var(--t-xl);
  line-height: 1.12;
}
h2 {
  font-family: var(--f-display);
  font-size: var(--t-lg);
  line-height: 1.2;
}
h3 {
  font-size: var(--t-base);
  font-weight: 700;
  letter-spacing: 0;
}
p {
  margin: 0 0 var(--s-3);
}
a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
a:hover {
  text-decoration-thickness: 2px;
}

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

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: var(--s-3);
  top: var(--s-3);
  z-index: 100;
  padding: var(--s-2) var(--s-4);
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- utility -------------------------------------------------------------- */
.mono {
  font-family: var(--f-mono);
  font-size: 0.92em;
  letter-spacing: -0.01em;
}
.num {
  font-variant-numeric: tabular-nums;
  font-family: var(--f-mono);
}
.eyebrow {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.muted {
  color: var(--ink-soft);
}
.faint {
  color: var(--ink-faint);
}
.lede {
  font-size: var(--t-md);
  color: var(--ink-soft);
  line-height: 1.5;
  max-width: 68ch;
}
.stack > * + * {
  margin-top: var(--s-5);
}
.row {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  flex-wrap: wrap;
}
.spread {
  display: flex;
  gap: var(--s-4);
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
}
/* Keeps page actions on the right even when the row wraps onto its own line —
   space-between alone drops them back to the left margin. */
.spread > *:last-child {
  margin-left: auto;
}
.icon {
  display: block;
  flex: none;
}

/* ============================ shell ====================================== */
.shell {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  min-height: 100vh;
}

.rail {
  background: var(--surface);
  border-right: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
.brand {
  padding: var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--rule);
  text-align: center;
}
.brand-link {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-1);
  text-decoration: none;
  color: inherit;
  border-radius: var(--r-sm);
  padding: var(--s-1);
}
.brand-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.brand-name {
  font-family: var(--f-display);
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.005em;
  margin-top: var(--s-2);
}
.brand-sub {
  font-size: var(--t-xs);
  color: var(--ink-faint);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* The artwork carries its own transparency, so it needs no plate behind it.
   Sized by the img's width/height attributes, which also reserve the space
   before the file arrives. */
.arms-img {
  display: block;
  height: auto;
  max-width: 100%;
}

.nav {
  padding: var(--s-4) var(--s-3);
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.nav-group {
  margin-top: var(--s-4);
}
.nav-group:first-child {
  margin-top: 0;
}
.nav-group > .eyebrow {
  padding: 0 var(--s-3) var(--s-2);
  display: block;
}
.nav a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
  min-height: 34px;
}
.nav a:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.nav a[aria-current='page'] {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--accent);
}
.nav .count {
  margin-left: auto;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  background: var(--surface-2);
  padding: 1px 6px;
  border-radius: 999px;
}
.nav a[aria-current='page'] .count {
  background: var(--surface);
  color: var(--accent-ink);
}

.rail-foot {
  margin-top: auto;
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: center;
}
.powered {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.powered-label {
  font-family: var(--f-mono);
  font-size: 9.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
/* The supplier mark is light ink drawn for a dark ground, so on a light surface
   it gets a dark plate instead of vanishing into the rail. */
.supplier-mark {
  display: block;
  height: auto;
  border-radius: 3px;
  background: #10231b;
  padding: 3px 5px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .supplier-mark {
    background: transparent;
    padding: 0;
  }
}

/* ============================ user menu ==================================
   Built on <details>/<summary>: it opens, closes and handles focus and the
   keyboard with no JavaScript. The script only adds Escape and click-outside,
   which are conveniences rather than the mechanism. */
.topbar-end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.user-menu {
  position: relative;
}
.user-menu > summary {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  cursor: pointer;
  padding: var(--s-1) var(--s-2) var(--s-1) var(--s-1);
  border-radius: 999px;
  border: 1px solid transparent;
  list-style: none;
  user-select: none;
}
.user-menu > summary::-webkit-details-marker {
  display: none;
}
.user-menu > summary::marker {
  content: '';
}
.user-menu > summary:hover {
  background: var(--surface-2);
  border-color: var(--rule);
}
.user-menu > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.user-menu[open] > summary {
  background: var(--surface-2);
  border-color: var(--rule-firm);
}
.user-menu .who {
  min-width: 0;
  line-height: 1.2;
}
.user-menu .name {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 18ch;
}
.user-menu .role {
  display: block;
  font-size: var(--t-xs);
  color: var(--ink-faint);
}
.user-menu .caret {
  color: var(--ink-faint);
  display: flex;
}
.user-menu[open] .caret {
  transform: rotate(180deg);
}
@media (max-width: 620px) {
  .user-menu .who {
    display: none;
  }
}
.user-menu .menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 60;
  min-width: 290px;
  max-width: min(340px, calc(100vw - 24px));
  background: var(--surface);
  border: 1px solid var(--rule-firm);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  max-height: min(72vh, 560px);
  overflow-y: auto;
}
.menu-head {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  padding: var(--s-4);
  border-bottom: 1px solid var(--rule);
  background: var(--surface-2);
}
.menu-head .name {
  font-size: var(--t-base);
  font-weight: 700;
  white-space: normal;
  max-width: none;
}
.menu-head .role {
  font-size: var(--t-xs);
  color: var(--ink-faint);
}
.avatar.lg {
  width: 40px;
  height: 40px;
  font-size: var(--t-sm);
}
.avatar.sm {
  width: 22px;
  height: 22px;
  font-size: 9px;
}
.menu-group {
  padding: var(--s-2) var(--s-1);
  border-bottom: 1px solid var(--rule);
}
.menu-group:last-child {
  border-bottom: 0;
}
.menu-label {
  display: block;
  padding: var(--s-2) var(--s-3) var(--s-1);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.menu a,
.menu-button {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  color: var(--ink);
  text-decoration: none;
  font: inherit;
  font-size: var(--t-sm);
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  min-height: 38px;
}
.menu a:hover,
.menu-button:hover {
  background: var(--surface-2);
}
.menu a:focus-visible,
.menu-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.menu .icon {
  color: var(--ink-faint);
  flex: none;
}
.mi-label {
  display: block;
  font-weight: 500;
}
.mi-detail {
  display: block;
  font-size: var(--t-xs);
  color: var(--ink-faint);
  line-height: 1.3;
}
.menu-form {
  margin: 0;
}

.main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.topbar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
  padding: var(--s-4) var(--s-6);
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  position: sticky;
  top: 0;
  z-index: 20;
}
.crumbs {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  font-size: var(--t-sm);
  color: var(--ink-faint);
}
.crumbs a {
  color: var(--ink-soft);
  text-decoration: none;
}
.crumbs a:hover {
  color: var(--accent);
  text-decoration: underline;
}
.content {
  padding: var(--s-6);
  max-width: 1320px;
  width: 100%;
}
.content.narrow {
  max-width: 860px;
}

@media (max-width: 900px) {
  .shell {
    grid-template-columns: 1fr;
  }
  .rail {
    position: static;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--rule);
  }
  .nav {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .nav-group {
    margin-top: 0;
  }
  .nav-group > .eyebrow {
    display: none;
  }
  .rail-foot {
    margin-top: 0;
  }
  .content {
    padding: var(--s-4);
  }
  .topbar {
    padding: var(--s-3) var(--s-4);
  }
}

/* ============================ surfaces =================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.card > header {
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.card > .body {
  padding: var(--s-5);
}
.card + .card {
  margin-top: var(--s-4);
}
.card > .body.flush {
  padding: 0;
}
.card > footer {
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--rule);
  background: var(--surface-2);
  font-size: var(--t-sm);
}

.grid {
  display: grid;
  gap: var(--s-5);
}
.grid.c2 {
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
/* A wide primary panel beside a narrower companion — a table that needs room
   next to a summary that does not. Collapses on narrow screens. */
.grid.split {
  grid-template-columns: minmax(0, 1.7fr) minmax(300px, 1fr);
}
@media (max-width: 1000px) {
  .grid.split {
    grid-template-columns: 1fr;
  }
}
.mt-5 {
  margin-top: var(--s-5);
}
.mt-4 {
  margin-top: var(--s-4);
}
.grid.c3 {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.grid.c4 {
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

/* ---- stat tiles: used only where the figure IS the point ----------------- */
/* Dividers are drawn per tile with overlapping borders rather than by showing a
   background through 1px gaps. The gap technique leaves the container colour
   exposed wherever the last row is short of a full set, which reads as a broken
   panel — and the number of tiles is not fixed. */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(154px, 1fr));
  background: var(--surface);
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--rule);
}
.tiles > .tile {
  border-left: 1px solid var(--rule);
  border-top: 1px solid var(--rule);
  margin: -1px 0 0 -1px;
}
.tile {
  background: var(--surface);
  padding: var(--s-5);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s-1);
}
.tile .label {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  min-height: 2.4em;
  line-height: 1.2;
}
.tile .value {
  font-family: var(--f-mono);
  font-size: 1.75rem;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.05;
  align-self: end;
}
.tile .value .unit {
  font-size: 0.9rem;
  color: var(--ink-faint);
  letter-spacing: 0;
  margin-left: 2px;
}
.tile .note {
  font-size: var(--t-xs);
  color: var(--ink-faint);
  line-height: 1.35;
}
.tile.alert .value {
  color: var(--bad);
}
.tile.watch .value {
  color: var(--warn);
}
.tile.good .value {
  color: var(--ok);
}

/* ============================ chips ====================================== */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.05em;
  padding: 2px 7px;
  border-radius: var(--r-sm);
  white-space: nowrap;
  background: var(--surface-2);
  color: var(--ink-soft);
  border: 1px solid transparent;
}
.chip.ok {
  background: var(--ok-soft);
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 22%, transparent);
}
.chip.warn {
  background: var(--warn-soft);
  color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 22%, transparent);
}
.chip.bad {
  background: var(--bad-soft);
  color: var(--bad);
  border-color: color-mix(in srgb, var(--bad) 22%, transparent);
}
.chip.info {
  background: var(--info-soft);
  color: var(--info);
  border-color: color-mix(in srgb, var(--info) 22%, transparent);
}
.chip.paused {
  background: var(--paused-soft);
  color: var(--paused);
  border-color: color-mix(in srgb, var(--paused) 22%, transparent);
}
.chip .icon {
  width: 1em;
  height: 1em;
}

/* ============================ tables ===================================== */
.table-wrap {
  overflow-x: auto;
}
/* Wide enough that columns stay legible, narrow enough that a table inside a
   half-width card does not scroll sideways for no reason. The queue tables sit
   in full-width cards, where this floor never binds. */
table.data {
  border-collapse: collapse;
  width: 100%;
  min-width: 520px;
  font-size: var(--t-sm);
}
/* For tables in a companion panel, where 520px would force a sideways scroll. */
table.data.compact {
  min-width: 0;
}
table.data.compact th,
table.data.compact td {
  padding: var(--s-3);
}
/* Identifiers and figures never wrap; a broken case number is unreadable. */
table.data .mono,
table.data .num {
  white-space: nowrap;
}
/* A long contract title gets two lines and then an ellipsis, so rows keep a
   predictable height and the eye can run down the column. */
a.row-link.clamp-2,
a.row-link.clamp-1 {
  display: -webkit-box;
}
/* Names wrap on word boundaries only. `anywhere` breaks mid-word and turns a
   narrow column into vertical letter soup. */
table.data a.row-link {
  overflow-wrap: break-word;
}
.clamp-1 {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.35;
}
.clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.35;
}
table.data tbody td {
  padding: var(--s-4) var(--s-4);
}
table.data thead th {
  text-align: left;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: var(--s-3) var(--s-4);
  background: var(--surface-2);
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: 0;
  z-index: 1;
}
table.data tbody td {
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
table.data tbody tr:last-child td {
  border-bottom: 0;
}
table.data tbody tr {
  transition: background 120ms ease;
}
table.data tbody tr:hover {
  background: var(--surface-2);
}
table.data td.right,
table.data th.right {
  text-align: right;
}
table.data td.num {
  font-family: var(--f-mono);
  white-space: nowrap;
}
table.data a.row-link {
  color: inherit;
  text-decoration: none;
  font-weight: 600;
}
table.data a.row-link:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* Severity is carried by a stripe AND a word, never colour alone. */
tr.sev-breached td:first-child {
  box-shadow: inset 3px 0 0 var(--bad);
}
tr.sev-at_risk td:first-child {
  box-shadow: inset 3px 0 0 var(--warn);
}
tr.sev-paused td:first-child {
  box-shadow: inset 3px 0 0 var(--paused);
}
tr.sev-comfortable td:first-child {
  box-shadow: inset 3px 0 0 var(--rule-firm);
}
tr.sev-not_started td:first-child {
  box-shadow: inset 3px 0 0 transparent;
}

/* ============================ the clock ================================== */
/* The Office's credibility is its turnaround, so the clock is the one element
   that gets real visual weight — and it shows paused time honestly rather than
   quietly excluding it. */
.clock {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-width: 220px;
}
.clock-head {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
}
.clock-figure {
  font-family: var(--f-mono);
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
}
.clock-figure.breached {
  color: var(--bad);
}
.clock-figure.at_risk {
  color: var(--warn);
}
.clock-figure.paused {
  color: var(--paused);
}
.clock-unit {
  font-size: var(--t-xs);
  color: var(--ink-faint);
  font-family: var(--f-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.clock-track {
  height: 8px;
  border-radius: 999px;
  background: var(--surface-3);
  display: flex;
  overflow: hidden;
  border: 1px solid var(--rule);
}
.clock-seg {
  height: 100%;
  transition: width 320ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.clock-seg.elapsed {
  background: var(--accent);
}
.clock-seg.paused {
  background: repeating-linear-gradient(135deg, var(--paused) 0 3px, transparent 3px 6px);
  background-color: var(--paused-soft);
}
.clock-seg.breach {
  background: var(--bad);
}
.clock-legend {
  display: flex;
  gap: var(--s-4);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  flex-wrap: wrap;
}
.clock-legend span {
  display: flex;
  align-items: center;
  gap: 5px;
}
.clock-legend i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: block;
}

/* ============================ case header ================================ */
.case-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s-5);
  align-items: start;
}
.case-head .title {
  font-family: var(--f-display);
  font-size: var(--t-xl);
  line-height: 1.14;
  margin-bottom: var(--s-2);
}
.case-head .facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  font-size: var(--t-sm);
  color: var(--ink-soft);
}
.case-head .facts b {
  font-weight: 600;
  color: var(--ink);
}
@media (max-width: 760px) {
  .case-head {
    grid-template-columns: 1fr;
  }
}

.case-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  gap: var(--s-5);
  align-items: start;
}
@media (max-width: 1100px) {
  .case-layout {
    grid-template-columns: 1fr;
  }
}

/* ---- evidence rail ------------------------------------------------------- */
.evidence {
  list-style: none;
  margin: 0;
  padding: 0;
}
.evidence li {
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--rule);
  display: flex;
  gap: var(--s-3);
}
.evidence li:last-child {
  border-bottom: 0;
}
.evidence .kind {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  background: var(--surface-2);
  color: var(--ink-faint);
}
.evidence .label {
  font-size: var(--t-sm);
  font-weight: 500;
  line-height: 1.35;
}
.evidence .meta {
  font-size: var(--t-xs);
  color: var(--ink-faint);
  margin-top: 2px;
}

/* ============================ comparison ================================= */
/* The variance chart and the provenance sit on one screen: a reference price
   without its specification, date and tax treatment is not evidence (FR-206). */
.compare {
  display: grid;
  gap: var(--s-5);
}
.cmp-scale {
  position: relative;
  padding: var(--s-6) 0 var(--s-5);
}
.cmp-axis {
  position: absolute;
  inset: auto 0 var(--s-4) 0;
  height: 1px;
  background: var(--rule-firm);
}
.cmp-bar {
  position: relative;
  height: 34px;
  margin-bottom: var(--s-2);
}
.cmp-bar .fill {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  display: flex;
  align-items: center;
  padding-left: var(--s-3);
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  color: #fff;
  white-space: nowrap;
  transition: width 420ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.cmp-bar.submitted .fill {
  background: var(--info);
}
.cmp-bar.benchmark .fill {
  background: var(--accent);
}
.cmp-bar.adjusted .fill {
  background: var(--accent);
  opacity: 0.62;
}
.cmp-bar .caption {
  position: absolute;
  left: 0;
  top: -18px;
  font-size: var(--t-xs);
  color: var(--ink-faint);
  font-family: var(--f-mono);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.cmp-verdict {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-md);
  background: var(--surface-2);
  border-left: 3px solid var(--rule-firm);
}
.cmp-verdict.within {
  background: var(--ok-soft);
  border-left-color: var(--ok);
}
.cmp-verdict.outside {
  background: var(--warn-soft);
  border-left-color: var(--warn);
}
.cmp-verdict .figure {
  font-family: var(--f-mono);
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.02em;
}
.cmp-verdict.within .figure {
  color: var(--ok);
}
.cmp-verdict.outside .figure {
  color: var(--warn);
}

.provenance {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.provenance div {
  padding: var(--s-4);
  border-left: 1px solid var(--rule);
  border-top: 1px solid var(--rule);
  margin: -1px 0 0 -1px;
}
.provenance dt {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 3px;
}
.provenance dd {
  margin: 0;
  font-size: var(--t-sm);
  line-height: 1.4;
}

/* ============================ certificate ================================ */
/* A certificate should feel like a document, because that is what it is. */
.certificate {
  background: var(--surface);
  border: 1px solid var(--rule-firm);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-2);
  position: relative;
  overflow: hidden;
}
.certificate::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: linear-gradient(90deg, var(--accent) 0 42%, var(--warn) 42% 71%, var(--bad) 71% 100%);
}
/* The watermark sits behind the text and never intercepts a click or a caret. */
.cert-watermark {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  opacity: 0.045;
  z-index: 0;
}
.cert-watermark .arms {
  width: min(320px, 60%);
  height: auto;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .cert-watermark {
    opacity: 0.07;
  }
}

/* A diagonal stamp for anything that is not a live, valid certificate. */
.cert-stamp {
  position: absolute;
  top: 46%;
  left: 50%;
  z-index: 1;
  pointer-events: none;
  transform: translate(-50%, -50%) rotate(-19deg);
  font-family: var(--f-display);
  font-size: clamp(3rem, 12vw, 6rem);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bad);
  opacity: 0.12;
  border: 5px solid currentColor;
  border-radius: 10px;
  padding: 0.08em 0.3em;
  white-space: nowrap;
}
.certificate.is-refused::before {
  background: var(--bad);
}

.cert-body {
  padding: var(--s-7) var(--s-7) var(--s-6);
  position: relative;
  z-index: 2;
}
.cert-head {
  display: flex;
  gap: var(--s-4);
  align-items: center;
}
.cert-arms {
  font-family: var(--f-display);
  font-size: var(--t-sm);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  line-height: 1.7;
}
.cert-title {
  font-family: var(--f-display);
  font-size: var(--t-2xl);
  line-height: 1.05;
  margin: var(--s-3) 0 var(--s-2);
}
.cert-number {
  font-family: var(--f-mono);
  font-size: var(--t-md);
  letter-spacing: 0.04em;
  color: var(--accent-ink);
}
.cert-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-5);
  margin: var(--s-6) 0;
}
.cert-grid dt {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cert-grid dd {
  margin: var(--s-1) 0 0;
  font-size: var(--t-base);
}
.cert-ceiling {
  font-family: var(--f-mono);
  font-size: 1.6rem;
  letter-spacing: -0.02em;
}
.cert-sig {
  margin-top: var(--s-7);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  gap: var(--s-5);
  flex-wrap: wrap;
  align-items: flex-end;
}
.sig-block {
  max-width: 46ch;
}
.sig-mark {
  display: block;
  color: var(--ink);
  margin-bottom: -6px;
}
.signature {
  display: block;
  max-width: 100%;
  height: auto;
}
.cert-sig .name {
  font-family: var(--f-display);
  font-size: var(--t-md);
  display: block;
}
.sig-attest {
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  line-height: 1.45;
  max-width: 46ch;
}
.sig-status {
  text-align: right;
}
.cert-verify {
  background: var(--surface-2);
  border-top: 1px solid var(--rule);
  padding: var(--s-4) var(--s-7);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  display: flex;
  gap: var(--s-4);
  align-items: center;
  flex-wrap: wrap;
}
.cert-hash {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  word-break: break-all;
  color: var(--ink-faint);
}

/* ============================ forms ====================================== */
.field {
  margin-bottom: var(--s-5);
}
.field > label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
  margin-bottom: 3px;
}
.field .req {
  font-weight: 400;
  color: var(--ink-faint);
}
.field .hint {
  margin: 0 0 var(--s-2);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  line-height: 1.45;
}
.control {
  display: flex;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--rule-firm);
  border-radius: var(--r-sm);
  transition:
    border-color 120ms ease,
    box-shadow 120ms ease;
}
.control:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.control-icon {
  display: flex;
  align-items: center;
  padding: 0 var(--s-3);
  color: var(--ink-faint);
  border-right: 1px solid var(--rule);
}
.control input,
.control textarea,
.control select {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  padding: 9px var(--s-3);
  resize: vertical;
}
.control textarea {
  min-height: 130px;
  line-height: 1.5;
  font-size: var(--t-sm);
}
.control input:focus,
.control textarea:focus,
.control select:focus {
  outline: none;
}
.counter {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  margin-top: var(--s-1);
  display: block;
}
.counter.short {
  color: var(--warn);
}
.counter.met {
  color: var(--ok);
}

fieldset {
  border: 0;
  margin: 0 0 var(--s-4);
  padding: 0;
}
fieldset legend {
  font-size: var(--t-sm);
  font-weight: 600;
  margin-bottom: var(--s-2);
  padding: 0;
}
.choice {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  padding: var(--s-4);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--surface);
  cursor: pointer;
  margin-bottom: var(--s-2);
}
.choice:hover {
  border-color: var(--rule-firm);
  background: var(--surface-2);
}
.choice input {
  margin-top: 3px;
  accent-color: var(--accent);
}
.choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.choice:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.choice .t {
  display: block;
  font-weight: 600;
  font-size: var(--t-sm);
}
.choice .d {
  display: block;
  font-size: var(--t-xs);
  color: var(--ink-soft);
  margin-top: 2px;
  line-height: 1.45;
}

/* ---- buttons: the whole state machine lives in one component ------------- */
/* Actions sit to the right, where the eye lands after reading the form. */
.actions {
  display: flex;
  gap: var(--s-3);
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}
/* A row of page-level actions above the content needs no rule above it. */
.actions.bare {
  border-top: 0;
  padding-top: 0;
  margin-top: var(--s-4);
}
.actions.start {
  justify-content: flex-start;
}
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 38px;
  min-width: calc(var(--label-ch, 8ch) + 4rem);
  padding: 0 var(--s-4);
  border-radius: var(--r-sm);
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 600;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  transition:
    background 120ms ease,
    border-color 120ms ease,
    transform 80ms ease;
}
.btn:hover {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
}
.btn:active {
  transform: translateY(1px);
}
.btn.secondary {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--rule-firm);
}
.btn.secondary:hover {
  background: var(--surface-2);
  border-color: var(--ink-faint);
}
.btn.danger {
  background: var(--bad);
  border-color: var(--bad);
}
.btn.ghost {
  background: transparent;
  border-color: transparent;
  color: var(--ink-soft);
  min-width: 0;
}
.btn.ghost:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.btn[disabled],
.btn[aria-disabled='true'] {
  cursor: not-allowed;
  opacity: 0.55;
}
.btn[data-state='pending'] {
  cursor: progress;
}
.btn[data-state='done'] {
  background: var(--ok);
  border-color: var(--ok);
}
.btn[data-state='failed'] {
  background: var(--bad);
  border-color: var(--bad);
}
.btn.secondary[data-state='done'] {
  background: var(--ok-soft);
  color: var(--ok);
  border-color: var(--ok);
}
.btn.secondary[data-state='failed'] {
  background: var(--bad-soft);
  color: var(--bad);
  border-color: var(--bad);
}

/* ---- inline notices ------------------------------------------------------ */
.notice {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-md);
  border-left: 3px solid var(--rule-firm);
  background: var(--surface-2);
  font-size: var(--t-sm);
  line-height: 1.5;
}
.notice .icon {
  margin-top: 2px;
  color: var(--ink-faint);
}
.notice.warn {
  background: var(--warn-soft);
  border-left-color: var(--warn);
}
.notice.warn .icon {
  color: var(--warn);
}
.notice.bad {
  background: var(--bad-soft);
  border-left-color: var(--bad);
}
.notice.bad .icon {
  color: var(--bad);
}
.notice.ok {
  background: var(--ok-soft);
  border-left-color: var(--ok);
}
.notice.ok .icon {
  color: var(--ok);
}
.notice.info {
  background: var(--info-soft);
  border-left-color: var(--info);
}
.notice.info .icon {
  color: var(--info);
}
.notice strong {
  display: block;
  margin-bottom: 2px;
}

.empty {
  text-align: center;
  padding: var(--s-8) var(--s-5);
  color: var(--ink-faint);
}
.empty .icon {
  margin: 0 auto var(--s-3);
  width: 28px;
  height: 28px;
  color: var(--rule-firm);
}

/* ---- timeline ------------------------------------------------------------ */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 10px;
  bottom: 10px;
  width: 1px;
  background: var(--rule);
}
.timeline li {
  position: relative;
  padding: 0 0 var(--s-4) var(--s-6);
}
.timeline li:last-child {
  padding-bottom: 0;
}
.timeline .dot {
  position: absolute;
  left: 0;
  top: 5px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--rule-firm);
}
.timeline li.is-accent .dot {
  border-color: var(--accent);
  background: var(--accent);
}
.timeline li.is-warn .dot {
  border-color: var(--warn);
  background: var(--warn);
}
.timeline li.is-bad .dot {
  border-color: var(--bad);
  background: var(--bad);
}
.timeline .when {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--ink-faint);
}
.timeline .what {
  font-size: var(--t-sm);
  font-weight: 600;
  margin-top: 1px;
}
.timeline .detail {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  margin-top: 3px;
  line-height: 1.5;
}

/* ---- sparkline / bars ---------------------------------------------------- */
.spark {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 34px;
}
.spark i {
  flex: 1;
  background: var(--accent-line);
  border-radius: 1px 1px 0 0;
  min-height: 2px;
  display: block;
}
.spark i.peak {
  background: var(--accent);
}

.meter {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
}
.meter > span {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}
.meter.physical > span {
  background: var(--info);
}
.meter.financial > span {
  background: var(--warn);
}

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

@media print {
  .rail,
  .topbar,
  .actions,
  .skip {
    display: none !important;
  }
  .shell {
    display: block;
  }
  .certificate {
    box-shadow: none;
    border-color: #999;
  }
  body {
    background: #fff;
  }
}

/* ============================ toolbar: filter + search ==================== */
.toolbar {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--rule);
  background: var(--surface-2);
}
.toolbar .grow {
  flex: 1;
  min-width: 220px;
}
.toolbar .control {
  background: var(--surface);
}
.toolbar .control input {
  padding: 7px var(--s-3);
  font-size: var(--t-sm);
}

/* Facets read as one object: same height, same baseline, same inner padding. */
.facets {
  display: flex;
  gap: var(--s-1);
  flex-wrap: wrap;
}
.facet {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 var(--s-3);
  border-radius: 999px;
  border: 1px solid var(--rule-firm);
  background: var(--surface);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: var(--t-xs);
  font-weight: 600;
  white-space: nowrap;
  transition:
    background 120ms ease,
    border-color 120ms ease,
    color 120ms ease;
}
.facet:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}
.facet[aria-pressed='true'] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.facet .n {
  font-family: var(--f-mono);
  font-size: 10px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-faint);
}
.facet[aria-pressed='true'] .n {
  background: rgb(255 255 255 / 22%);
  color: #fff;
}
.facet .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: block;
}
.facet .dot.bad {
  background: var(--bad);
}
.facet .dot.warn {
  background: var(--warn);
}
.facet .dot.paused {
  background: var(--paused);
}
.facet .dot.ok {
  background: var(--ok);
}

.filter-summary {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-2) var(--s-5);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
}
.filter-summary .clear {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
  font-size: var(--t-xs);
}
.filter-summary .clear:hover {
  text-decoration: underline;
}

/* ============================ sortable headers =========================== */
table.data thead th.sortable {
  padding: 0;
}
table.data thead th.sortable a {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  padding: var(--s-3) var(--s-4);
  color: inherit;
  text-decoration: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
}
table.data thead th.sortable a:hover {
  color: var(--ink);
  background: var(--surface-3);
}
table.data thead th.sortable.right a {
  justify-content: flex-end;
}
.sort-caret {
  width: 9px;
  height: 9px;
  opacity: 0.35;
  flex: none;
}
th[aria-sort] .sort-caret {
  opacity: 1;
  color: var(--accent);
}
th[aria-sort] a {
  color: var(--ink);
}

/* ============================ pagination ================================= */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--rule);
  flex-wrap: wrap;
  font-size: var(--t-sm);
  color: var(--ink-soft);
}
.pagination .pages {
  display: flex;
  gap: var(--s-1);
  align-items: center;
}
.pagination .page {
  display: inline-grid;
  place-items: center;
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  color: var(--ink-soft);
  text-decoration: none;
  font-family: var(--f-mono);
  font-size: var(--t-sm);
}
.pagination .page:hover {
  background: var(--surface-2);
  color: var(--ink);
  border-color: var(--rule);
}
.pagination .page[aria-current='page'] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 600;
}
.pagination .page[aria-disabled='true'] {
  opacity: 0.35;
  pointer-events: none;
}
.pagination .gap {
  color: var(--ink-faint);
  padding: 0 2px;
}
.pagination .size {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.pagination select {
  font: inherit;
  font-size: var(--t-sm);
  padding: 4px 6px;
  border-radius: var(--r-sm);
  border: 1px solid var(--rule-firm);
  background: var(--surface);
  color: inherit;
}

/* ============================ infographics =============================== */
/* Charts are inline SVG drawn to one scale, with every label naming a value the
   chart reaches, and text coloured from the theme tokens so it reads in both. */
/* The viewBox is close to the width these render at, and the width is capped,
   so label type stays in a legible band instead of being scaled to nothing in a
   narrow card or blown up in a wide one. */
.chart {
  display: block;
  width: 100%;
  max-width: 640px;
  height: auto;
  overflow: visible;
  margin-inline: auto;
}
.chart text {
  font-family: var(--f-mono);
  font-size: 13px;
  fill: var(--ink-faint);
  letter-spacing: 0.02em;
}
.chart-caption {
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  line-height: 1.45;
  max-width: 60ch;
}
.chart .axis-line {
  stroke: var(--rule);
  stroke-width: 1;
}
.chart .grid-line {
  stroke: var(--rule);
  stroke-width: 1;
  stroke-dasharray: 2 3;
  opacity: 0.7;
}
.chart .bar {
  fill: var(--accent);
  transition: fill 120ms ease;
}
.chart .bar.alt {
  fill: var(--accent-line);
}
.chart .bar.bad {
  fill: var(--bad);
}
.chart .bar.warn {
  fill: var(--warn);
}
.chart .bar.info {
  fill: var(--info);
}
.chart .bar-label {
  fill: var(--ink);
  font-size: 13px;
  font-weight: 500;
}
.chart .series-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.chart .series-area {
  fill: var(--accent);
  opacity: 0.1;
}
.chart .endpoint {
  fill: var(--accent);
  stroke: var(--surface);
  stroke-width: 2;
}
.chart .target-line {
  stroke: var(--bad);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
}
.chart .target-label {
  fill: var(--bad);
}

.donut-wrap {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  flex-wrap: wrap;
}
.donut {
  flex: none;
}
.donut circle {
  fill: none;
  stroke-width: 14;
}
.donut .track {
  stroke: var(--surface-3);
}
.donut-centre {
  font-family: var(--f-mono);
  text-anchor: middle;
}
.donut-centre .big {
  font-size: 20px;
  fill: var(--ink);
}
.donut-centre .small {
  font-size: 9px;
  fill: var(--ink-faint);
  letter-spacing: 0.08em;
}
.legend {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  font-size: var(--t-sm);
  min-width: 160px;
}
.legend .item {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.legend .swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex: none;
}
.legend .n {
  margin-left: auto;
  font-family: var(--f-mono);
  color: var(--ink-soft);
}

/* Horizontal breakdown bar — one object, parts in fixed order. */
.stackbar {
  display: flex;
  height: 10px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface-3);
}
.stackbar > span {
  display: block;
  height: 100%;
}
.stackbar-key {
  display: flex;
  gap: var(--s-4);
  flex-wrap: wrap;
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--ink-soft);
}
.stackbar-key span {
  display: flex;
  align-items: center;
  gap: 6px;
}
.stackbar-key i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: block;
}

/* ============================ authentication ============================= */
/* The sign-in page is the first thing anyone sees, a minister included, so it
   carries the emblem and the same care as the rest of the product. */
/* The shell owns the viewport height so the proof-of-concept strip can sit
   above the card at full width instead of becoming a centred grid item. */
.auth-shell {
  background: var(--paper-sunk);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.auth-body {
  flex: 1 0 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  padding: var(--s-5) var(--s-4);
}
.auth-card {
  width: 100%;
  max-width: 470px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  padding: var(--s-6);
}
.auth-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s-5);
}
.auth-office {
  display: block;
  font-family: var(--f-display);
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.2;
}
.auth-country {
  display: block;
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.auth-title {
  font-family: var(--f-display);
  font-size: 1.6rem;
  margin-bottom: var(--s-2);
}
.auth-lede {
  color: var(--ink-soft);
  font-size: var(--t-sm);
  line-height: 1.5;
  margin-bottom: var(--s-5);
}
.auth-form .actions {
  justify-content: flex-end;
}
/* The reset link is a way out of the form, not a second action competing with
   the button, so it sits below rather than beside it. */
.auth-alt {
  margin-top: var(--s-4);
  text-align: right;
  font-size: var(--t-sm);
}
.auth-alt a {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}
.auth-alt a:hover {
  text-decoration: underline;
}
.auth-card .notice {
  margin-bottom: var(--s-4);
}
.auth-card .notice:last-of-type {
  margin-top: var(--s-5);
  margin-bottom: 0;
}
.auth-foot {
  margin-top: var(--s-6);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  justify-content: center;
}
/* A six-digit code is read back in pairs; space it and make it big. */
#f-code {
  font-family: var(--f-mono);
  font-size: 1.4rem;
  letter-spacing: 0.4em;
}

/* ============================ row action menus =========================== */
/* A floating panel cannot escape a scroll container, so tables carrying row
   menus drop the horizontal scroll and hide their lower-priority columns on
   narrow screens instead. Scrolling a table sideways to reach an actions column
   was never good on a phone anyway. */
.table-wrap.has-menus {
  overflow: visible;
}
table.data.responsive {
  min-width: 0;
  table-layout: fixed;
}
/* Dates and figures are short and must never wrap; wrapping them steals width
   from the column that actually needs it. */
table.data.responsive td.num,
table.data.responsive .chip,
table.data.responsive .faint {
  white-space: nowrap;
}
table.data.responsive td .clamp-1,
table.data.responsive td .clamp-2,
table.data.responsive td a.row-link {
  white-space: normal;
}
/* An identifier is one token. Wrapping "VFM/2026/000315" across two lines makes
   it unreadable and unsearchable by eye. Specificity has to beat the rule above
   that lets row links wrap. */
table.data.responsive td a.row-link.mono,
table.data.responsive td .mono,
table.data .mono {
  white-space: nowrap;
}
/* Fixed layout does not grow a cell to fit, so anything too long would print
   over its neighbour. Clip it instead. */
/* Clip rather than ellipsise: a cell holding a chip would otherwise show a
   stray "…" for the whitespace after it. */
table.data.responsive td,
table.data.responsive th {
  overflow: hidden;
}
table.data.responsive td.col-actions {
  overflow: visible;
}
/* Keyed off the table's own width, not the viewport's.
   A media query measures the window, but the table only ever gets the window
   minus the rail and the page padding — so a viewport breakpoint fires several
   hundred pixels too late and the columns are already clipped by the time it
   does. */
.table-wrap {
  container-type: inline-size;
}
@container (max-width: 860px) {
  table.data.responsive .col-1 {
    display: none;
  }
}
@container (max-width: 720px) {
  table.data.responsive .col-2 {
    display: none;
  }
}
@container (max-width: 600px) {
  table.data.responsive .col-3 {
    display: none;
  }
}

th.col-actions,
td.col-actions {
  width: 44px;
  padding-left: 0;
  padding-right: var(--s-3);
  text-align: right;
}

.row-menu {
  position: relative;
  display: inline-block;
}
.row-menu > summary {
  list-style: none;
  cursor: pointer;
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  color: var(--ink-faint);
  border: 1px solid transparent;
}
.row-menu > summary::-webkit-details-marker {
  display: none;
}
.row-menu > summary::marker {
  content: '';
}
.row-menu > summary:hover {
  background: var(--surface-3);
  color: var(--ink);
}
.row-menu > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.row-menu[open] > summary {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: var(--accent-line);
}
.row-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 50;
  min-width: 236px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule-firm);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  padding: var(--s-2) var(--s-1);
}
/* Near the bottom of a long table the panel would fall off the page. */
tbody tr:nth-last-child(-n + 2) .row-menu-panel {
  top: auto;
  bottom: calc(100% + 6px);
}
.menu-rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: var(--s-2) var(--s-2);
}
.row-menu-panel .menu-label {
  padding-top: var(--s-1);
}
/* Actions that cannot work without scripting are not offered without it. */
.needs-script {
  display: none;
}
.js .needs-script {
  display: flex;
}

/* ---- searchable filter --------------------------------------------------- */
.filter-search {
  display: flex;
  gap: var(--s-2);
  align-items: stretch;
  flex: 1;
  min-width: 260px;
}
.filter-search .control {
  flex: 1;
  background: var(--surface);
}
.filter-search .control input {
  padding: 7px var(--s-3);
  font-size: var(--t-sm);
}
.filter-search .btn {
  min-width: 0;
  min-height: 0;
  white-space: nowrap;
}
.control-clear {
  display: flex;
  align-items: center;
  padding: 0 var(--s-3);
  color: var(--ink-faint);
  border-left: 1px solid var(--rule);
  text-decoration: none;
}
.control-clear:hover {
  color: var(--bad);
  background: var(--bad-soft);
}

/* ---- column widths ------------------------------------------------------
   As classes rather than style attributes: a width that rides on an inline
   style is at the mercy of anything that sanitises markup, and a fixed-layout
   table whose widths are dropped distributes every column equally — which is
   how an identifier column ends up too narrow for the identifier. */
table.data th.w-10 {
  width: 10%;
}
table.data th.w-11 {
  width: 11%;
}
table.data th.w-12 {
  width: 12%;
}
table.data th.w-13 {
  width: 13%;
}
table.data th.w-14 {
  width: 14%;
}
table.data th.w-16 {
  width: 16%;
}
table.data th.w-20 {
  width: 20%;
}
table.data th.w-25 {
  width: 25%;
}
table.data th.w-26 {
  width: 26%;
}
table.data th.w-30 {
  width: 30%;
}
table.data th.w-34 {
  width: 34%;
}
table.data th.w-42 {
  width: 42%;
}

/* ---- filter bar ---------------------------------------------------------- */
.filters {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  flex-wrap: wrap;
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  background: var(--surface-2);
}
.filter-field {
  min-width: 150px;
}
.filter-field.grow {
  flex: 1;
  min-width: 230px;
}
.filters .control {
  background: var(--surface);
}
.filters .control input,
.filters .control select {
  padding: 8px var(--s-3);
  font-size: var(--t-sm);
}
.filters .control select {
  appearance: none;
  cursor: pointer;
  /* Room for the chevron drawn on the wrapper. */
  padding-right: var(--s-6);
}
.filters .filter-field:has(select) .control {
  position: relative;
}
.filters .filter-field:has(select) .control::after {
  content: '';
  position: absolute;
  right: 12px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -5px;
  border-right: 1.5px solid var(--ink-faint);
  border-bottom: 1.5px solid var(--ink-faint);
  transform: rotate(45deg);
  pointer-events: none;
}
.filters .btn {
  min-width: 0;
  min-height: 0;
  white-space: nowrap;
}

/* ------------------------------------------------------------------ *
 * Searchable dropdowns
 *
 * A datalist-backed input. It has to read as a dropdown — otherwise the
 * suggestions look like an accident — while still inviting typing, which is
 * the whole point once the list behind it runs to hundreds of entries.
 * ------------------------------------------------------------------ */
.control.searchable {
  position: relative;
}
.control.searchable input {
  padding-right: var(--s-6);
}
.control.searchable::after {
  content: '';
  position: absolute;
  right: 12px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -5px;
  border-right: 1.5px solid var(--ink-faint);
  border-bottom: 1.5px solid var(--ink-faint);
  transform: rotate(45deg);
  pointer-events: none;
}
/* Chrome hides its own picker button; ours is the only affordance shown. */
.control.searchable input::-webkit-calendar-picker-indicator {
  opacity: 0;
}

/* ------------------------------------------------------------------ *
 * Proof-of-concept markings
 *
 * Rendered only while the build serves invented data. The strip sits above
 * everything and stays in the flow rather than floating, so it cannot cover
 * content and cannot be scrolled away from — a marking that leaves the screen
 * is one a screenshot can be taken without.
 * ------------------------------------------------------------------ */
.poc-strip {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-2) var(--s-5);
  background: var(--warn-soft);
  color: var(--warn);
  border-bottom: 1px solid color-mix(in srgb, var(--warn) 30%, transparent);
  font-size: var(--t-xs);
  line-height: 1.45;
}
.poc-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  flex: none;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.poc-tag .icon {
  width: 0.95em;
  height: 0.95em;
}
.poc-text {
  color: color-mix(in srgb, var(--warn) 82%, var(--ink));
}

.poc-chip {
  display: inline-block;
  margin-top: var(--s-2);
  padding: 2px 7px;
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius: var(--r-1);
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 0.62rem;
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.auth-head .poc-chip {
  margin-top: var(--s-1);
}

/* The strip is the one piece of chrome that must survive printing: a printed
   page leaves the application behind, and the Specimen stamp alone does not
   cover the screens that are not certificates. */
@media print {
  .poc-strip {
    display: flex !important;
    background: transparent;
    border-bottom: 1px solid #999;
    color: #000;
  }
  .poc-text {
    color: #000;
  }
}

/* A shell that sizes itself to the viewport has to make room for the strip
   above it, or the page gains a scrollbar the height of the strip. */
body:has(> .poc-strip) > .shell {
  min-height: calc(100vh - 2.4rem);
}

/* ------------------------------------------------------------------ *
 * Demonstration account roster
 *
 * Sits beside the sign-in card rather than inside it: nine people do not fit
 * a 470px column without turning the form into a scroll. On a narrow screen
 * the two stack, form first, because someone who already knows an address
 * should not have to scroll past the list to reach the fields.
 * ------------------------------------------------------------------ */
.auth-body:has(.roster-panel) {
  grid-template-columns: minmax(0, 470px) minmax(0, 420px);
  gap: var(--s-5);
  align-items: start;
  justify-content: center;
  padding-block: var(--s-6);
}
.roster-panel {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  padding: var(--s-5);
  width: 100%;
}
.roster-head h2 {
  font-family: var(--f-display);
  font-size: 1.05rem;
  margin: 0;
}
.roster-head p {
  margin: var(--s-2) 0 var(--s-4);
  font-size: var(--t-xs);
  color: var(--ink-soft);
  line-height: 1.55;
}
.roster-head .mono {
  padding: 1px 5px;
  border-radius: var(--r-1);
  background: var(--surface-2);
  color: var(--ink);
}
.roster-group + .roster-group {
  margin-top: var(--s-4);
}
.roster {
  list-style: none;
  margin: var(--s-2) 0 0;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.roster-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
}
.roster-row + .roster-row {
  border-top: 1px solid var(--rule);
}
.roster-row:hover {
  background: var(--surface-2);
}
.roster-who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.roster-name {
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.3;
}
.roster-role {
  font-size: var(--t-xs);
  color: var(--ink-faint);
}
.roster-email {
  font-size: 0.68rem;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.roster-row .btn {
  flex: none;
  padding: 4px 10px;
  font-size: var(--t-xs);
}

@media (max-width: 960px) {
  .auth-body:has(.roster-panel) {
    grid-template-columns: minmax(0, 470px);
  }
}
