/* ----------------------------------------------------------------- palette
   Two palettes, written out once each as --l-* and --d-*, and four short blocks
   that assign one of them to the names the rest of the file uses. Nothing below
   this section names a literal colour, which is the only reason a theme switch
   is a stylesheet change rather than a second stylesheet to keep in step.

   The fourth assignment block is @media print, at the bottom of the file: a
   register printed from the dark theme would otherwise come out as light text
   on paper the printer renders white. */
:root {
  /* Light. Warm rather than white — a register is read for an hour at a time,
     and paper-coloured is easier to sit in front of than lit-panel white. */
  --l-bg: #f4efe4;
  --l-surface: #fcfaf5;
  --l-field: #fffdf8;
  --l-fg: #21201a;
  --l-muted: #6a6558;
  --l-line: #ded6c6;
  --l-line-strong: #c5bba6;
  --l-accent: #1e5138;
  --l-accent-bg: #1e5138;
  --l-accent-wash: #eaf1eb;
  --l-on-accent: #fcfaf5;
  --l-error: #9a2f24;
  --l-error-bg: #9a2f24;
  --l-on-error: #fdf3f1;
  --l-shadow: rgba(60, 50, 30, 0.07);

  /* The header is its own surface, darker than the page rather than lighter.
     A masthead the same colour as the panels below it reads as one more panel. */
  --l-header: #e3dac5;
  --l-header-fg: #21201a;
  --l-header-line: #cec2a6;
  --l-header-muted: #5f5a4c;

  /* Panels are held by a shadow now, not a border, so the border that remains is
     only there to keep the edge from dissolving on a light background. */
  --l-panel-line: #e8e0ce;
  --l-row-hover: #ece5d6;
  --l-elev-1: 0 1px 1px rgba(74, 62, 38, 0.04), 0 2px 6px rgba(74, 62, 38, 0.05);
  --l-elev-2: 0 1px 2px rgba(74, 62, 38, 0.06), 0 6px 16px rgba(74, 62, 38, 0.08);

  /* Band colours. Deliberately desaturated: a register that looks like a traffic
     light stops being read. Colour is never the only signal — every band is
     printed as a number and a name alongside its swatch, which is also what keeps
     the grid usable for a colour-blind reader. */
  --l-band-very-low: #dceadb;
  --l-band-low: #e6edd2;
  --l-band-medium: #f7e9c2;
  --l-band-high: #f5dabd;
  --l-band-critical: #f1cec8;
  --l-band-none: #e9e4d6;
  --l-band-ink: #2f2e28;

  /* Effectiveness levels are a maturity ladder, not a severity scale, so they get
     their own ramp — reusing the band colours would imply a "critical" control. */
  --l-level-1: #eae5d9;
  --l-level-2: #e2e7dc;
  --l-level-3: #d8e5d8;
  --l-level-4: #cbe1d4;
  --l-level-5: #bfddcf;

  /* Dark. Not neutral grey: the same forest hue pulled through the darks, so the
     two themes read as one product rather than one product and its negative. */
  --d-bg: #151815;
  --d-surface: #1d211d;
  --d-field: #212520;
  --d-fg: #e9e5da;
  --d-muted: #9c9689;
  --d-line: #333a33;
  --d-line-strong: #4a534a;
  /* Brighter and more saturated than the light theme's forest, with dark text on
     the button. A mid-green button on a dark page separates from it by about
     3:1, which is why the old one looked recessed — this one clears 4.5:1 and
     reads as the primary action it is. */
  --d-accent: #4fd191;
  --d-accent-bg: #2b9160;
  --d-accent-wash: #17281f;
  --d-on-accent: #08160e;
  --d-error: #ef9086;
  --d-error-bg: #8c3a30;
  --d-on-error: #fdf1ef;
  --d-shadow: rgba(0, 0, 0, 0.4);

  --d-header: #232823;
  --d-header-fg: #e9e5da;
  --d-header-line: #333a33;
  --d-header-muted: #9c9689;

  /* Shadows do almost nothing on a dark page, so depth there is carried by the
     surface stepping up from the background and by a border that stays visible. */
  --d-panel-line: #2c322c;
  --d-row-hover: #232723;
  --d-elev-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --d-elev-2: 0 2px 4px rgba(0, 0, 0, 0.45), 0 8px 20px rgba(0, 0, 0, 0.35);

  /* Inverted the same way: dark fills, light ink. Kept as desaturated as the
     light set, and still never the only signal. */
  --d-band-very-low: #24382b;
  --d-band-low: #313c26;
  --d-band-medium: #453a22;
  --d-band-high: #4d3422;
  --d-band-critical: #4d2b27;
  --d-band-none: #2b2e2a;
  --d-band-ink: #e9e5da;

  --d-level-1: #2c2c29;
  --d-level-2: #29332b;
  --d-level-3: #26392e;
  --d-level-4: #234232;
  --d-level-5: #1f4b37;

  /* The band fills sit behind a line chart, where a flat wash reads better than a
     solid block. Dark fills are already quiet, so they need less help. */
  --l-chart-band-opacity: 0.55;
  --d-chart-band-opacity: 0.85;
}

/* Light is the default: assigned unconditionally so that every name below has a
   value even when neither the media query nor the attribute matches. */
:root {
  color-scheme: light;
  --bg: var(--l-bg); --surface: var(--l-surface); --field: var(--l-field);
  --fg: var(--l-fg); --muted: var(--l-muted);
  --line: var(--l-line); --line-strong: var(--l-line-strong);
  --accent: var(--l-accent); --accent-bg: var(--l-accent-bg);
  --accent-wash: var(--l-accent-wash); --on-accent: var(--l-on-accent);
  --error: var(--l-error); --error-bg: var(--l-error-bg); --on-error: var(--l-on-error);
  --shadow: var(--l-shadow);
  --band-very-low: var(--l-band-very-low); --band-low: var(--l-band-low);
  --band-medium: var(--l-band-medium); --band-high: var(--l-band-high);
  --band-critical: var(--l-band-critical); --band-none: var(--l-band-none);
  --band-ink: var(--l-band-ink);
  --level-1: var(--l-level-1); --level-2: var(--l-level-2); --level-3: var(--l-level-3);
  --level-4: var(--l-level-4); --level-5: var(--l-level-5);
  --header: var(--l-header); --header-fg: var(--l-header-fg);
  --header-line: var(--l-header-line); --header-muted: var(--l-header-muted);
  --panel-line: var(--l-panel-line); --row-hover: var(--l-row-hover);
  --elev-1: var(--l-elev-1); --elev-2: var(--l-elev-2);
  --chart-band-opacity: var(--l-chart-band-opacity);
}

/* Follow the operating system when nobody has chosen. The :not() is what lets an
   explicit "light" win on a machine set to dark — without it the media query
   would quietly outrank the choice the reader made. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: var(--d-bg); --surface: var(--d-surface); --field: var(--d-field);
    --fg: var(--d-fg); --muted: var(--d-muted);
    --line: var(--d-line); --line-strong: var(--d-line-strong);
    --accent: var(--d-accent); --accent-bg: var(--d-accent-bg);
    --accent-wash: var(--d-accent-wash); --on-accent: var(--d-on-accent);
    --error: var(--d-error); --error-bg: var(--d-error-bg); --on-error: var(--d-on-error);
    --shadow: var(--d-shadow);
    --band-very-low: var(--d-band-very-low); --band-low: var(--d-band-low);
    --band-medium: var(--d-band-medium); --band-high: var(--d-band-high);
    --band-critical: var(--d-band-critical); --band-none: var(--d-band-none);
    --band-ink: var(--d-band-ink);
    --level-1: var(--d-level-1); --level-2: var(--d-level-2); --level-3: var(--d-level-3);
    --level-4: var(--d-level-4); --level-5: var(--d-level-5);
    --header: var(--d-header); --header-fg: var(--d-header-fg);
    --header-line: var(--d-header-line); --header-muted: var(--d-header-muted);
    --panel-line: var(--d-panel-line); --row-hover: var(--d-row-hover);
    --elev-1: var(--d-elev-1); --elev-2: var(--d-elev-2);
    --chart-band-opacity: var(--d-chart-band-opacity);
  }
}

/* And an explicit choice, which theme.js writes to the root element. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: var(--d-bg); --surface: var(--d-surface); --field: var(--d-field);
  --fg: var(--d-fg); --muted: var(--d-muted);
  --line: var(--d-line); --line-strong: var(--d-line-strong);
  --accent: var(--d-accent); --accent-bg: var(--d-accent-bg);
  --accent-wash: var(--d-accent-wash); --on-accent: var(--d-on-accent);
  --error: var(--d-error); --error-bg: var(--d-error-bg); --on-error: var(--d-on-error);
  --shadow: var(--d-shadow);
  --band-very-low: var(--d-band-very-low); --band-low: var(--d-band-low);
  --band-medium: var(--d-band-medium); --band-high: var(--d-band-high);
  --band-critical: var(--d-band-critical); --band-none: var(--d-band-none);
  --band-ink: var(--d-band-ink);
  --level-1: var(--d-level-1); --level-2: var(--d-level-2); --level-3: var(--d-level-3);
  --level-4: var(--d-level-4); --level-5: var(--d-level-5);
  --header: var(--d-header); --header-fg: var(--d-header-fg);
  --header-line: var(--d-header-line); --header-muted: var(--d-header-muted);
  --panel-line: var(--d-panel-line); --row-hover: var(--d-row-hover);
  --elev-1: var(--d-elev-1); --elev-2: var(--d-elev-2);
  --chart-band-opacity: var(--d-chart-band-opacity);
}

/* ------------------------------------------------------- scale and shape
   Not themed — these are the same in light and dark, so they sit outside the
   palette blocks. A named step is the point: the file used to reach for an
   arbitrary rem value at every call site, which is how a type scale drifts into
   eleven sizes that are each two pixels apart and mean nothing. */
:root {
  --text-2xs: 0.6875rem;
  --text-xs: 0.75rem;
  --text-sm: 0.8125rem;
  --text-base: 0.875rem;
  --text-md: 0.9375rem;
  --text-lg: 1.0625rem;
  --text-xl: 1.5rem;
  --text-2xl: 2rem;

  /* Headings tighten as they grow. Default tracking is drawn for body text and
     leaves large type looking gappy. */
  --track-tight: -0.015em;
  --track-tighter: -0.025em;
  --track-caps: 0.06em;

  --r-sm: 7px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-pill: 999px;

  /* Spacing, on a 4px grid and named by multiples of it: --sp-4 is 16px. Every
     margin, padding and gap in the file takes one of these, for the same reason
     the type scale exists — 0.85rem beside 0.9rem beside 1rem is not three
     decisions, it is drift, and the eye reads it as a page nobody lined up. */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.25rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-10: 2.5rem;
  --sp-12: 3rem;

  /* One height for everything you can type into or press, so a button beside a
     field lines up without either one being nudged. */
  --control-h: 2.375rem;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Sticky, because the register and the dashboard are both long enough that the
   nav scrolls out of reach inside one screen. The z-index only has to beat the
   panels; nothing else in the app stacks. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-6);
  border-bottom: 1px solid var(--header-line);
  background: var(--header);
  color: var(--header-fg);
}

.site-header nav { display: flex; align-items: center; gap: 0.15rem; }
.site-header nav form { margin-left: var(--sp-4); }
.header-end { display: flex; align-items: center; gap: var(--sp-3); }
.brand {
  font-size: var(--text-lg);
  font-weight: 650;
  text-decoration: none;
  color: var(--header-fg);
  letter-spacing: var(--track-tight);
}
.header-signin { color: var(--header-fg); font-size: var(--text-base); font-weight: 600; }
.tenant { color: var(--header-muted); font-size: var(--text-base); margin-left: var(--sp-2); }

/* Nav links get a hit area rather than sitting as bare underlined text. That is
   what lets the current section be marked with a filled pill — a colour change
   on an underlined link is a distinction nobody notices. */
.site-header nav > a {
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--r-sm);
  color: var(--header-fg);
  font-size: var(--text-base);
  font-weight: 550;
  text-decoration: none;
}
.site-header nav > a:hover { background: var(--accent-wash); }

/* Set from the resolved URL's app_name, so it follows the section rather than an
   exact path — a risk's history page is still the register. */
.site-header nav > a.is-current { background: var(--accent-bg); color: var(--on-accent); }

/* The Menu switch is for phones only; see the breakpoint below. */
.nav-toggle-input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.nav-toggle { display: none; }

/* Below this width the five links, the company and Sign out do not fit beside
   the brand, and a header wider than the screen makes every page scroll sideways.
   They fold behind a Menu button and open as a panel under the sticky header. */
@media (max-width: 860px) {
  .site-header { padding: var(--sp-2) var(--sp-4); }
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    min-height: 2.25rem;
    margin: 0;
    padding: var(--sp-1) var(--sp-3);
    border: 1px solid var(--header-line);
    border-radius: var(--r-sm);
    color: var(--header-fg);
    font-size: var(--text-base);
    font-weight: 600;
    cursor: pointer;
  }
  .nav-toggle-input:checked + .nav-toggle { background: var(--accent-wash); }
  .nav-toggle-input:focus-visible + .nav-toggle { outline: 2px solid var(--accent); outline-offset: 2px; }

  .site-header nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    padding: var(--sp-3) var(--sp-4) var(--sp-4);
    border-bottom: 1px solid var(--header-line);
    background: var(--header);
    box-shadow: var(--elev-2);
  }
  .nav-toggle-input:checked ~ nav { display: flex; }
  .site-header nav > a { padding: var(--sp-2) var(--sp-3); }
  .site-header nav .tenant {
    margin: var(--sp-2) 0 0;
    padding: var(--sp-3) var(--sp-3) 0;
    border-top: 1px solid var(--header-line);
  }
  .site-header nav form { margin: 0; padding: var(--sp-1) var(--sp-3); }
}

/* ---------------------------------------------------------- theme switch */

/* Hidden until theme.js has run. Without script the button cannot store a
   choice or repaint anything, and a control that does nothing when pressed is
   worse than no control — the media query already gives those readers the
   theme their machine asked for. */
.theme-toggle { display: none; }
:root.js-theme .theme-toggle {
  display: inline-flex;
  align-items: center;
  min-height: 0;
  margin: 0;
  padding: var(--sp-1);
  border: 1px solid var(--header-line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--header-muted);
  cursor: pointer;
}
.theme-toggle:hover { border-color: var(--line-strong); color: var(--header-fg); }
.theme-toggle svg { display: none; width: 1.05rem; height: 1.05rem; }

/* One icon per state, chosen in CSS from the attribute theme.js writes, so the
   button never disagrees with the page it is sitting on. */
:root:not([data-theme]) .theme-icon-auto,
:root[data-theme="light"] .theme-icon-light,
:root[data-theme="dark"] .theme-icon-dark { display: block; }

main { padding: var(--sp-8) var(--sp-6); }
.narrow { max-width: 24rem; margin: var(--sp-12) auto; }

h1 {
  font-size: var(--text-xl);
  font-weight: 640;
  letter-spacing: var(--track-tighter);
  line-height: 1.2;
  margin: 0 0 var(--sp-2);
}
.muted { color: var(--muted); }
.small { font-size: var(--text-base); }
.error { color: var(--error); }

label { display: block; margin: var(--sp-4) 0 var(--sp-1); font-size: var(--text-base); font-weight: 600; }

/* No field wider than what holds it. Django sizes a textarea to forty columns,
   which on a phone is wider than the screen and makes the whole page scroll. */
input, textarea, select { max-width: 100%; }

input[type="email"], input[type="text"] {
  width: 100%;
  min-height: var(--control-h);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  font: inherit;
  font-size: var(--text-md);
  line-height: 1.4;
}

input:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* One button, everywhere: the same height, size and weight whether it is a
   <button> or a link dressed as one. No margin of its own — space above a button
   belongs to whatever holds it, or two forms end up disagreeing by a few pixels
   about where their submit sits. */
button, a.button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--control-h);
  margin: 0;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--accent-bg);
  border-radius: var(--r-sm);
  background: var(--accent-bg);
  color: var(--on-accent);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.3;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

/* A field and then its submit, with nothing wrapping them: the old default
   margin, now only where it was ever wanted. */
form > :is(input:not([type="hidden"]), textarea, select, label, p, div, fieldset, ul, pre) + button {
  margin-top: var(--sp-5);
}

button.link {
  display: inline;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: inherit;
  font-weight: 400;
  text-decoration: underline;
}

a { color: var(--accent); }

/* ---------------------------------------------------------------- layout */

.page { max-width: 62rem; margin: 0 auto; }
.crumb { margin: 0 0 var(--sp-3); font-size: var(--text-base); }

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-4) var(--sp-6);
  margin-bottom: var(--sp-6);
}
/* The heading block takes the width; the actions take only what they need.
   Without this the intro paragraph was squeezed into a third of a narrow page. */
.page-head > :first-child { flex: 1 1 24rem; min-width: 0; }
.page-head > :first-child > p { max-width: 42rem; margin: var(--sp-2) 0 0; }
.page-head > :first-child > h1 { margin: 0; }

h2 {
  font-size: var(--text-md);
  font-weight: 620;
  letter-spacing: var(--track-tight);
  margin: 0 0 var(--sp-2);
}

/* Held by a shadow rather than a rule. The remaining hairline is there so the
   panel edge does not dissolve where its surface and the page are close in
   value, which is most of the light theme. */
.panel {
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
  padding: var(--sp-5) var(--sp-6);
  margin-bottom: var(--sp-4);
}

.panel-quiet { background: transparent; }

.panel > :last-child { margin-bottom: 0; }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-4); margin-top: var(--sp-6); }

/* The quiet partner of the primary button: same box, no fill. Used for every
   "the other way out" — back, cancel, add one more — so that the one filled
   button on a page is the one that moves the reader forward. */
button.secondary, a.button.secondary, .button-quiet {
  border-color: var(--line);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--elev-1);
}
button.secondary:hover, a.button.secondary:hover, .button-quiet:hover { border-color: var(--line-strong); }
button:not(.secondary, .link, .button-quiet, .danger, .choice):hover,
a.button:not(.secondary, .button-quiet):hover { filter: brightness(1.08); }

button.small, a.button.small { min-height: 2rem; padding: var(--sp-1) var(--sp-3); font-size: var(--text-sm); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ------------------------------------------------------------ band chips */

/* Underscored, matching Band.VERY_LOW's stored value: every template composes
   these class names as band-{{ band }} straight from the field, so a hyphen here
   silently leaves the least severe band unpainted. */
.band-very_low { background: var(--band-very-low); }
.band-low { background: var(--band-low); }
.band-medium { background: var(--band-medium); }
.band-high { background: var(--band-high); }
.band-critical { background: var(--band-critical); }
.band-none { background: var(--band-none); }

.band-pill {
  display: inline-block;
  padding: 0.15rem var(--sp-2);
  border-radius: var(--r-pill);
  color: var(--band-ink);
  font-size: var(--text-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.over { color: var(--error); }
.tag {
  display: inline-block;
  padding: 0.05rem var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: var(--text-xs);
  /* A pill that wraps is two half-pills. */
  white-space: nowrap;
}

/* ------------------------------------------------------------- 5x5 grid */

/* The grid is wide by design — the anchors are printed on the axes rather than
   hidden in help text, because a number chosen without them means nothing. On a
   narrow screen it scrolls sideways rather than collapsing, which would take the
   anchors away exactly where they matter most. */
/* Positioned so the hidden radios inside are clipped with the grid; otherwise
   they are placed against the page and widen it on a phone. */
.matrix-wrap { position: relative; overflow-x: auto; }

.matrix { border-collapse: separate; border-spacing: 3px; min-width: 42rem; }
.matrix-axis {
  padding-bottom: var(--sp-2);
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 550;
  text-align: center;
}
.matrix-axis-side { color: var(--muted); font-size: 0.8rem; font-weight: 550; }
.matrix-corner { width: 9rem; vertical-align: bottom; }

.matrix-head { font-weight: 400; text-align: left; vertical-align: bottom; padding: 0 var(--sp-1) var(--sp-1); }
.matrix-head-row { width: 9rem; vertical-align: middle; }
.matrix-head-name { display: block; font-size: 0.8rem; font-weight: 600; }
.matrix-head-anchor { display: block; color: var(--muted); font-size: 0.7rem; line-height: 1.3; }

.matrix-cell { padding: 0; border-radius: 6px; text-align: center; }
.matrix-radio { position: absolute; opacity: 0; pointer-events: none; }

.matrix-score {
  display: block;
  padding: var(--sp-3) 0.2rem;
  border: 2px solid transparent;
  border-radius: 6px;
  color: var(--band-ink);
  font-size: 0.95rem;
  font-weight: 550;
  cursor: pointer;
}

.matrix-score:hover { border-color: var(--line-strong); }
.matrix-radio:checked + .matrix-score { border-color: var(--fg); box-shadow: inset 0 0 0 2px var(--surface); }
.matrix-radio:focus-visible + .matrix-score { outline: 2px solid var(--accent); outline-offset: 1px; }

.matrix-readonly .matrix-score { cursor: default; padding: var(--sp-2) 0.2rem; }
.matrix-readonly .is-selected .matrix-score { border-color: var(--fg); box-shadow: inset 0 0 0 2px var(--surface); }

/* The read-only grid on a risk's page fits a phone by dropping the level
   descriptions, and the impact names above the columns: five of them do not fit
   across, so the columns are numbered under their axis label and the rows keep
   their names. The grid on the raise form keeps everything and scrolls inside its
   box instead: there the descriptions are what you choose by. */
@media (max-width: 640px) {
  .matrix-readonly { min-width: 0; width: 100%; table-layout: fixed; }
  .matrix-readonly .matrix-head-anchor { display: none; }
  .matrix-readonly .matrix-corner,
  .matrix-readonly .matrix-head-row { width: 4.75rem; }
  .matrix-readonly .matrix-head-name { font-size: 0.7rem; }
  .matrix-readonly thead .matrix-head-word { display: none; }
  .matrix-readonly thead .matrix-head { text-align: center; }
}

/* --------------------------------------------------------- score readout */

.readout { margin-top: var(--sp-4); }
.readout-headline { display: flex; align-items: baseline; gap: var(--sp-2); margin: 0 0 var(--sp-1); }
.readout-score {
  font-size: var(--text-2xl);
  font-weight: 650;
  letter-spacing: var(--track-tighter);
  font-variant-numeric: tabular-nums;
}
.readout-of { color: var(--muted); font-size: var(--text-sm); }

.score-row { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.score-row .score-panel { flex: 1 1 18rem; }

.axes { margin: var(--sp-2) 0 0; }
.axes dt { font-size: 0.85rem; font-weight: 600; margin-top: var(--sp-2); }
.axes dd { margin: 0.1rem 0 0; }

.detail-list dt { font-size: 0.8rem; font-weight: 600; color: var(--muted); margin-top: var(--sp-3); }
.detail-list dd { margin: 0.15rem 0 0; }
.detail-list dt:first-child { margin-top: 0; }

/* -------------------------------------------------------------- register */

/* The title is the column doing the reading; the rest are short values. Left to
   themselves the tracked-out capitals in the head divide the width evenly and
   wrap every risk name onto four lines. */
.register th:first-child { width: 26%; }
.register th.numeric { width: 7rem; }

/* No rule under every row. Ten columns of hairlines is a grid the eye has to
   climb over to read a title; the separation comes from vertical space and from
   a tint that follows the pointer instead. The one rule that stays is under the
   head, because that is a real boundary rather than a repeated one. */
.register { width: 100%; border-collapse: collapse; }
.register th, .register td {
  padding: var(--sp-3) var(--sp-2);
  text-align: left;
  vertical-align: top;
}
.register thead th {
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}
.register tbody td { padding-top: var(--sp-3); padding-bottom: var(--sp-3); }

/* Every number in the register is compared against the number above it, which
   only works if the digits are the same width. */
.register .numeric { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* The hover tint is the row separator now, so it has to reach the full width of
   the row — hence the rounding on the end cells rather than on the tr, which
   cannot take a radius. */
.register tbody tr:hover { background: var(--row-hover); }
.register tbody tr td:first-child { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.register tbody tr td:last-child { border-radius: 0 var(--r-sm) var(--r-sm) 0; }

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
  margin-bottom: var(--sp-5);
}
/* A column, and explicitly not a wrapping one: .filters above sets flex-wrap for
   the row layout the control library still uses, and a wrapping *column* flows
   into columns and stretches each line to fill — which is where the empty band
   above the search box came from. */
form.filters {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: var(--sp-4);
}

.filter-top { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3); }
.filter-q { flex: 1 1 18rem; }
.filter-q input { width: 100%; }

.filter-row { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-10); }
.filter-row-selects { align-items: flex-end; gap: var(--sp-4) var(--sp-5); }

/* Apply sits at the foot of a rail taller than the screen, which would put it
   out of sight at the moment it is wanted. Pinned to the bottom of the rail's
   own scroll instead, with the surface carried under it so the chips do not
   scroll through the text. */
.split-filters .filter-actions {
  position: sticky;
  bottom: -1rem;
  margin: 0 calc(-1 * var(--sp-4)) calc(-1 * var(--sp-4));
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border-top: 1px solid var(--panel-line);
}

/* In the rail every group gets its own row — there is no width to put two
   side by side, and a select that has to share it is unreadable. */
.split-filters .filter-top,
.split-filters .filter-row { flex-direction: column; align-items: stretch; gap: var(--sp-4); }
.split-filters .filter-q { flex: 1 1 auto; }
.split-filters select { width: 100%; }
.split-filters .filter-check { flex-direction: row; align-items: center; }

/* ------------------------------------------------------------------ chips

   A dropdown answers "which one"; these answer "which of these", which is the
   question a register is actually asked. Severity is the case that forces it:
   "High and Critical" cannot be expressed by a control that permits one value,
   and it is the commonest thing anybody wants from the list.

   Checkbox and radio chips are deliberately identical to look at. Whether a
   group takes one answer or several is a property of the question, not something
   the reader should have to learn per filter — they click, and the group either
   keeps the previous answer or drops it. */
.chipset { min-width: 0; margin: 0; padding: 0; border: 0; }
.chipset legend {
  padding: 0;
  margin-bottom: var(--sp-2);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--muted);
}

.chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); }

/* Off-screen rather than display:none, which would take the input out of the tab
   order and make the whole panel unreachable from the keyboard. */
.chips input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

.chips .chip {
  display: inline-block;
  margin: 0;
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--field);
  color: var(--fg);
  font-size: var(--text-base);
  font-weight: 500;
  text-transform: none;
  letter-spacing: normal;
  white-space: nowrap;
  cursor: pointer;
}

.chips .chip:hover { border-color: var(--line-strong); }

.chips input:checked + .chip {
  border-color: var(--accent-bg);
  background: var(--accent-bg);
  color: var(--on-accent);
  font-weight: 600;
}

.chips input[value=""]:checked + .chip {
  border-color: var(--line-strong);
  background: var(--surface);
  color: var(--fg);
  font-weight: 600;
}

.chips input:focus-visible + .chip { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ------------------------------------------------------- company profile

   One answer style for every question, so a step reads as one form rather than a
   collage. A box for "choose any", a circle for "choose one" — the same marks a
   paper form uses — and the answers flow and wrap at their natural width. */

.narrow-page.wizard-page { max-width: 48rem; }

/* Steps along the top. A real sequence, so it is numbered; done steps are filled,
   the current one is ringed, the rest are quiet. */
.stepper {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-6);
  padding: 0;
  list-style: none;
  /* Clear of the sticky header when a step change scrolls back up to it. */
  scroll-margin-top: 5rem;
}
.stepper-step > a, .stepper-step > .stepper-num { text-decoration: none; }
.stepper-step > a,
.stepper-step:not(:has(a)) {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2) var(--sp-1) var(--sp-1);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 550;
}
.stepper-step > a:hover { background: var(--row-hover); color: var(--fg); }
.stepper-num {
  display: inline-grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  font-size: var(--text-xs);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.stepper-step.is-current > a,
.stepper-step.is-current:not(:has(a)) { background: var(--surface); color: var(--fg); box-shadow: var(--elev-1); }
.stepper-step.is-current .stepper-num { border-color: var(--accent-bg); background: var(--accent-bg); color: var(--on-accent); }
.stepper-step.is-done .stepper-num { border-color: var(--accent); color: var(--accent); background: var(--accent-wash); }

/* Without script every step is on the page, so the per-step buttons are hidden
   and the one submit at the bottom does the work. */
.wizard-nav { display: none; }
.js-wizard .wizard-nav {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}
.js-wizard .wizard-nav [data-wizard-next] { margin-left: auto; }
/* The last step carries the submit inside its own card; the one below the form
   is the no-script submit. A returning company keeps the one below on every
   step, so changing one answer does not mean paging to the end. */
.wizard-nav [type="submit"] { display: none; }
.js-wizard:not([data-wizard-edit]) .wizard-final { display: none; }
.js-wizard:not([data-wizard-edit]) .wizard-nav [type="submit"] { display: inline-flex; margin-left: auto; }
.js-wizard .wizard-final { margin-top: var(--sp-4); }

.wizard-step { padding: var(--sp-6) var(--sp-8) var(--sp-8); }
.wizard-step-head { margin-bottom: var(--sp-6); }
.wizard-step-count { margin: 0; color: var(--muted); font-size: var(--text-sm); }
.wizard-step-title {
  margin: var(--sp-1) 0 0;
  font-size: var(--text-xl);
  font-weight: 640;
  letter-spacing: var(--track-tighter);
}
.wizard-step-title:focus { outline: none; }

/* A question reads as a question: full ink, sentence case, the size of a lead
   paragraph — not a tracked-out caption above its answers. */
.question { min-width: 0; margin: 0 0 var(--sp-8); padding: 0; border: 0; }
.question:last-of-type { margin-bottom: 0; }
.question-ask {
  display: block;
  margin-bottom: var(--sp-3);
  padding: 0;
  font-size: var(--text-md);
  font-weight: 620;
  line-height: 1.4;
}
.question-hint { display: block; margin-top: var(--sp-1); color: var(--muted); font-size: var(--text-sm); font-weight: 400; }

/* Off-screen rather than display:none, so every answer stays in the tab order. */
.options > input, .decision > input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.option {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 500;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms, color 120ms;
}
.options > input:focus-visible + .option,
.decision > input:focus-visible + .choice { outline: 2px solid var(--accent); outline-offset: 2px; }
.options > input:disabled + .option { cursor: default; opacity: 0.7; }

.options { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.option {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--sp-2);
  max-width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  line-height: 1.4;
}
.option::before {
  content: "";
  flex: none;
  width: 0.875rem;
  height: 0.875rem;
  margin-top: 0.15rem;
  border: 1.5px solid var(--line-strong);
  border-radius: 3px;
  background: var(--surface);
}
.options > input[type="radio"] + .option::before { border-radius: 50%; }
.option:hover { border-color: var(--line-strong); }
.options > input:checked + .option {
  border-color: var(--accent);
  background: var(--accent-wash);
  color: var(--fg);
}
.options > input:checked + .option::before {
  border-color: var(--accent-bg);
  background: var(--accent-bg);
  box-shadow: inset 0 0 0 2px var(--surface);
}
.option-skip { border-style: dashed; background: transparent; color: var(--muted); }
.options > input:checked + .option-skip { border-color: var(--line-strong); background: transparent; color: var(--muted); }
.options > input:checked + .option-skip::before { border-color: var(--line-strong); background: var(--line-strong); }

/* Tools come in named groups: the name sits just above its answers, close enough
   to belong to them and far enough from the group before. */
.option-group + .option-group { margin-top: var(--sp-4); }
.option-group-name { margin: 0 0 var(--sp-2); color: var(--muted); font-size: var(--text-sm); font-weight: 600; }

@media (max-width: 560px) {
  .wizard-step { padding: var(--sp-5) var(--sp-4) var(--sp-6); }
  .stepper-title { display: none; }
  .stepper-step.is-current .stepper-title { display: inline; }
}

/* ----------------------------------------------------------- quick checks */

.check-group + .check-group { margin-top: var(--sp-6); padding-top: var(--sp-6); border-top: 1px solid var(--line); }
.check-control { margin: 0 0 var(--sp-3); font-size: var(--text-lg); }
.check-row { min-width: 0; margin: 0; padding: 0; border: 0; }
.check-row + .check-row { margin-top: var(--sp-5); }
.check-ask { margin-bottom: var(--sp-2); padding: 0; font-size: var(--text-base); font-weight: 550; }

/* ------------------------------------------------------- suggestion review */

.count {
  display: inline-grid;
  place-items: center;
  min-width: 1.5rem;
  height: 1.5rem;
  margin-left: var(--sp-1);
  padding: 0 var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--bg);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  vertical-align: 0.1em;
}

.callout {
  margin-bottom: var(--sp-6);
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--panel-line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-md);
  background: var(--accent-wash);
}
.callout p { margin: 0; }

/* One suggested risk: what it is on the left, the decision on the right. */
.suggestion {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-3) var(--sp-6);
  padding: var(--sp-5) 0;
  border-top: 1px solid var(--line);
}
.panel > h2 + .suggestion, details > p + .suggestion { border-top: 0; }
.suggestion:last-child { padding-bottom: 0; }
.suggestion-title {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 620;
  line-height: 1.4;
  letter-spacing: var(--track-tight);
}
.suggestion-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  margin: var(--sp-2) 0 0;
  font-size: var(--text-sm);
}
.suggestion-more { margin-top: var(--sp-2); font-size: var(--text-base); }
.suggestion-more summary { color: var(--muted); font-size: var(--text-sm); }
.suggestion-more p { margin: var(--sp-2) 0 0; }

/* The panel's three questions, each under its own small heading, with a rule
   between them so the reasons, the note and the controls read as separate things. */
.why { margin-top: var(--sp-3); border-left: 2px solid var(--line); padding-left: var(--sp-4); }
.why-part + .why-part { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.why-part h4 {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-size: var(--text-xs);
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
.why-part p.small { margin-top: var(--sp-1); }
.why-reasons { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin: var(--sp-2) 0 0; padding: 0; list-style: none; }
.why-controls { margin: var(--sp-3) 0 0; padding: 0; list-style: none; }
.why-controls li { padding: var(--sp-2) 0; }
.why-controls li + li { border-top: 1px dashed var(--line); }
.why-control-name { margin-right: var(--sp-2); }
.why-control-detail { display: block; margin-top: 0.15rem; }

/* Relevant / Not relevant. Two real choices rather than a tick: both are kept,
   and the one that is pressed is unmistakable at a glance down the page. */
.decision { display: flex; align-items: flex-start; gap: var(--sp-2); }
.choice {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--control-h);
  margin: 0;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms, color 120ms;
}
.choice svg { width: 0.9rem; height: 0.9rem; }
.choice:hover { border-color: var(--line-strong); color: var(--fg); }
.decision > input:checked + .choice-yes { border-color: var(--accent-bg); background: var(--accent-bg); color: var(--on-accent); }
.decision > input:checked + .choice-no { border-color: var(--error); background: transparent; color: var(--error); box-shadow: inset 0 0 0 1px var(--error); }

/* Ruled out reads as ruled out: the title steps back, and the reason box opens. */
.suggestion:has(input[value="off"]:checked) .suggestion-title { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--line-strong); }
.suggestion-reason { display: none; grid-column: 1 / -1; }
.suggestion:has(input[value="off"]:checked) .suggestion-reason { display: block; }
.suggestion-reason label { margin: 0 0 var(--sp-1); font-size: var(--text-sm); font-weight: 550; }
@supports not selector(:has(*)) { .suggestion-reason { display: block; } }

@media (max-width: 640px) {
  .suggestion { grid-template-columns: minmax(0, 1fr); }
}

.flag { padding: var(--sp-4) 0; border-top: 1px solid var(--line); }
.panel > p + .flag { border-top: 0; }
.flag p { margin: 0; }
.flag-ack { margin-top: var(--sp-2); color: var(--muted); font-size: var(--text-sm); }

/* A regime, or one entry in a library release: a block per item, ruled like a flag. */
.regime, .release-entry { padding: var(--sp-3) 0; border-top: 1px solid var(--line); }
.panel > p + .regime, .panel > p + .release-entry { border-top: 0; }
.regime h3, .release-entry h3 { margin: 0 0 var(--sp-1); font-size: var(--text-md); }
.regime p, .release-entry p { margin: 0 0 var(--sp-1); }
.regime ul { margin: var(--sp-1) 0; padding-left: var(--sp-4); }

/* The ask for an account, at the foot of the public suggestions. */
.keep { border-color: var(--accent); box-shadow: var(--elev-1), inset 3px 0 0 var(--accent); }
.keep-title { font-size: var(--text-lg); }
.keep .field-row label { margin-top: var(--sp-3); }

/* Pinned to the bottom while the list scrolls past, so the save is never a
   scroll away and the count of what it will do is always in view. */
.decision-bar {
  position: sticky;
  bottom: var(--sp-4);
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-6);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-5);
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-2);
}
.decision-count { margin: 0; font-size: var(--text-base); font-weight: 600; }
.decision-bar-actions { display: flex; gap: var(--sp-2); margin-left: auto; }

/* One suggestion per row, ruled like the register so the review reads as the
   register it is about to become. */
.proposal-item { padding: var(--sp-4) 0; border-top: 1px solid var(--line); }
.proposal-item:first-of-type { border-top: 0; }
.proposal-item p { margin: var(--sp-1) 0 0; }
.proposal-item details { margin-top: var(--sp-2); }
.proposal-item ul { margin: var(--sp-2) 0 0; padding-left: var(--sp-5); }
.inline-check { display: flex; gap: var(--sp-2); align-items: baseline; margin: 0; font-weight: 500; }
.inline-check input { flex: none; }

.filters label {
  margin: 0 0 var(--sp-1);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--muted);
}
.filters input, .filters select {
  padding: var(--sp-2) var(--sp-2);
  border-radius: var(--r-sm);
  font-size: var(--text-base);
}
.filter-check { display: flex; align-items: center; gap: var(--sp-2); }
.filter-check label {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}
/* Apply and Clear get a row to themselves rather than trailing whichever field
   happened to end the last one. Full basis rather than a reorder — putting them
   first would move the primary action above the fields it applies to. */
form.filters .filter-actions { flex-basis: 100%; }
.filter-actions { display: flex; align-items: center; gap: var(--sp-3); }

/* ------------------------------------------------- split view (list + pane) */

/* The register and the control library are both worked through one item at a
   time, which a table makes into a round trip per item. The list keeps enough to
   choose by; the pane answers the rest without leaving the page.

   The page is capped at 62rem elsewhere; a two-column layout needs more than
   that to give either column a usable width. */
.page-split { max-width: 94rem; }

.split {
  display: grid;
  grid-template-columns: minmax(0, 24rem) minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}

/* Three columns on the register: filters, list, pane. The rail is narrow enough
   that it costs the pane little and wide enough that a chip row is two lines
   rather than five. */
.split.has-filters {
  grid-template-columns: minmax(0, 16.5rem) minmax(0, 22rem) minmax(0, 1fr);
}

/* The rail is the panel now, so the form carries the panel's own surface. */
.split-filters {
  margin-bottom: 0;
  padding: var(--sp-4) var(--sp-4);
}

/* Wide enough for three columns means wide enough that the fold is pointless:
   the rail is beside the list, not on top of it, so leaving it open costs the
   reader nothing and saves them a click before every filter. */
.filter-toggle { display: none; }

/* Each column scrolls on its own against the viewport, so a long register does
   not push the pane off the bottom of the page and a long pane does not leave
   the list stranded. Offset by the sticky header's height. */
.split-filters, .split-list, .split-pane {
  position: sticky;
  top: 4.5rem;
  max-height: calc(100vh - 6rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.split-count {
  margin: 0 0 var(--sp-2);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  font-size: var(--text-xs);
  font-weight: 600;
}

/* -------------------------------------------------------------- list rows */

.pick {
  display: block;
  padding: var(--sp-3) var(--sp-3);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  color: var(--fg);
  text-decoration: none;
}

.pick + .pick { margin-top: 0.15rem; }
.pick:hover { background: var(--row-hover); }

/* The selected row is a filled card rather than a tint, because the tint is
   already spoken for by hover and the two would be indistinguishable on the row
   the pointer happens to be over. */
.pick.is-selected {
  background: var(--surface);
  border-color: var(--line);
  box-shadow: var(--elev-1);
}

.pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.pick-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
}
.pick-title {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: var(--track-tight);
}
.pick-head .band-pill { flex-shrink: 0; }

.pick-meta {
  display: block;
  margin-top: 0.2rem;
  color: var(--muted);
  font-size: var(--text-sm);
}

/* Empty unless something is owed, so it collapses to nothing on a healthy row
   rather than reserving a line for the word "fine". */
.pick-flags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--text-xs);
  font-weight: 600;
}
.pick-flags:not(:empty) { margin-top: var(--sp-1); }

/* ------------------------------------------------------------- the pane */

.split-pane {
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
}

.summary { padding: var(--sp-6) var(--sp-6); }
.summary-title {
  font-size: var(--text-lg);
  font-weight: 640;
  letter-spacing: var(--track-tight);
  line-height: 1.3;
  margin: 0 0 var(--sp-1);
}
.summary-meta { margin: 0 0 var(--sp-4); }

.summary-scores {
  display: grid;
  /* Capped rather than stretched: three figures spread across a full-width pane
     stop reading as one group. */
  max-width: 38rem;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--sp-3);
  margin: 0 0 var(--sp-5);
  padding: var(--sp-4) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--bg);
}
.summary-scores dt {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--muted);
}
.summary-scores dd { margin: var(--sp-1) 0 0; font-size: var(--text-base); }

/* Two columns: the label reads down the left edge, the values line up beside
   it. A definition list rather than a table because that is what it is. */
.summary-facts {
  display: grid;
  grid-template-columns: 10.5rem minmax(0, 1fr);
  gap: var(--sp-2) var(--sp-4);
  margin: 0;
  max-width: 46rem;
  font-size: var(--text-base);
}
.summary-facts dt { color: var(--muted); font-weight: 600; }
.summary-facts dd { margin: 0; }

.summary-description {
  margin: var(--sp-5) 0 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--text-base);
}

.pane-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 16rem;
  padding: var(--sp-8);
  text-align: center;
}


/* Below this width there is no room for two columns, so the pane goes under the
   list and both stop being sticky — a sticky column shorter than the viewport is
   just a column that will not scroll. */
/* No room for a third column: the rail becomes a block above the list, and folds
   again, because a full-width filter panel is the thing that had to be folded in
   the first place. The checkbox is the control; the label is what you see. */
@media (max-width: 1279px) {
  .split.has-filters { grid-template-columns: minmax(0, 24rem) minmax(0, 1fr); }

  .split-filters {
    grid-column: 1 / -1;
    order: -1;
    position: static;
    max-height: none;
    overflow-y: visible;
  }
  #filter-toggle:not(:checked) ~ .split-filters { display: none; }

  .filter-toggle {
    display: inline-block;
    grid-column: 1 / -1;
    order: -2;
    justify-self: start;
    margin: 0;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--muted);
    font-size: var(--text-base);
    font-weight: 550;
    text-transform: none;
    letter-spacing: normal;
    cursor: pointer;
  }
  .filter-toggle:hover { border-color: var(--line-strong); color: var(--fg); }
  #filter-toggle:focus-visible ~ .filter-toggle { outline: 2px solid var(--accent); outline-offset: 2px; }
}

@media (max-width: 1023px) {
  .split, .split.has-filters { grid-template-columns: minmax(0, 1fr); }
  .split-list, .split-pane {
    position: static;
    max-height: none;
    overflow-y: visible;
  }
}

/* ------------------------------------------------------------ empty state */

.empty {
  padding: var(--sp-10) var(--sp-6);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  text-align: center;
}
.empty-first-run { max-width: 34rem; margin: 0 auto; text-align: left; }
.empty-first-run p { color: var(--muted); }
.empty-first-run .actions { justify-content: flex-start; }
.example-preview { margin-top: var(--sp-4); }

/* ---------------------------------------------------------------- forms */

.risk-form select,
.risk-form textarea,
.risk-form input[type="text"] {
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--field);
  font: inherit;
}

.field-row { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.field-row > div { flex: 1 1 12rem; }
.field-row label { margin-top: var(--sp-3); }

/* ------------------------------------------------------- control library */

/* Effectiveness levels are a maturity ladder, not a severity scale, so they get
   their own ramp — reusing the band colours would imply a "critical" control. */
.level-1 { background: var(--level-1); }
.level-2 { background: var(--level-2); }
.level-3 { background: var(--level-3); }
.level-4 { background: var(--level-4); }
.level-5 { background: var(--level-5); }

.level-pill {
  display: inline-block;
  padding: 0.15rem var(--sp-2);
  border-radius: var(--r-pill);
  color: var(--band-ink);
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
}

.levels { list-style: none; margin: var(--sp-3) 0 0; padding: 0; display: grid; gap: var(--sp-2); }
.levels input { position: absolute; opacity: 0; pointer-events: none; }

.levels label {
  display: block;
  margin: 0;
  padding: var(--sp-3) var(--sp-3);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  font-weight: 400;
  cursor: pointer;
}

.levels label:hover { border-color: var(--line-strong); }
.levels input:checked + label { border-color: var(--accent); border-left-color: var(--accent); background: var(--accent-wash); }
.levels input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 1px; }

.level-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); }
.level-name { font-size: 0.9rem; font-weight: 600; }
.level-reduction { color: var(--muted); font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.level-anchor { display: block; margin-top: 0.15rem; font-size: 0.875rem; }
.level-evidence { display: block; margin-top: 0.15rem; color: var(--muted); font-size: 0.8rem; }

.axis-choices ul { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: grid; gap: var(--sp-1); }
.axis-choices label { display: inline; margin: 0; font-weight: 400; }

/* -------------------------------------------------------- control picker */

/* Step one of linking. Cards rather than a table: the reader is choosing one
   thing, not comparing a column, and a card has room for the description that
   tells two similarly named controls apart. The whole card is the link. */
.page-pick { max-width: 48rem; }

.linkpick-head { margin-bottom: var(--sp-5); }
.linkpick-head h1 { margin: 0 0 var(--sp-2); }
.linkpick-head > p:last-child { max-width: 40rem; margin: 0; }
.linkpick-step {
  margin: 0 0 var(--sp-1);
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.linkpick-risk { color: var(--muted); font-weight: 500; }

.linkpick-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-1) var(--sp-1) 2.5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field);
  box-shadow: var(--elev-1);
}
.linkpick-search:focus-within { border-color: var(--accent); outline: 2px solid var(--accent-wash); }
.linkpick-search-icon { position: absolute; left: var(--sp-3); color: var(--muted); pointer-events: none; }
.linkpick-search input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--control-h);
  padding: var(--sp-2) 0;
  border: 0;
  background: transparent;
  color: var(--fg);
  font: inherit;
  font-size: var(--text-md);
}
.linkpick-search input[type="search"]:focus-visible { outline: none; }
/* Typing filters already; the button is only the no-script round trip. */
.linkpick-search.is-live .linkpick-search-go { display: none; }

.linkpick-count { margin: var(--sp-3) 0 var(--sp-3); }

.linkpick-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.linkpick-card[hidden] { display: none; }

.linkpick-card-link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 9.5rem auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-5);
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
  color: var(--fg);
  text-decoration: none;
  transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}
.linkpick-card-link:hover { border-color: var(--accent); box-shadow: var(--elev-2); transform: translateY(-1px); }
.linkpick-card-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.linkpick-card-body { display: grid; gap: var(--sp-1); min-width: 0; }
.linkpick-card-name { font-size: var(--text-lg); font-weight: 620; letter-spacing: var(--track-tight); }
.linkpick-card-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--muted);
  font-size: var(--text-base);
}
.linkpick-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  margin-top: var(--sp-1);
  color: var(--muted);
  font-size: var(--text-sm);
}
.linkpick-card-meta > span:not(.tag) + span:not(.tag)::before { content: "·"; margin-right: var(--sp-3); }
.linkpick-card-meta > span { overflow-wrap: anywhere; }

/* The rating as a tile in the level's own fill, with a five-step meter: the
   ladder is the thing being taught, so the position on it is drawn, not only
   named. */
.linkpick-card-rating {
  display: grid;
  gap: 0.2rem;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  color: var(--band-ink);
}
.linkpick-meter { display: grid; grid-template-columns: repeat(5, 1fr); gap: 3px; margin-bottom: 0.15rem; }
.linkpick-meter i { height: 5px; border-radius: 2px; background: var(--band-ink); opacity: 0.14; }
.linkpick-meter[data-level="1"] i:nth-child(-n+1),
.linkpick-meter[data-level="2"] i:nth-child(-n+2),
.linkpick-meter[data-level="3"] i:nth-child(-n+3),
.linkpick-meter[data-level="4"] i:nth-child(-n+4),
.linkpick-meter[data-level="5"] i { opacity: 0.7; }
.linkpick-card-level { font-size: var(--text-base); font-weight: 650; }
.linkpick-card-cut { font-size: var(--text-xs); font-variant-numeric: tabular-nums; opacity: 0.8; }

.linkpick-card-go { color: var(--accent); font-size: var(--text-sm); font-weight: 650; white-space: nowrap; }

.linkpick-none { margin-top: var(--sp-2); }
.linkpick-foot { margin-top: var(--sp-5); text-align: center; }

@media (max-width: 640px) {
  .linkpick-card-link { grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); padding: var(--sp-4); }
  .linkpick-card-rating { grid-template-columns: auto auto 1fr; align-items: center; gap: var(--sp-3); }
  .linkpick-meter { width: 4rem; margin: 0; }
  .linkpick-card-cut { justify-self: end; }
  .linkpick-card-go { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .linkpick-card-link { transition: none; }
  .linkpick-card-link:hover { transform: none; }
}

.filters a.is-current { color: var(--fg); font-weight: 600; text-decoration: none; }

/* ------------------------------------------------------- residual panel */

.score-panel-primary { border-color: var(--line-strong); box-shadow: 0 1px 2px var(--shadow); }
.floor-note { margin-top: var(--sp-2); padding-top: var(--sp-2); border-top: 1px solid var(--line); }

.prose p { margin: 0 0 var(--sp-2); }
.prose-overall { font-weight: 600; }
.stale-warning { margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line); }

.axis-heading {
  margin: var(--sp-6) 0 var(--sp-2);
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.contributions td { vertical-align: middle; }

/* On a phone each control on a risk is one line of facts under its name, rather
   than six columns that wrap the name a word per line. The cells keep their order
   (rated, relevance, on its own, counted); the two percentages get their names. */
@media (max-width: 640px) {
  .contributions thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .contributions, .contributions tbody { display: block; }
  .contributions tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-1) var(--sp-3);
    padding: var(--sp-3) 0;
  }
  .contributions tr + tr { border-top: 1px solid var(--line); }
  .contributions tbody td { display: block; padding: 0; }
  .contributions td:first-child { flex: 1 0 100%; }
  .contributions td:nth-child(4), .contributions td:nth-child(5) { font-size: var(--text-sm); }
  .contributions td:nth-child(4)::before { content: "on its own "; }
  .contributions td:nth-child(5)::before { content: "counted "; color: var(--muted); }
  .contributions td:nth-child(6) { margin-left: auto; }
}
/* A control contributing nothing still appears, dimmed. Hiding it would leave the
   user wondering where it went; the point is to make decorative controls visible. */
.is-decorative { opacity: 0.62; }

.adjusters { display: grid; gap: var(--sp-2); }
.adjuster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field);
}
.adjuster-name { flex: 1 1 12rem; font-size: 0.875rem; font-weight: 550; }
.adjuster select { padding: var(--sp-1) var(--sp-2); font-size: 0.85rem; }
.adjuster button { min-height: 0; padding: var(--sp-1) var(--sp-2); font-size: var(--text-sm); }

/* htmx submits on change, so the button is only needed when htmx is absent. */
.htmx-enabled .adjuster-apply { display: none; }

/* Grid markers: the inherent cell is outlined, the residual filled. Two different
   shapes rather than two colours, so the movement survives a colour-blind reader
   and a black-and-white print of the register. */
.matrix-readonly .is-selected .matrix-score {
  border-color: var(--muted);
  border-style: dashed;
  box-shadow: none;
}
.matrix-readonly .is-residual .matrix-score {
  border-color: var(--fg);
  border-style: solid;
  box-shadow: inset 0 0 0 2px var(--surface);
  font-weight: 700;
}

.key {
  display: inline-block;
  width: 0.9rem;
  height: 0.9rem;
  margin: 0 0.15rem 0 var(--sp-2);
  border-radius: 3px;
  vertical-align: -0.1rem;
}
.key-inherent { border: 2px dashed var(--muted); }
.key-residual { border: 2px solid var(--fg); }

.inactive-links { list-style: none; margin: var(--sp-2) 0 0; padding: 0; color: var(--muted); }
.inactive-links li { padding: var(--sp-1) 0; }

/* ------------------------------------------------------ history (phase 6) */

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
}
.panel-head h2 { margin: 0; }

.timeline { list-style: none; margin: var(--sp-4) 0 0; padding: 0; }

.timeline-entry {
  position: relative;
  margin: 0;
  padding: var(--sp-3) 0 var(--sp-3) var(--sp-4);
  border-left: 2px solid var(--line);
}
/* The dot on the rail. Drawn rather than a list marker so the rail stays
   continuous between entries and the whole thing reads as one sequence. */
.timeline-entry::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 1.1rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
/* An entry where the score did not move. Still shown — a recompute that changed
   nothing is evidence the register was maintained — but visibly quieter, so the
   movements are what the eye lands on. */
.timeline-held::before { background: var(--line); }
.timeline-held .timeline-move { color: var(--muted); }

.timeline-head { margin: 0; font-size: 0.9rem; }
.timeline-what { font-weight: 600; }
.timeline-move { margin: var(--sp-1) 0 0; }
.timeline-arrow { margin: 0 0.15rem; color: var(--muted); }
.timeline-meta { margin: var(--sp-1) 0 0; }

.diff { margin: var(--sp-2) 0 0; font-size: 0.875rem; }
.diff dt { margin-top: var(--sp-1); font-size: 0.75rem; font-weight: 600; color: var(--muted); }
.diff dd { margin: 0.1rem 0 0; }
.diff-before { color: var(--muted); text-decoration: line-through; }
.diff-after { font-weight: 550; }

.pager { display: flex; align-items: center; gap: var(--sp-4); margin-top: var(--sp-4); }

/* ------------------------------------------------------- the score chart */

.chart-wrap { margin-top: var(--sp-3); }
.score-chart { width: 100%; height: auto; overflow: visible; }

/* SVG fills, not backgrounds: the band swatch classes elsewhere paint a
   background, which does nothing to a <rect>. Both read the same custom
   properties, so the colours stay defined in exactly one place. */
.chart-band { opacity: var(--chart-band-opacity); }
.chart-band.band-very_low { fill: var(--band-very-low); }
.chart-band.band-low { fill: var(--band-low); }
.chart-band.band-medium { fill: var(--band-medium); }
.chart-band.band-high { fill: var(--band-high); }
.chart-band.band-critical { fill: var(--band-critical); }

.chart-tick { stroke: var(--surface); stroke-width: 1; opacity: 0.7; }
.chart-tick-label { fill: var(--muted); font-size: 9px; }
.chart-date { fill: var(--muted); font-size: 10px; }

.chart-inherent { stroke: var(--muted); stroke-width: 1.5; stroke-dasharray: 4 3; }
.chart-residual { stroke: var(--fg); stroke-width: 2; }
.chart-point { fill: var(--fg); }

.chart-marker { stroke: var(--accent); stroke-width: 1; stroke-dasharray: 2 2; }
.chart-marker-label { fill: var(--accent); font-size: 9px; font-weight: 600; }
.key-methodology { border-left: 2px dashed var(--accent); border-radius: 0; width: 0; }

/* ------------------------------------------------- acceptance (phase 7) */

/* The one panel that is allowed to be loud, and only in one state: a risk above
   appetite with nobody's name against it. That is the finding an auditor opens
   the register looking for, so it is the finding the page refuses to whisper. */
.acceptance-wanted { border-color: var(--error); border-left-width: 3px; }

.tag-accepted { border-color: var(--accent); color: var(--accent); }
.tag-warn { border-color: var(--error); color: var(--error); }

.justification {
  margin: var(--sp-2) 0 0;
  padding: 0.1rem 0 0.1rem var(--sp-4);
  border-left: 2px solid var(--line);
  color: var(--fg);
  font-size: 0.9rem;
}

.narrow-page { max-width: 44rem; }

.risk-form input[type="date"] {
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  font: inherit;
}

/* ------------------------------------------------------ review (phase 8) */

.review-overdue { border-color: var(--error); border-left-width: 3px; }

/* -------------------------------------------- reporting (phase 9) */

.head-actions { display: flex; align-items: center; gap: var(--sp-4); flex-shrink: 0; }

.report-section { margin: 0 0 var(--sp-8); }
.report-section h3 { font-size: 0.9rem; margin: var(--sp-4) 0 var(--sp-1); }
.report-section h4 { font-size: 0.85rem; color: var(--muted); margin: var(--sp-4) 0 var(--sp-1); }

/* Four numbers, not eleven. A dashboard whose top row is a wall of tiles has
   decided nothing about what matters, and this row is meant to answer "where are
   we" before the reader scrolls. */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}

.tile {
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
  padding: var(--sp-4) var(--sp-5);
}

.tile-number {
  display: block;
  font-size: var(--text-2xl);
  font-weight: 650;
  letter-spacing: var(--track-tighter);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.tile-label { display: block; margin-top: 0.15rem; font-size: var(--text-base); color: var(--muted); }
.tile-label a { color: inherit; }

/* Loud only where something is actually owed. A tile showing zero overdue is good
   news and must not be painted like a warning, or the colour stops meaning
   anything on the day it does. */
.tile-warn { border-color: var(--band-high); }
.tile-over { border-color: var(--error); }
.tile-over .tile-number { color: var(--error); }

.report-table { width: 100%; border-collapse: collapse; margin-top: var(--sp-2); }
.report-table th,
.report-table td {
  padding: var(--sp-2) var(--sp-2);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.report-table th {
  font-size: var(--text-xs);
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}
.report-table td.numeric,
.report-table th.numeric { text-align: right; font-variant-numeric: tabular-nums; }

.trend-chart { width: 100%; height: auto; overflow: visible; }
.trend-segment.band-very_low { fill: var(--band-very-low); }
.trend-segment.band-low { fill: var(--band-low); }
.trend-segment.band-medium { fill: var(--band-medium); }
.trend-segment.band-high { fill: var(--band-high); }
.trend-segment.band-critical { fill: var(--band-critical); }
.trend-segment { stroke: var(--surface); stroke-width: 0.5; }

.under { color: var(--accent); }

.pack-head { margin-bottom: var(--sp-6); }
.pack-stamp { color: var(--muted); font-size: 0.9rem; line-height: 1.5; margin: var(--sp-2) 0; }
.methodology .report-section p { max-width: 44rem; }
.worked-example { border-top: 1px solid var(--line); padding-top: var(--sp-4); }

/* The whole of the PDF story. The browser already renders this page and already
   prints to PDF, so the review pack is a stylesheet rather than a rendering
   dependency with a font stack and a memory profile. */
@media print {
  /* The fourth assignment block. A reader on the dark theme who hits print would
     otherwise get pale text on paper the printer leaves white, and band fills
     dark enough to swallow the number written on them. Paper is light, so the
     print stylesheet is unconditionally light — no media query about it. */
  :root, :root[data-theme="dark"] {
    color-scheme: light;
    --bg: #fff; --surface: #fff; --field: #fff;
    --fg: #000; --muted: #444;
    --line: #ccc; --line-strong: #999;
    --accent: var(--l-accent); --accent-bg: var(--l-accent-bg);
    --accent-wash: var(--l-accent-wash); --on-accent: #fff;
    --error: var(--l-error); --error-bg: var(--l-error-bg); --on-error: #fff;
    --shadow: transparent;
    --band-very-low: var(--l-band-very-low); --band-low: var(--l-band-low);
    --band-medium: var(--l-band-medium); --band-high: var(--l-band-high);
    --band-critical: var(--l-band-critical); --band-none: var(--l-band-none);
    --band-ink: #000;
    --level-1: var(--l-level-1); --level-2: var(--l-level-2); --level-3: var(--l-level-3);
    --level-4: var(--l-level-4); --level-5: var(--l-level-5);
    --header: #fff; --header-fg: #000; --header-line: #ccc; --header-muted: #444;
    --panel-line: #ccc; --row-hover: transparent;
    --elev-1: none; --elev-2: none;
    --chart-band-opacity: var(--l-chart-band-opacity);
  }

  .site-header,
  .no-print,
  .head-actions { display: none; }

  /* Shadows print as grey smudges, and every panel edge has to be an actual line
     on paper rather than a suggestion of one. */
  .panel, .tile, .filters, .message { box-shadow: none; border-color: var(--line); }

  body { background: #fff; font-size: 11pt; }
  .page { max-width: none; }
  main { padding: 0; }

  /* A table split across a page break is a table an auditor has to reassemble. */
  .report-section { break-inside: avoid; page-break-inside: avoid; }
  .report-table { break-inside: avoid; page-break-inside: avoid; }
  h2, h3 { break-after: avoid; page-break-after: avoid; }

  /* Band fills are the only colour carrying meaning, and every band is named in
     text beside its swatch — so a black-and-white print loses nothing. */
  .band-pill, .trend-segment { print-color-adjust: exact; -webkit-print-color-adjust: exact; }

  a { text-decoration: none; color: inherit; }
}

/* -------------------------------------------- settings (phase 10) */

.messages { list-style: none; margin: 0 0 var(--sp-5); padding: 0; }
.message {
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--panel-line);
  border-left-width: 3px;
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--elev-1);
  margin-bottom: var(--sp-2);
}
.message-success { border-left-color: var(--accent); }
.message-info { border-left-color: var(--muted); }
.message-error { border-left-color: var(--error); }

.weight-row { margin-bottom: var(--sp-4); }
.weight-row label { display: block; font-weight: 600; font-size: 0.9rem; }
.weight-row p { margin: 0.2rem 0 0; }

.weight-input { display: flex; align-items: center; gap: var(--sp-2); margin: var(--sp-1) 0; }
.weight-input input {
  width: 5rem;
  padding: var(--sp-2) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.weight-input .suffix { color: var(--muted); font-size: 0.9rem; }

.fixed-level {
  padding: var(--sp-2) var(--sp-3);
  background: var(--band-none);
  border-radius: 6px;
  margin-bottom: var(--sp-4);
}

.form-errors { border-color: var(--error); border-left-width: 3px; }

/* The preview is allowed to be loud only when something crosses a line somebody has
   to answer for. A change that moves scores around inside their bands is ordinary
   and is styled as such. */
.preview { border-color: var(--muted); }
.preview-warns { border-color: var(--error); border-left-width: 3px; }

/* ------------------------------------------ data rights (phase 11) */

.deletion-pending { border-color: var(--error); border-left-width: 3px; }
.deletion-warning { border-color: var(--error); border-left-width: 3px; }

/* The only destructive button in the product, and styled so it cannot be mistaken
   for the one next to it. */
button.danger {
  border-color: var(--error);
  background: var(--error-bg);
  color: var(--on-error);
}

#confirm {
  display: block;
  width: 100%;
  max-width: 20rem;
  margin: var(--sp-2) 0 var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
}

details summary { cursor: pointer; }

.site-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
  padding: var(--sp-6);
  margin-top: var(--sp-12);
  border-top: 1px solid var(--line);
  font-size: var(--text-base);
}
.site-footer a { color: var(--muted); }
.site-footer button.link { font-size: inherit; }

/* The analytics question. Fixed to the bottom so it never pushes the register
   around, and small enough to ignore: not answering means no. */
.consent {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  left: 1rem;
  z-index: 50;
  max-width: 34rem;
  margin-left: auto;
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  box-shadow: var(--elev-1);
  font-size: var(--text-base);
}
.consent[hidden] { display: none; }
.consent p { margin: 0; }
.consent-actions { display: flex; gap: var(--sp-2); align-items: center; margin-top: var(--sp-3); }

/* ------------------------------------ assessment scale (phase 14) */

/* The reference table is wide by nature — five definitions across — so it scrolls
   inside its own box rather than pushing the page sideways. */
.scale-wrap { overflow-x: auto; }

.scale-table { min-width: 46rem; }
.scale-table td { vertical-align: top; }
.scale-dimension-head,
.scale-dimension {
  white-space: nowrap;
  font-weight: 600;
  text-align: left;
}
.scale-definition { font-size: 0.85rem; line-height: 1.35; }

/* Folded away under the grid on the raise form. Closed by default so it does not
   crowd the thing it is explaining; open with no JavaScript involved. */
.scale-help { margin-top: var(--sp-4); }
.scale-help > summary { font-size: 0.9rem; color: var(--muted); }
.scale-help[open] > summary { margin-bottom: var(--sp-2); }

.scale-edit-row { align-items: start; gap: var(--sp-3); }
.scale-edit-level {
  width: 1.5rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  padding-top: var(--sp-2);
}
.scale-edit-fields { flex: 1; display: flex; flex-direction: column; gap: var(--sp-2); }
.scale-edit-fields input {
  width: 100%;
  padding: var(--sp-2) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
}

/* --------------------------------- decisions made elsewhere (phase 15) */

.decision-elsewhere { border-left: 3px solid var(--accent); }
.record-links { margin: var(--sp-2) 0 0; padding: 0; list-style: none; }
.record-links li { padding: var(--sp-1) 0; border-top: 1px solid var(--line); }
.record-kind {
  font-size: 0.75rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.record-missing { color: var(--error); }

/* --------------------------------------------------- team (phase 16) */

/* Not `button.danger`: that one is reserved for deleting a company, and the
   difference is the whole point of revoking rather than removing. This reads as
   an undoable action in a warning colour, which is what it is. */
button.link-warn { color: var(--error); }

.team-table { margin-bottom: var(--sp-6); }
.team-table th:first-child { width: auto; }
.team-action { text-align: right; }
.team-action form { margin: 0; }

/* Dimmed rather than struck through. These rows are still the answer to "who
   owned this in March", so they have to stay readable — they are just not
   describing anybody who can sign in today. */
.team-table tr.is-revoked td:first-child { color: var(--muted); }
.team-past { margin-top: var(--sp-8); }

/* ------------------------------------------------- agents (phase 16) */

/* A draft is not a failure, so it is not in the error colour. It is work waiting
   on somebody — the same weight as "due soon", not the same weight as "overdue". */
.tag-draft { border-color: var(--accent); color: var(--accent); }
.draft-count { color: var(--accent); }

/* The key, shown exactly once. Wide, selectable, and unmistakably a value to copy
   rather than a sentence to read. */
.token {
  overflow-x: auto;
  margin: var(--sp-2) 0;
  padding: var(--sp-3) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: var(--text-base);
  user-select: all;
}

/* Three states, three left edges. The colour carries the same meaning it does in
   the row flags, so a reader who has learned the register has learned this too. */
.authorship { border-left: 3px solid var(--line); }
.authorship-draft { border-left-color: var(--accent); }
.authorship-changed { border-left-color: var(--error); }
.authorship-reviewed { border-left-color: var(--line-strong); }
.authorship h2 { font-size: var(--text-base); }

.actor-agent { font-style: italic; }
.plain { margin: 0; padding-left: var(--sp-4); }
.plain li { margin: 0.2rem 0; }

/* A confirm sitting inside a table cell beside the flag it answers. */
.inline-confirm { display: inline; margin: 0; }

/* -------------------------------------------------------------- home page */

.page.home { max-width: 70rem; }

.home-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 19rem;
  gap: var(--sp-6);
  align-items: start;
}
.home-main { display: grid; gap: var(--sp-6); }
.home-main > * { margin: 0; }
.home-main .tiles { margin: 0; }

/* Risks and controls on rows of their own, each named by a quiet label above it
   rather than a heading that would compete with the numbers. */
.home-tiles { display: grid; gap: var(--sp-2); }
.home-tiles .tiles + .tiles-label { margin-top: var(--sp-3); }
.tiles-label {
  margin: 0;
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

/* A tile on the home page is a way into the rows it counts, so the whole tile
   is the link rather than a label inside it. */
.tile-link { color: var(--fg); text-decoration: none; transition: border-color 120ms, box-shadow 120ms; }
.tile-link:hover { border-color: var(--line-strong); box-shadow: var(--elev-2); }
.tile-link .tile-label { margin-top: var(--sp-1); }

.owed { margin: var(--sp-3) 0 0; padding: 0; list-style: none; }
.owed li + li { border-top: 1px solid var(--line); }
.owed a {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-2);
  margin: 0 calc(-1 * var(--sp-2));
  border-radius: var(--r-sm);
  color: var(--fg);
  text-decoration: none;
}
.owed a:hover { background: var(--row-hover); }
.owed-count {
  min-width: 2rem;
  color: var(--error);
  font-size: var(--text-lg);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.owed-label { display: flex; flex-direction: column; font-size: var(--text-base); font-weight: 550; }

/* The library's suggestions on the home page: what each one is, and its one action. */
.typical { margin: var(--sp-3) 0 0; padding: 0; list-style: none; }
.typical li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-3) 0;
}
.typical li + li { border-top: 1px solid var(--line); }
.typical-what { display: flex; flex: 1 1 20rem; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.typical form { margin: 0; }

.recent { margin: var(--sp-3) 0 0; padding: 0; list-style: none; }
.recent li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--sp-1) var(--sp-4);
  padding: var(--sp-3) 0;
  font-size: var(--text-base);
}
.recent li + li { border-top: 1px solid var(--line); }
.recent li:last-child { padding-bottom: 0; }
.recent-what { flex: 1 1 18rem; min-width: 0; }
.recent-meta { color: var(--muted); font-size: var(--text-sm); white-space: nowrap; }

.home-side { display: grid; gap: var(--sp-6); }
.home-side .panel { margin: 0; }
.side-links ul { margin: var(--sp-2) 0 0; padding: 0; list-style: none; }
.side-links li { padding: var(--sp-2) 0; }
.side-links li + li { border-top: 1px solid var(--line); }
.side-links li:last-child { padding-bottom: 0; }
.side-links a { font-size: var(--text-base); font-weight: 600; text-decoration: none; }
.side-links a:hover { text-decoration: underline; }
.side-links p { margin: 0; color: var(--muted); font-size: var(--text-sm); }

.callout-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3); }

@media (max-width: 900px) {
  .home-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------- first visit (_welcome) */

.page.welcome { max-width: 68rem; }

.welcome-hero { max-width: 44rem; margin: var(--sp-4) 0 var(--sp-8); }
.welcome-hero h1 {
  margin: 0;
  font-size: 2.25rem;
  font-weight: 680;
  letter-spacing: -0.03em;
  line-height: 1.1;
  text-wrap: balance;
}
.welcome-hero p { margin: var(--sp-3) 0 0; color: var(--muted); font-size: var(--text-lg); }

.ways {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: var(--sp-5);
}

/* One target per box: the button's hit area is stretched over the whole box. */
.way {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--sp-8);
  border: 1px solid var(--panel-line);
  border-radius: 20px;
  background: var(--surface);
  box-shadow: var(--elev-1);
  transition: transform 160ms ease, box-shadow 160ms ease;
}
.way:hover { transform: translateY(-2px); box-shadow: var(--elev-2); }
.way .button::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.way h2 { margin: 0; font-size: var(--text-xl); font-weight: 660; letter-spacing: var(--track-tighter); }
.way > p { max-width: 30rem; margin: var(--sp-2) 0 0; color: var(--muted); font-size: var(--text-md); }
.way-cta { display: flex; align-items: center; gap: var(--sp-4); margin-top: auto; padding-top: var(--sp-6); }
.way-cta .button { min-height: 2.75rem; padding: var(--sp-2) var(--sp-5); font-size: var(--text-md); }
.way-note { color: var(--muted); font-size: var(--text-sm); }

.way-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.way-pill {
  padding: 0.125rem var(--sp-3);
  border-radius: var(--r-pill);
  background: var(--accent-wash);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 650;
}

/* The recommended way is the loud one: the forest fill, the only one on the page. */
.way-primary { border-color: var(--accent-bg); background: var(--accent-bg); color: var(--on-accent); }
.way-primary > p, .way-primary .way-note { color: var(--on-accent); opacity: 0.82; }
.way-primary .way-pill { background: color-mix(in srgb, var(--on-accent) 16%, transparent); color: var(--on-accent); }
.way-primary .button { border-color: var(--on-accent); background: var(--on-accent); color: var(--accent-bg); }

/* What the review will look like: two suggestions kept, one ruled out. Dealt in
   once on arrival — the page's one piece of motion. */
.preview { display: grid; gap: var(--sp-2); margin: var(--sp-6) 0 0; }
.preview-card {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  font-size: var(--text-base);
  font-weight: 560;
  animation: deal 520ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.preview-card:nth-child(2) { margin-left: var(--sp-4); animation-delay: 120ms; }
.preview-card:nth-child(3) { margin-left: var(--sp-8); animation-delay: 240ms; }
.preview-title { flex: 1; min-width: 0; }
.preview-tag { color: var(--muted); font-size: var(--text-xs); font-weight: 600; white-space: nowrap; }
.mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--on-accent);
}
.preview-card.is-out .mark { background: transparent; color: var(--error); box-shadow: inset 0 0 0 1.5px var(--error); }
.preview-card.is-out .preview-title { color: var(--muted); text-decoration: line-through; }
@keyframes deal { from { opacity: 0; transform: translateY(10px) rotate(-1deg); } }

/* The scratch path's picture is the product's own 5x5 grid, one cell picked. */
.grid-preview { display: flex; align-items: center; gap: var(--sp-5); margin-top: var(--sp-6); }
.mini-matrix { display: grid; grid-template-columns: repeat(5, 1.75rem); gap: 3px; }
.mini-matrix span { height: 1.75rem; border-radius: 5px; }
.mini-matrix .is-picked { box-shadow: inset 0 0 0 2px var(--fg), inset 0 0 0 4px var(--surface); }
.grid-readout { display: grid; gap: var(--sp-1); }
.grid-readout strong { font-size: var(--text-2xl); font-weight: 680; letter-spacing: var(--track-tighter); line-height: 1; }
.grid-readout .band-pill { justify-self: start; }

.welcome-more {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  margin-top: var(--sp-10);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}
.welcome-more h3 { margin: 0; font-size: var(--text-base); font-weight: 620; }
.welcome-more p { margin: var(--sp-1) 0 0; color: var(--muted); font-size: var(--text-sm); }

@media (max-width: 860px) {
  .ways, .welcome-more { grid-template-columns: minmax(0, 1fr); }
  .way { padding: var(--sp-6); }
  .welcome-hero h1 { font-size: 1.75rem; }
  .preview-card:nth-child(n) { margin-left: 0; }
  .preview-tag { display: none; }
  .way-cta { flex-direction: column; align-items: stretch; }
}

@media (prefers-reduced-motion: reduce) {
  .preview-card { animation: none; }
  .way, .way:hover { transition: none; transform: none; }
}

/* ------------------------------------------------- how it works (explainer) */

/* The landing page's way to the method: big enough to find above the fold, quiet
   enough not to compete with the two ways in. */
.welcome-hero a.button.hero-how {
  margin-top: var(--sp-6);
  min-height: 3.25rem;
  padding: var(--sp-3) var(--sp-6);
  border: 2px solid var(--accent-bg);
  color: var(--accent);
  font-size: var(--text-lg);
  font-weight: 650;
}
.welcome-hero a.button.hero-how:hover { background: var(--accent-wash); }

.page.explainer { max-width: 60rem; }

.explainer-hero { max-width: 46rem; margin: var(--sp-4) 0 var(--sp-10); }
.explainer-hero h1 {
  margin: 0;
  font-size: 2.25rem;
  font-weight: 680;
  letter-spacing: -0.03em;
  line-height: 1.1;
}
.explainer-hero > p { margin: var(--sp-3) 0 0; }
.explainer-hero > p:not(.explainer-kicker, .muted) { color: var(--muted); font-size: var(--text-lg); }

.explainer-kicker {
  margin: 0 0 var(--sp-2);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 650;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.explainer-toc { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: var(--sp-6) 0 var(--sp-3); }

/* Heading in a narrow column beside the text: a long read that can be skimmed by
   its headings alone. */
.explainer-section {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: var(--sp-4) var(--sp-8);
  padding: var(--sp-8) 0;
  border-top: 1px solid var(--line);
  scroll-margin-top: var(--sp-4);
}
.explainer-head h2 { margin: 0; font-size: var(--text-lg); font-weight: 650; line-height: 1.3; }
.explainer-body { max-width: 40rem; font-size: var(--text-md); line-height: 1.6; }
.explainer-body > :first-child { margin-top: 0; }
.explainer-body > :last-child { margin-bottom: 0; }
.explainer-body ul { padding-left: var(--sp-5); }
.explainer-body li + li { margin-top: var(--sp-2); }

/* The services come first and are the loud section: the forest fill, as the
   landing page's recommended way. */
.explainer-lead {
  grid-template-columns: minmax(0, 1fr);
  padding: var(--sp-10);
  border: 0;
  border-radius: 20px;
  background: var(--accent-bg);
  color: var(--on-accent);
}
.explainer-lead .explainer-kicker { color: var(--on-accent); opacity: 0.82; }
.explainer-lead .explainer-head h2 { max-width: 34rem; font-size: var(--text-xl); letter-spacing: var(--track-tighter); line-height: 1.2; }
.explainer-lead .explainer-body { max-width: none; }
.explainer-lead .explainer-body > p { max-width: 44rem; }
.explainer-lead a { color: var(--on-accent); }
.explainer-lead + .explainer-section { border-top: 0; margin-top: var(--sp-4); }

.explainer-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4);
  margin: var(--sp-6) 0;
}
.explainer-cards article {
  padding: var(--sp-5) var(--sp-6);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--elev-1);
}
.explainer-cards h3 { margin: 0 0 var(--sp-2); font-size: var(--text-md); font-weight: 650; }
.explainer-cards p { margin: 0; color: var(--muted); font-size: var(--text-base); line-height: 1.55; }
.explainer-note { font-weight: 600; }

.explainer-links { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); margin-top: var(--sp-5); font-size: var(--text-base); font-weight: 600; }

.explainer-figure {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-5) var(--sp-8);
  margin: var(--sp-6) 0;
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
}
.mini-matrix .is-was { box-shadow: inset 0 0 0 2px var(--surface); outline: 2px dashed var(--fg); outline-offset: -2px; opacity: 0.6; }
.explainer-controls { display: grid; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; font-size: var(--text-base); }
.explainer-controls li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0; }
.explainer-figure .grid-readout { grid-template-columns: auto auto; align-items: center; gap: var(--sp-2) var(--sp-3); }

.explainer-terms { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4) var(--sp-6); margin: 0; }
.explainer-terms dt { font-weight: 650; font-size: var(--text-base); }
.explainer-terms dd { margin: var(--sp-1) 0 0; color: var(--muted); font-size: var(--text-base); line-height: 1.5; }

.explainer-cta { margin-top: var(--sp-4); padding: var(--sp-8) 0 0; border-top: 1px solid var(--line); }
.explainer-cta h2 { margin: 0; font-size: var(--text-xl); }
.explainer-cta p { margin: var(--sp-2) 0 0; color: var(--muted); }

@media (max-width: 860px) {
  .explainer-hero h1 { font-size: 1.75rem; }
  .explainer-section, .explainer-cards, .explainer-terms { grid-template-columns: minmax(0, 1fr); }
  .explainer-lead { padding: var(--sp-6); }
  .hero-how { width: 100%; }
}

/* ------------------------------------------------- register views (Phase 19) */

/* The register's two tabs. A segmented control rather than underlined tabs: the
   two views are peers, and the filled pill is the same "you are here" the site
   header already uses. */
.view-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  padding: var(--sp-1);
  margin: 0 0 var(--sp-6);
  border-radius: var(--r-md);
  background: var(--header);
}
.view-tabs a {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 2.5rem;
  padding: 0 var(--sp-4);
  border-radius: var(--r-sm);
  color: var(--header-muted);
  font-size: var(--text-base);
  font-weight: 560;
  text-decoration: none;
}
.view-tabs a:hover { color: var(--fg); background: var(--row-hover); }
.view-tabs a.is-current { color: var(--fg); background: var(--surface); box-shadow: var(--elev-1); }
.view-tabs-count {
  min-width: 1.25rem;
  padding: 0 var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--error-bg);
  color: var(--on-error);
  font-size: var(--text-xs);
  font-weight: 700;
  line-height: 1.25rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.page-queue { max-width: 76rem; }

.queue-health {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4) var(--sp-8);
  margin-bottom: var(--sp-6);
}
.queue-health-main { flex: 2 1 26rem; min-width: 0; display: grid; gap: var(--sp-2); }
.queue-health-main p { margin: 0; }
.queue-health-figure { font-size: var(--text-md); }
.queue-health-figure strong { font-size: var(--text-2xl); font-weight: 680; letter-spacing: var(--track-tighter); margin-right: var(--sp-1); }
.queue-health-side { flex: 1 1 14rem; display: grid; gap: var(--sp-3); justify-items: start; }
.queue-health-side p { margin: 0; }

/* The bar is a <progress>, which every engine draws differently until told not
   to. Filled = good standing, the track = what is owed. */
.queue-health-bar {
  appearance: none;
  width: 100%;
  height: 0.625rem;
  border: 0;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--band-high);
}
.queue-health-bar::-webkit-progress-bar { background: var(--band-high); border-radius: var(--r-pill); }
.queue-health-bar::-webkit-progress-value { background: var(--accent-bg); border-radius: var(--r-pill); }
.queue-health-bar::-moz-progress-bar { background: var(--accent-bg); border-radius: var(--r-pill); }

.queue-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 19rem;
  gap: var(--sp-6);
  align-items: start;
}
.queue-main { display: grid; gap: var(--sp-8); }
.queue-side { display: grid; gap: var(--sp-4); }
.queue-side .panel { margin: 0; }
.queue-side h2 { margin-bottom: var(--sp-3); }

.queue-section-head { margin-bottom: var(--sp-3); }
.queue-section-head h2 { margin: 0; font-size: var(--text-lg); }
.queue-section-head p { margin: var(--sp-1) 0 0; }
.queue-section-count { color: var(--error); font-variant-numeric: tabular-nums; margin-left: var(--sp-1); }

.queue-list { padding: 0; margin: 0; overflow: hidden; }

.queue-card { display: grid; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); }
.queue-card + .queue-card { border-top: 1px solid var(--line); }
.queue-card-head { display: flex; align-items: flex-start; gap: var(--sp-4); }
.queue-card-title { flex: 1 1 auto; min-width: 0; }
.queue-card-title a { color: var(--fg); font-weight: 620; text-decoration: none; line-height: 1.35; }
.queue-card-title a:hover { text-decoration: underline; }
.queue-card-title p { margin: var(--sp-1) 0 0; }
.queue-card-score { display: grid; justify-items: end; gap: var(--sp-1); flex-shrink: 0; }
.queue-card-tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0; }

.queue-quote {
  margin: 0;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--bg);
}
.queue-quote p { margin: 0; font-size: var(--text-base); }
.queue-quote footer { margin-top: var(--sp-1); }

.queue-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
.queue-actions form { margin: 0; }
.queue-card > p { margin: 0; }
.queue-reassign { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.queue-reassign label { margin: 0; font-weight: 400; }
.queue-reassign select {
  min-height: 2rem;
  padding: var(--sp-1) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--fg);
  font: inherit;
  font-size: var(--text-base);
}
form.queue-reassign > :is(select, button) + button { margin-top: 0; }

/* After htmx swaps a card for what happened to it: quieter than a card, so the
   eye moves on to the next one. */
.queue-card-done {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-4);
  background: var(--accent-wash);
}
.queue-card-done p { margin: 0; font-size: var(--text-base); }
.queue-card-done form { margin: 0; }

.queue-draft {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
}
.queue-draft + .queue-draft { border-top: 1px solid var(--line); }
.queue-draft input[type="checkbox"] { margin-top: 0.2rem; accent-color: var(--accent-bg); }
.queue-draft-text { flex: 1 1 auto; min-width: 0; }
.queue-draft-text label { margin: 0; font-weight: 600; font-size: var(--text-base); line-height: 1.35; }
.queue-draft-text p { margin: var(--sp-1) 0 0; }
.queue-drafts .queue-actions { padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--line); background: var(--bg); }

.queue-clear h2 { font-size: var(--text-lg); }

.queue-snoozed summary { cursor: pointer; color: var(--muted); font-size: var(--text-base); margin-bottom: var(--sp-3); }

.queue-upcoming, .queue-moves { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-3); }
.queue-upcoming li { display: flex; gap: var(--sp-3); align-items: flex-start; }
.queue-upcoming time {
  flex: none;
  width: 2.75rem;
  padding: var(--sp-1) 0;
  border-radius: var(--r-sm);
  background: var(--bg);
  text-align: center;
  line-height: 1.1;
}
.queue-upcoming time span { display: block; color: var(--muted); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--track-caps); }
.queue-upcoming time strong { font-size: var(--text-lg); }
.queue-upcoming a, .queue-moves a { display: block; color: var(--fg); font-size: var(--text-sm); line-height: 1.35; margin-bottom: var(--sp-1); }
.queue-move { display: inline-flex; align-items: center; gap: var(--sp-1); }

@media (max-width: 900px) {
  .queue-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .queue-card-head { flex-direction: column; }
  .queue-card-score { justify-items: start; }
}

/* --------------------------------------------- review session (Phase 19) */

.page-session { max-width: 70rem; }
.session-bar { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--sp-2) var(--sp-4); margin-bottom: var(--sp-4); }
.session-bar p { margin: 0; }

.session-grid { display: grid; grid-template-columns: minmax(0, 1fr) 17rem; gap: var(--sp-6); align-items: start; }
.session-card { display: grid; gap: var(--sp-4); margin: 0; padding: var(--sp-6) var(--sp-8); }
.session-card > p, .session-card h1 { margin: 0; }
.session-card h1 { font-size: var(--text-xl); line-height: 1.3; letter-spacing: var(--track-tight); }

.session-scores { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-8); margin: 0; }
.session-scores dt { color: var(--muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--track-caps); font-weight: 600; }
.session-scores dd { margin: var(--sp-1) 0 0; font-size: var(--text-base); }

.session-form { display: grid; gap: var(--sp-2); border-top: 1px solid var(--line); padding-top: var(--sp-5); }
.session-form > label { margin-top: var(--sp-3); }
.session-form textarea, .exception-review-form textarea {
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--fg);
  font: inherit;
}
.session-form .actions { margin-top: var(--sp-4); }
.session-form .actions button.link { font-size: var(--text-base); }

/* Three big answers rather than three radio dots: this is the one question the
   page asks, and it should look like a question. The input stays in the tab order,
   moved off-screen; the label is the target and :checked paints it. */
.session-outcomes { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: var(--sp-2); margin: 0; padding: 0; border: 0; }
.session-outcomes legend { margin-bottom: var(--sp-3); font-size: var(--text-lg); font-weight: 620; }
.session-outcomes input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.session-outcome {
  display: flex;
  align-items: center;
  min-height: 3.5rem;
  margin: 0;
  padding: var(--sp-3) var(--sp-4);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--field);
  font-weight: 600;
  cursor: pointer;
}
.session-outcome:hover { border-color: var(--accent); }
.session-outcomes input:checked + .session-outcome { border-color: var(--accent); background: var(--accent-wash); box-shadow: 0 0 0 1px var(--accent); }
.session-outcomes input:focus-visible + .session-outcome { outline: 2px solid var(--accent); outline-offset: 2px; }

.session-changes { display: grid; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); border: 1px solid var(--line); border-radius: var(--r-md); }
.session-changes h2, .session-changes p { margin: 0; }
@supports selector(:has(*)) {
  .session-changes { display: none; }
  .session-form:has(input[name="outcome"][value="rescored"]:checked) .session-changes { display: grid; }
}
.session-levels { display: grid; gap: var(--sp-2); }

/* The risks a control's rating holds down, shown before the reader rates it. */
.session-risks h2 { margin: 0 0 var(--sp-2); color: var(--muted); font-weight: 600; }
.session-risk-list { display: grid; gap: var(--sp-1); margin: 0; padding: 0; list-style: none; }
.session-risk-list li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); }
.session-risk-list li > span:first-child { flex: 1 1 14rem; min-width: 0; }
.session-level { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2) var(--sp-4); }
.session-level label { margin: 0; font-weight: 550; }
.session-level select {
  min-height: 2rem;
  padding: var(--sp-1) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--fg);
  font: inherit;
  font-size: var(--text-base);
}
.session-grid-details summary { cursor: pointer; font-size: var(--text-base); font-weight: 600; margin-bottom: var(--sp-3); }

.session-side h2 { font-size: var(--text-base); text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--muted); }
.session-next { margin: 0 0 var(--sp-3); padding-left: var(--sp-5); display: grid; gap: var(--sp-2); font-size: var(--text-sm); }

.session-done { display: grid; gap: var(--sp-3); justify-items: start; }
.session-done h1, .session-done p { margin: 0; }

@media (max-width: 900px) {
  .session-grid { grid-template-columns: minmax(0, 1fr); }
  .session-card { padding: var(--sp-5); }
}

/* --------------------------------------------------- All risks table (Phase 19) */

.page-table { max-width: 94rem; }

.table-layout {
  display: grid;
  grid-template-columns: 13rem minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: start;
}

.table-views h2 {
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-3);
  color: var(--muted);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}
.table-views ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 2px; }
.table-views a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--fg);
  font-size: var(--text-base);
  text-decoration: none;
}
.table-views a:hover { background: var(--row-hover); }
.table-views a.is-current { background: var(--accent-wash); color: var(--accent); font-weight: 600; }

.table-views h2.table-views-own { margin-top: var(--sp-6); }
.table-view-own { display: flex; align-items: center; gap: var(--sp-1); }
.table-view-own a { flex: 1 1 auto; min-width: 0; }
.table-view-own form { margin: 0; }
.table-view-own button.link { width: 1.75rem; height: 1.75rem; border-radius: 50%; text-decoration: none; font-size: var(--text-md); }
.table-view-own button.link:hover { background: var(--row-hover); color: var(--fg); }
.table-view-save { display: grid; gap: var(--sp-2); margin-top: var(--sp-6); padding: 0 var(--sp-3); }
.table-view-save label { margin: 0; font-size: var(--text-sm); font-weight: 600; }
.table-view-save input[type="text"] { min-height: 2.25rem; padding: var(--sp-1) var(--sp-2); font-size: var(--text-base); }
form.table-view-save > input + button { margin-top: 0; justify-self: start; }

.table-main { min-width: 0; display: grid; gap: var(--sp-4); }
.table-main > * { margin: 0; }

.table-toolbar { gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); }
.table-toolbar-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); }
.table-search { flex: 1 1 16rem; min-width: 0; }
.table-inline-field { display: flex; align-items: center; gap: var(--sp-2); margin: 0; white-space: nowrap; }
.table-toolbar-row > button { margin-top: 0; }
.table-filters summary { cursor: pointer; font-size: var(--text-base); font-weight: 600; color: var(--accent); }
.table-filters-body { display: grid; gap: var(--sp-4); padding-top: var(--sp-4); }

.table-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.table-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-1) var(--sp-1) var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  font-size: var(--text-sm);
}
.table-chip a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  color: var(--muted);
  text-decoration: none;
}
.table-chip a:hover { background: var(--row-hover); color: var(--fg); }

.table-bulk { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
.table-bulk select, .owner-form select {
  min-height: 2rem;
  max-width: 11.5rem;
  padding: var(--sp-1) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--fg);
  font: inherit;
  font-size: var(--text-sm);
}
/* form. and :is(…) to match the specificity of the global "field then submit" margin rule, which would otherwise win. */
form.table-bulk > :is(select, span, button) + button { margin-top: 0; }
.table-bulk > span:last-child { margin-left: auto; }

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--panel-line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--elev-1);
  padding: var(--sp-2) var(--sp-3);
}
.risk-table { min-width: 64rem; }
.control-table { min-width: 56rem; }
.exception-list-table { min-width: 60rem; }
.exception-list-table .exception-row-sub { display: block; }
@media (min-width: 641px) {
  .exception-list-table .col-trend { white-space: nowrap; }
}
@media (max-width: 640px) {
  /* On the card the review date says it; the period would squeeze the title. */
  .exception-list-table .col-scores .exception-row-sub { display: none; }
}
.control-table .col-trend { white-space: nowrap; }
.card-table th:first-child { width: 2rem; }
.card-table td { vertical-align: middle; }
.card-table .col-pick input { accent-color: var(--accent-bg); }
.card-table .col-title { width: 28%; min-width: 15rem; }
.card-table .col-title a { display: block; color: var(--fg); font-weight: 600; line-height: 1.35; text-decoration: none; }
.card-table .col-title a:hover { text-decoration: underline; }
.card-table .col-scores, .card-table .col-review { white-space: nowrap; }
.card-table .col-status .tag { margin: 0 var(--sp-1) var(--sp-1) 0; }
.card-table .group-row th {
  padding: var(--sp-4) var(--sp-2) var(--sp-2);
  border-bottom: 1px solid var(--line);
  font-size: var(--text-base);
  font-weight: 650;
  text-transform: none;
  letter-spacing: 0;
}
.card-table tbody tr.group-row:hover { background: none; }

.owner-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); margin: 0; }
form.owner-form > :is(select, button) + button { margin-top: 0; }
.htmx-enabled .owner-save { display: none; }

.trend { display: inline-flex; align-items: center; gap: var(--sp-2); white-space: nowrap; }
.trend svg { flex: none; overflow: visible; }
.trend-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }

/* On a phone each row of All risks, or All controls, becomes a card. Eight columns cannot share
   390px, and a table that scrolls sideways loses the risk's name while the
   reader is looking at its score. The markup stays a table, so nothing else
   changes: the head is kept for screen readers, the trend is dropped (it is
   unreadable at this size), and the two bare values get their column's name. */
@media (max-width: 640px) {
  .table-wrap { overflow-x: visible; padding: 0; }
  .card-table { min-width: 0; }
  .card-table thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .card-table, .card-table tbody { display: block; }
  .card-table tbody tr {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "pick title  scores"
      ".    owner  owner"
      ".    facts  facts"
      ".    status status";
    gap: var(--sp-1) var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
  }
  .card-table tbody tr + tr { border-top: 1px solid var(--line); }
  .card-table tbody tr.group-row { display: block; padding: 0; }
  .card-table tbody tr.group-row th { display: block; padding: var(--sp-4) var(--sp-4) var(--sp-2); }
  /* tbody, to match the specificity of the register's own cell padding. */
  .card-table tbody td { display: block; padding: 0; }
  .card-table .col-pick { grid-area: pick; padding-top: 0.2rem; }
  .card-table .col-title { grid-area: title; width: auto; min-width: 0; }
  .card-table .col-scores { grid-area: scores; }
  /* "Before → after" needs the column head to make sense; on a card the score
     that matters is the one now. */
  .risk-table .col-scores > :not(:last-child) { display: none; }
  .card-table .col-owner { grid-area: owner; }
  .card-table .col-owner select { max-width: 100%; }
  .card-table .col-trend { display: none; }
  .card-table .col-controls { grid-area: facts; justify-self: start; }
  .card-table .col-review { grid-area: facts; justify-self: end; }
  /* The cell names its own value, so each table says what its columns are. */
  .card-table [data-label]::before { content: attr(data-label) " "; color: var(--muted); }
  .card-table .col-status { grid-area: status; }
  /* :has rather than :empty, which still counts the template's whitespace. */
  .card-table .col-status:not(:has(*)) { display: none; }
}
.trend-appetite { stroke: var(--error); stroke-width: 1; stroke-dasharray: 3 3; opacity: 0.55; }
.trend-down { color: var(--accent); }
.trend-up { color: var(--error); }
.trend-steady, .trend-new { color: var(--muted); }

@media (max-width: 1023px) {
  .table-layout { grid-template-columns: minmax(0, 1fr); }
  .table-views ul { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
  .table-views a { padding: var(--sp-1) var(--sp-3); border: 1px solid var(--line); border-radius: var(--r-pill); font-size: var(--text-sm); }
}

/* ------------------------------------------------------- Overview (Phase 19) */

.overview-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--sp-3);
}
.overview-tiles .tile { display: grid; gap: var(--sp-2); align-content: start; }
.overview-tiles .tile-label { margin: 0; }
.overview-tiles .tile-number { font-size: var(--text-xl); }
/* The words around the numbers, so a tile reads as a sentence. Quieter and smaller
   than the figures, and never painted red with them. */
.tile-unit { color: var(--muted); font-size: var(--text-md); font-weight: 500; letter-spacing: 0; }
.tile-over .tile-number .tile-unit { color: var(--muted); }
.tile-title { color: var(--fg); font-weight: 600; line-height: 1.35; text-decoration: none; }
a.tile-title:hover { text-decoration: underline; }

/* Cell and plot links reload onto #map; the margin keeps the heading and the
   before/after tabs clear of the sticky header. */
.overview-map { scroll-margin-top: 5rem; }
.overview-map-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.overview-map-head h2 { margin: 0; }
.view-tabs-small { margin: 0; }
.view-tabs-small a { min-height: 2rem; font-size: var(--text-sm); }

.overview-map-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22rem;
  gap: var(--sp-6);
  align-items: start;
}

.heatmap-wrap { overflow-x: auto; }
.heatmap { width: 100%; min-width: 30rem; border-collapse: separate; border-spacing: 4px; table-layout: fixed; }
.heatmap td { padding: 0; }
.heatmap-axis {
  width: 8.5rem;
  padding: 0 var(--sp-2) 0 0;
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 550;
  text-align: right;
  line-height: 1.25;
}
.heatmap-axis-impact { width: auto; padding: var(--sp-2) 0 0; text-align: center; }

.heat-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1.35 / 1;
  min-height: 3.25rem;
  border-radius: var(--r-md);
  color: var(--band-ink);
  text-decoration: none;
}
a.heat-cell:hover { filter: brightness(0.96); }
.heat-score { position: absolute; top: var(--sp-1); left: var(--sp-2); font-size: var(--text-2xs); opacity: 0.75; }
.heat-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.125rem;
  height: 2.125rem;
  padding: 0 var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--fg);
  color: var(--bg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.heat-cell.is-above { outline: 2px dashed var(--error); outline-offset: -5px; }
.heat-cell.is-selected { box-shadow: 0 0 0 3px var(--accent); }
.heat-cell:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.heatmap-legend { margin: var(--sp-3) 0 0; }
.heat-key {
  display: inline-block;
  width: 1.25rem;
  height: 0.75rem;
  margin: 0 var(--sp-1) -0.1rem var(--sp-2);
  border-radius: 3px;
  outline: 2px dashed var(--error);
  outline-offset: -2px;
  background: var(--band-high);
}

.overview-cell { margin: 0; display: grid; gap: var(--sp-2); justify-items: start; }
.overview-cell > p, .overview-cell h3 { margin: 0; }
.overview-cell h3 { font-size: var(--text-lg); }
.overview-cell-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-3); width: 100%; }
.overview-cell-list li { display: grid; gap: var(--sp-1); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.overview-cell-list a { color: var(--fg); font-weight: 600; font-size: var(--text-base); line-height: 1.35; }
.overview-cell-scores { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); }

/* SVG fills for the band colours: the band-* classes paint backgrounds, which a
   rect does not have. */
.fill-very_low { fill: var(--band-very-low); }
.fill-low { fill: var(--band-low); }
.fill-medium { fill: var(--band-medium); }
.fill-high { fill: var(--band-high); }
.fill-critical { fill: var(--band-critical); }

.category-bars th { width: 14rem; color: var(--fg); font-size: var(--text-base); font-weight: 500; text-transform: none; letter-spacing: 0; vertical-align: middle; }
.category-bars td { vertical-align: middle; }
.category-bar-cell { width: auto; }
.category-bar { display: block; width: 100%; height: 0.875rem; }
.category-bars .numeric { width: 7rem; white-space: nowrap; }

@media (max-width: 960px) {
  .overview-map-body { grid-template-columns: minmax(0, 1fr); }
}
@media print {
  .heat-cell { aspect-ratio: auto; min-height: 2.5rem; }
  .heat-count { background: none; color: var(--fg); border: 1px solid var(--fg); }
}
.page-overview { max-width: 76rem; }

/* A suggested next step on a queue card: set apart from the card's facts, in the
   accent wash the product uses for "this is the way forward". */
.queue-remedy {
  display: grid;
  gap: var(--sp-2);
  justify-items: start;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--accent-wash);
}
.queue-remedy p { margin: 0; font-size: var(--text-base); line-height: 1.5; }

/* ---------------------------------------------- review rhythm (Phase 19) */

.rhythm-next { display: grid; gap: var(--sp-1); }
.rhythm-next p { margin: 0; }
.rhythm-next-date { font-size: var(--text-xl); font-weight: 650; letter-spacing: var(--track-tight); }
.rhythm-when { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-8); }
.rhythm-when select { min-height: var(--control-h); padding: var(--sp-1) var(--sp-2); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--field); color: var(--fg); font: inherit; }
.rhythm-when p { margin: var(--sp-1) 0 0; }
.rhythm-later { margin-top: var(--sp-10); padding-top: var(--sp-6); border-top: 1px solid var(--line); }

.queue-sitting { display: grid; gap: var(--sp-2); margin: 0 0 var(--sp-6); }
.queue-sitting-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); }
.queue-sitting-head h2 { margin: 0; flex: 1 1 18rem; font-size: var(--text-lg); }
.queue-sitting p { margin: 0; }
.queue-sitting details summary { cursor: pointer; font-size: var(--text-base); color: var(--accent); }
.queue-sitting ol { margin: var(--sp-2) 0 0; padding-left: var(--sp-5); display: grid; gap: var(--sp-1); font-size: var(--text-sm); }
.queue-sitting .before { padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm); background: var(--bg); }

.sittings-list { margin: var(--sp-2) 0 0; padding: 0; list-style: none; }
.sittings-list li { padding: var(--sp-3) 0; border-bottom: 1px solid var(--line); display: grid; gap: var(--sp-1); }
.sittings-list p { margin: 0; }
.queue-rhythm-hint { margin: 0 0 var(--sp-6); }
.session-record { display: grid; gap: var(--sp-2); width: 100%; margin-top: var(--sp-2); padding: var(--sp-4) var(--sp-5); border-radius: var(--r-md); background: var(--accent-wash); }
.session-record h2, .session-record p { margin: 0; }
.session-record label { margin: var(--sp-2) 0 0; }
.session-record textarea { width: 100%; padding: var(--sp-2) var(--sp-3); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--field); color: var(--fg); font: inherit; }
form.session-record > textarea + button { margin-top: var(--sp-2); justify-self: start; }

/* ------------------------------------------------- control exceptions */

/* The sections that apply to one choice only fold away where :has() works;
   elsewhere they are simply shown, which is untidy and still correct. */
@supports selector(:has(*)) {
  .exception-form:has(input[name="kind"][value="one_time"]:checked) .exception-continuous { display: none; }
  .exception-form:has(input[name="mode"][value="in_tool"]:checked) .exception-recorded { display: none; }
}
.exception-continuous, .exception-recorded { margin-top: var(--sp-3); }

.exception-risks ul, .exception-risk-list, .exception-list, .exception-reviews {
  margin: var(--sp-2) 0 0;
  padding: 0;
  list-style: none;
}
.exception-risks li { margin: 0 0 var(--sp-1); }
.exception-risks label { display: inline; margin: 0; font-weight: 500; }
.exception-risk-list li, .exception-list li, .exception-reviews li { padding: var(--sp-2) 0; }
.exception-risk-list li + li, .exception-list li + li, .exception-reviews li + li { border-top: 1px solid var(--line); }
.exception-risk-list li { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-1) var(--sp-3); }
.exception-list p, .exception-reviews p { margin: var(--sp-1) 0 0; }
.exception-state { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); margin: var(--sp-1) 0 0; }
.exception-past { margin-top: var(--sp-3); }
.exception-past summary { color: var(--muted); font-size: var(--text-sm); cursor: pointer; }
.exception-review-form { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--line); }

/* The report's exception list, as one small card per exception on a phone: four
   columns of names and dates do not share 390px. The head stays for screen
   readers, and each value is named by its cell. */
@media (max-width: 640px) {
  .exception-table thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .exception-table, .exception-table tbody, .exception-table tr { display: block; }
  .exception-table tr { padding: var(--sp-3) 0; border-top: 1px solid var(--line); }
  .exception-table tbody td,
  .exception-table tbody td.numeric { display: block; padding: var(--sp-1) 0 0; border: 0; text-align: left; }
  .exception-table tbody td.numeric { font-size: var(--text-sm); }
  .exception-table td[data-label]::before { content: attr(data-label) " "; color: var(--muted); }
}

/* The caveat an exception puts on a score: beside the number, never inside it. */
.exception-caveat {
  margin-top: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-left: 3px solid var(--band-high);
  border-radius: var(--r-sm);
  background: var(--accent-wash);
}
.exception-caveat p { margin: 0; }
.exception-caveat ul { margin: var(--sp-2) 0 0; padding-left: var(--sp-5); }
