/* ============================================================================
   Cornice Credit — design system (single source of truth).
   Light/paper is the default; dark is opt-in via [data-theme="dark"], and honored automatically
   when the OS prefers dark unless the user has explicitly chosen light.
   ============================================================================ */

/* Self-hosted IBM Plex Sans (400/500/600), latin subset. Paths are
   relative to this stylesheet (served at /assets/styles.css → /assets/fonts/…). */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/plex-sans-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/plex-sans-500.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/plex-sans-600.woff2") format("woff2");
}

/* Palette values live here once, as theme-independent constants; the theme selectors below only
   remap the semantic tokens to them. Dark is applied by two separate selectors (OS preference and
   explicit pin), so without this a colour fix would have to be made in two places and would
   eventually be made in one. Contrast targets are enforced by the R2 audit, not by eye:
   text >=4.5:1 (WCAG AA), component boundaries >=3:1 (WCAG 1.4.11). */
:root {
  /* light ramp */
  /* Contrast targets are checked against the WORST surface a token lands on, not against --paper.
     These two were originally certified on --paper alone and then used on raised and sunken
     surfaces, where they failed: --ink-faint hit 3.18:1 on dark --paper-raised (needs 4.5) and
     --line-strong 2.14:1 (needs 3). Light failed on --paper-sunken, dark on --paper-raised — the
     failing surface differs per theme, so checking one theme would not have caught both. */
  --l-paper: #f6f4ee;
  --l-paper-raised: #fffdf8;
  --l-paper-sunken: #efece2;
  --l-ink: #1b1a17;
  --l-ink-muted: #57534a;
  --l-ink-faint: #6d695f; /* 4.98 paper / 5.39 raised / 4.63 sunken — worst surface governs */
  --l-line: #bcb8ae; /* 1.80:1 — decorative divider (WCAG 1.4.11 exempt) */
  --l-line-strong: #89857b; /* 3.35 paper / 3.62 raised / 3.11 sunken — component boundary */
  --l-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231b1a17' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");

  /* dark ramp */
  --d-paper: #14130f;
  --d-paper-raised: #343229; /* 1.45:1 on --d-paper — elevation must be visible */
  --d-paper-sunken: #100f0c;
  --d-ink: #ece7db;
  --d-ink-muted: #a9a493;
  --d-ink-faint: #a09c8f; /* 6.77 paper / 4.68 raised / 6.98 sunken — worst surface governs */
  --d-line: #565345; /* 2.41:1 — decorative divider */
  --d-line-strong: #827e70; /* 4.57 paper / 3.16 raised / 4.72 sunken — component boundary */
  --d-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ece7db' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");

  /* --- palette: light / paper (default) --- */
  --paper: var(--l-paper); /* page background (warm off-white) */
  --paper-raised: var(--l-paper-raised); /* cards, inputs, popovers */
  --paper-sunken: var(--l-paper-sunken); /* subtle inset surfaces */
  --ink: var(--l-ink); /* primary text */
  --ink-muted: var(--l-ink-muted); /* secondary text */
  --ink-faint: var(--l-ink-faint); /* captions */
  --line: var(--l-line); /* hairline borders */
  --line-strong: var(--l-line-strong); /* emphasized borders */
  --accent: #1b1a17; /* primary action = ink (black-on-paper) */
  --accent-ink: #f6f4ee; /* text on --accent */
  --link: #2a2f6b; /* restrained indigo for links */
  --danger: #a3271f;
  --success: #2f6b3a;
  --warning: #8a5a0a; /* 5.38:1 on --paper, 5.82:1 on --paper-raised */
  --select-chevron: var(--l-select-chevron); /* the native <select> arrow, dressed in ink */

  /* --- type --- */
  --font-sans:
    "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial,
    sans-serif;
  --font-display: var(--font-sans);
  --step--2: clamp(0.66rem, 0.64rem + 0.08vw, 0.6875rem);
  --step--1: clamp(0.82rem, 0.8rem + 0.1vw, 0.875rem);
  --step-0: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --step-1: clamp(1.2rem, 1.13rem + 0.35vw, 1.4rem);
  --step-2: clamp(1.5rem, 1.35rem + 0.75vw, 1.95rem);
  --step-3: clamp(1.9rem, 1.6rem + 1.5vw, 2.75rem);
  --step-4: clamp(2.4rem, 1.9rem + 2.5vw, 3.8rem);
  --leading-tight: 1.12;
  --leading-snug: 1.3;
  --leading-body: 1.65;
  --tracking-wide: 0.12em; /* an uppercase label, spaced so the caps stay legible */

  /* Spacing roles. Pages name the role, not the step, so a gap cannot be chosen at random and the
     ladder stays monotonic: anything nested must sit inside the level that contains it. */
  --space-hair: var(--sp-1); /* a caption bound to the line above it */
  --space-tight: var(--sp-2); /* a label under its value */
  --space-heading: var(--sp-3); /* a heading to the content it introduces */
  --space-within: var(--sp-4); /* body under a heading, inside one block */
  --space-between: var(--sp-6); /* sibling blocks inside a section */
  --space-section: var(--sp-6); /* a section's own padding-block */
  --space-section-gap: calc(var(--space-section) * 2); /* sections gapped rather than padded */
  --space-page-start: var(--space-section); /* under the header, before a page's first block */
  --space-page-end: var(--sp-7); /* after a page's last block, before the footer */
  --space-list-indent: 1.25rem; /* room for a list marker */
  --site-brand-logo-size: 2rem; /* logo sits on the brand wordmark's cap height */

  /* --- space (0.25rem base) --- */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4.5rem;
  --sp-9: 7rem;

  /* --- form --- */
  --radius-sm: 3px;
  --radius: 5px;
  --radius-lg: 8px;
  /* Widths name what they hold, so a cap is chosen once and paired with the type role it was
     tuned for. ch measures line length in characters — the actual constraint — which is why each
     role belongs with its own type size: 68ch of body copy is a comfortable line, 68ch of caption
     is a much shorter one. */
  --width-title: 24ch; /* a section heading */
  --width-prose: 68ch; /* body copy */
  --width-art: 30rem; /* an illustration standing beside its text */
  --width-section: 56rem; /* a section narrower than the layout shell */
  --width-layout: 74rem; /* the layout shell */
  --header-height: 60px;
  /* 70%, not 30%. :focus-visible sets `outline: none` and uses this ring as the ONLY focus
     indicator, so it must satisfy WCAG 2.4.11 at >=3:1 against whatever it sits on. At 30% it
     measured 1.77:1 light and 1.80:1 dark — a ring a keyboard user could barely see, on every
     focusable element in the app. The binding surface is dark --paper-raised, which needs >=0.65;
     0.70 clears it with margin on all three surfaces in both themes. */
  --ring: 0 0 0 3px color-mix(in srgb, var(--link) 70%, transparent);
  --transition: 140ms ease;
}

/* Dark, when the OS prefers it and the user hasn't pinned light. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: var(--d-paper);
    --paper-raised: var(--d-paper-raised);
    --paper-sunken: var(--d-paper-sunken);
    --ink: var(--d-ink);
    --ink-muted: var(--d-ink-muted);
    --ink-faint: var(--d-ink-faint);
    --line: var(--d-line);
    --line-strong: var(--d-line-strong);
    --accent: #ece7db;
    --accent-ink: #14130f;
    --link: #a6adf0;
    --danger: #e08b84;
    --success: #8fce9c;
    --warning: #e3bd7a; /* 10.47:1 on --paper, 7.24:1 on --paper-raised */
    --select-chevron: var(--d-select-chevron);
  }
}

/* Dark, pinned explicitly (wins over OS preference). */
[data-theme="dark"] {
  --paper: var(--d-paper);
  --paper-raised: var(--d-paper-raised);
  --paper-sunken: var(--d-paper-sunken);
  --ink: var(--d-ink);
  --ink-muted: var(--d-ink-muted);
  --ink-faint: var(--d-ink-faint);
  --line: var(--d-line);
  --line-strong: var(--d-line-strong);
  --accent: #ece7db;
  --accent-ink: #14130f;
  --link: #a6adf0;
  --danger: #e08b84;
  --success: #8fce9c;
  --warning: #e3bd7a; /* 10.47:1 on --paper, 7.24:1 on --paper-raised */
  --select-chevron: var(--d-select-chevron);
}

/* Light, pinned explicitly (restores defaults over an OS dark preference). */
[data-theme="light"] {
  --paper: var(--l-paper);
  --paper-raised: var(--l-paper-raised);
  --paper-sunken: var(--l-paper-sunken);
  --ink: var(--l-ink);
  --ink-muted: var(--l-ink-muted);
  --ink-faint: var(--l-ink-faint);
  --line: var(--l-line);
  --line-strong: var(--l-line-strong);
  --accent: #1b1a17;
  --accent-ink: #f6f4ee;
  --link: #2a2f6b;
  --danger: #a3271f;
  --success: #2f6b3a;
  --warning: #8a5a0a; /* 5.38:1 on --paper, 5.82:1 on --paper-raised */
}

@media (min-width: 768px) {
  :root {
    --header-height: 72px;
  }
}

/* ---------------------------------------------------------------- reset --- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: var(--leading-body);
  color: var(--ink);
  background: var(--paper);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img,
svg,
video {
  display: block;
  max-width: 100%;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}

/* ------------------------------------------------------------ elements --- */
h1,
h2,
h3,
h4,
.subhead-bar__title {
  font-family: var(--font-display);
  line-height: var(--leading-tight);
  font-weight: 600;
  letter-spacing: -0.014em;
  text-wrap: balance;
}
h2,
.section-title {
  font-size: var(--step-1);
}
h3,
h4 {
  font-size: var(--step-0);
}
p {
  max-width: var(--width-prose);
}
a {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 0.16em;
  text-decoration-thickness: from-font;
}
a:hover {
  text-decoration-thickness: 0.09em;
}
hr {
  border: none;
  border-top: 1px solid var(--line);
  margin: var(--sp-6) 0;
}
code,
kbd,
samp {
  font-size: 0.9em;
}

/* ----------------------------------------------------------- layout ------ */
.wrap {
  width: 100%;
  max-width: var(--width-layout);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}
/* Hold a block to the line length its type role was tuned for; .hold-full releases it. */
.hold-full {
  max-width: 100%;
}
.hold-title {
  max-width: var(--width-title);
}
.hold-prose {
  max-width: var(--width-prose);
}
/* A line that runs to the layout, for text sized to be read at a glance rather than in a block. */
.hold-layout {
  max-width: var(--width-layout);
}

/* Page shell. Every page in both trees is this class plus a width modifier, so the gutter, the
   centring and the vertical padding are stated once. They used to be inline on each page, where a
   `padding: X 0` shorthand silently reset the gutter to zero — twice, in both trees. */
.page {
  width: 100%;
  max-width: var(--page-max, var(--width-layout));
  margin-inline: auto;
  padding-inline: var(--sp-5);
  padding-block: var(--page-start, var(--space-page-start)) var(--page-end, var(--space-page-end));
}
/* Named for what they hold, not for their size, so a page picks a role and inherits the width. A
   genuinely one-off width sets --page-max directly rather than earning a role of its own. */
.page--auth {
  --page-max: 27rem;
}
.page--panel {
  --page-max: 44rem;
}
.page--text {
  --page-max: 46rem;
}
.page--feed {
  --page-max: 52rem;
}
.page--prose {
  --page-max: 56rem;
}
.page--wide {
  --page-max: 60rem;
}
/* Vertical rhythm. Anything stacked uses these, so no component writes its own margin-top. */
.stack-sm > * + * {
  margin-top: var(--sp-2);
}
.stack > * + * {
  margin-top: var(--sp-4);
}
.stack-lg > * + * {
  margin-top: var(--sp-6);
}

/* Horizontal grouping. Five feature stylesheets had each written their own copy of this. */
.row {
  display: flex;
  align-items: center;
  gap: var(--row-gap, var(--sp-4));
  flex-wrap: wrap;
}
.row--tight {
  --row-gap: var(--sp-2);
}
.row--top {
  align-items: flex-start;
}
.row--end {
  justify-content: flex-end;
}
.row--nowrap {
  flex-wrap: nowrap;
}
.col {
  display: flex;
  flex-direction: column;
  gap: var(--row-gap, var(--sp-4));
}

/* Auto-fitting grid: --grid-min is the point a column stops shrinking and the track wraps, which is
   why none of these need a media query. */
.grid {
  display: grid;
  gap: var(--grid-gap, var(--sp-5));
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min, 16rem), 1fr));
}

/* A list that is a list semantically but not visually. The reset owns the margin; a <ul> keeps a
   default padding-inline-start (~40px) that would indent every row against the heading above it. */
.list-plain {
  list-style: none;
  padding: 0;
}
.muted {
  color: var(--ink-muted);
}
.faint {
  color: var(--ink-faint);
}
.hairline {
  border-top: 1px solid var(--line);
}
/* Out of view and out of the accessibility tree, but still laid out and still submitted with the
   form -- `display: none` and `hidden` both drop a control from FormData. */
.offscreen {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Page title — plain display sans, sized to outrank the section headings inside the page. */
/* A heading's level sets its size, here and nowhere else. */
h1,
.page-title,
.subhead-bar__title {
  font-size: var(--step-2);
  color: var(--ink);
}

/* Owns the gap to its content: sections that set their own margin-top all disagreed. Size comes
   from the h2 rule above; naming it twice is how the two drift apart. */
.section-title {
  color: var(--ink);
  margin-bottom: var(--space-heading);
}

/* Type roles. The scale itself lives in :root; these name the steps that recur, so pages stop
   restating font-size inline and a change to the scale reaches all of them. */
.t-figure {
  font-size: var(--step-1);
  line-height: var(--leading-tight);
}
/* The prose measure is a character count, so it shrinks with the type: small roles hit it long
   before the eye needs them to. Type that is not body copy takes the container instead. */
p.t-caption,
p.t-footnote {
  max-width: var(--page-max, var(--width-layout));
}
.t-footnote {
  font-size: var(--step--2);
}
.t-caption {
  font-size: var(--step--1);
}
.t-lead {
  font-size: var(--step-1);
}
/* ------------------------------------------------------- primitives ------ */
/* Button (<Button>) — variants via .btn--{variant}, sizes via .btn--sm/lg. */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  --btn-bd: var(--line-strong);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.55rem 1.05rem;
  font-size: var(--step-0);
  font-weight: 500;
  line-height: 1;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition:
    background var(--transition),
    border-color var(--transition),
    opacity var(--transition);
}
.btn:hover {
  background: color-mix(in srgb, var(--btn-fg) 8%, transparent);
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.btn--primary {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-ink);
  --btn-bd: var(--accent);
}
.btn--primary:hover {
  background: color-mix(in srgb, var(--accent) 88%, var(--ink));
}
.btn--ghost {
  --btn-bd: transparent;
}
.btn--danger {
  --btn-fg: var(--danger);
  --btn-bd: color-mix(in srgb, var(--danger) 45%, var(--line));
}
.btn--sm {
  padding: 0.35rem 0.7rem;
  font-size: var(--step--1);
}
.btn--lg {
  padding: 0.75rem 1.5rem;
  font-size: var(--step-1);
}
/* Icon-only trigger: square, no text metrics to pad around. */
.btn--icon {
  padding: 0.4rem;
}

/* Settings rows (<SettingsSection>) — the account surface. One bordered card, hairline row
   dividers, action on the right; an expanded form pushes the rows below it down rather than
   overlaying them. --line-strong on the card for the same component-boundary reason as .card. */
.settings {
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--paper-raised);
  overflow: hidden;
}
.settings__row + .settings__row {
  border-top: 1px solid var(--line);
}
.settings__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
}
.settings__name {
  font-weight: 500;
}
.settings__detail {
  margin-top: var(--sp-1);
  font-size: var(--step--1);
  color: var(--ink-muted);
}
/* A zero-width space, so a valueless row still occupies two lines and every row is the same height
   at any type scale. A min-height in rem would have to be re-derived every time the scale moves. */
.settings__detail:empty::before {
  content: "\200b";
}
.settings__summary {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.settings__body {
  padding: 0 var(--sp-5) var(--sp-5);
}

/* A <fieldset> carries a browser border, padding and margin that fight the design system; the
   legend needs the gap the stack cannot give it, since it is not a stack sibling. */
.fieldgroup {
  border: 0;
  padding: 0;
}
.fieldgroup > legend {
  margin-bottom: var(--sp-2);
}

/* Radio/checkbox row — the control and its label share a baseline and one hit target. */
.choice {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  cursor: pointer;
}

/* Card (<Card>) */
/* --line-strong, not --line: a card is a component boundary the user must be able to identify
   (WCAG 1.4.11, 3:1), not a decorative rule. Fill alone can't carry it in either theme — light
   sits against the white ceiling, dark would need a garish lift. */
.card {
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
}

/* Field + Input (<Input>) */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.field__label {
  font-size: var(--step--1);
  font-weight: 500;
  color: var(--ink-muted);
}
.input {
  width: 100%;
  padding: 0.55rem 0.75rem;
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  transition:
    border-color var(--transition),
    box-shadow var(--transition);
}
.input::placeholder {
  color: var(--ink-faint);
}
/* Native <select> in input dress: the themed chevron replaces the OS arrow, and required gives us
   :invalid for free, so the placeholder option reads faint. The listbox stays browser-native,
   keeping keyboard, assistive tech and required validation untouched. */
select.input {
  appearance: none;
  padding-right: calc(var(--sp-3) + 1rem + var(--sp-1));
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
  background-size: 1rem;
  color: var(--ink);
}
select.input option {
  color: var(--ink);
}
select.input:invalid {
  color: var(--ink-faint);
}
/* The old app disabled inputs with `disabled:opacity-50` (chat composer) and
   `opacity-50 cursor-not-allowed` (alert inputs). The port carried the disabled ATTRIBUTE across
   but not the affordance, so a disabled field looked identical to an editable one — the chat
   composer is disabled whenever a response is streaming or the context is full. Mirrors
   .btn:disabled so the whole system says "disabled" the same way. */
.input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
/* Every disabled control, not only those carrying .btn or .input. The design system's disabled
   styling was attached to two classes, so the many bare <button> elements across features
   (issuer toggles, section heads, filter triggers) rendered identically whether enabled or not —
   the control ignored the user and looked like it hadn't. */
button:disabled,
input:disabled,
select:disabled,
textarea:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.input:focus-visible {
  border-color: var(--link);
  box-shadow: var(--ring);
}
.input[aria-invalid="true"] {
  border-color: var(--danger);
}
.field__error {
  font-size: var(--step--1);
  color: var(--danger);
}
/* A live-status output starts empty; an empty flex item still pays the row's gap, pushing the
   row's other children off their alignment edge. Hide it until it has text to show. */
output:empty {
  display: none;
}

/* Badge (<Badge>) */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 0.15rem 0.55rem;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-full, 999px);
  color: var(--ink-muted);
  white-space: nowrap;
}
.badge--success {
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 45%, var(--line));
}
.badge--danger {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 45%, var(--line));
}
.badge--warning {
  color: var(--warning);
  border-color: color-mix(in srgb, var(--warning) 45%, var(--line));
}

/* Overlay primitives (Dialog/Menu/Popover) */
.overlay {
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, #000 42%, transparent);
  display: grid;
  place-items: center;
  padding: var(--sp-5);
}
.overlay__backdrop {
  position: absolute;
  inset: 0;
  background: none;
  border: none;
  cursor: default;
}
.dialog {
  position: relative;
  z-index: 1;
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  width: min(32rem, 100%);
  box-shadow: 0 24px 60px -24px color-mix(in srgb, #000 55%, transparent);
}
.menu {
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--sp-1);
  min-width: 11rem;
  box-shadow: 0 16px 40px -20px color-mix(in srgb, #000 50%, transparent);
}
.menu__item {
  display: flex;
  width: 100%;
  align-items: center;
  gap: var(--sp-2);
  /* 0.45rem produced a 42.42px row — under the 44px touch target by less than 2px. */
  padding: 0.55rem 0.6rem;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  text-align: left;
  cursor: pointer;
}
.menu__item:hover,
.menu__item[data-active="true"] {
  background: var(--paper-sunken);
}

/* ------------------------------------------------------- site shell (C0) --- */
.site {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.site-main {
  flex: 1;
}
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
/* One hairline under the chrome, not two: where a title bar follows the header, the two are one
   block and the lower bar closes it. */
.site:has(.subhead-bar) .site-header {
  border-bottom: none;
}
.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  height: var(--header-height);
}

/* A page's title line, pinned under the site header for the whole page. Sticky rather than revealed:
   a bar that appears only once its source scrolls away leaves a stretch with neither on screen. */
.subhead-bar {
  position: sticky;
  top: var(--header-height);
  z-index: 30;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.subhead-bar__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-between);
  padding-block: var(--space-tight);
}
/* Text centres on the page, not in the space the button leaves; the button stays on the edge.
   Both lanes name their row so sparse auto-placement can never drop the button under the text. */
.subhead-bar__inner > :not(.btn) {
  grid-column: 2;
  grid-row: 1;
  justify-self: center;
}
.subhead-bar__inner > .btn {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
}
.site-brand {
  display: flex;
  align-items: center;
  gap: var(--space-tight);
  font-weight: 600;
  font-size: var(--step-1);
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.01em;
}
.site-brand__logo {
  width: var(--site-brand-logo-size);
  height: var(--site-brand-logo-size);
}
.site-nav {
  display: flex;
  gap: var(--sp-5);
  margin-left: var(--sp-4);
}
.site-nav a {
  color: var(--ink-muted);
  text-decoration: none;
  font-size: var(--step-0);
}
.site-nav a:hover,
.site-nav a.is-active {
  color: var(--ink);
}
.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-left: auto;
}
.theme-btn {
  padding: 0.4rem;
}
/* The app swaps this icon in JS; the static site ships both and lets the theme cascade choose, so
   the two headers show the same mark. Same three theme selectors as above, ordered by specificity. */
.theme-icon--sun {
  display: none;
}
[data-theme="dark"] .theme-icon--sun {
  display: block;
}
[data-theme="dark"] .theme-icon--moon {
  display: none;
}
[data-theme="light"] .theme-icon--sun {
  display: none;
}
[data-theme="light"] .theme-icon--moon {
  display: block;
}
/* Last, and highest specificity, so the OS preference only reaches roots with no explicit choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-icon--sun {
    display: block;
  }
  :root:not([data-theme="light"]) .theme-icon--moon {
    display: none;
  }
}
.site-footer {
  border-top: 1px solid var(--line);
  /* A page tunes its own run-out by setting --footer-gap, the way .page sets --page-end. */
  margin-top: var(--footer-gap, var(--space-section));
  padding: var(--sp-6) 0;
}
.site-footer__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.site-footer__links {
  display: flex;
  gap: var(--sp-4);
}
.site-footer__links a {
  color: var(--ink-muted);
  text-decoration: none;
  font-size: var(--step--1);
}
.site-footer__links a:hover {
  color: var(--ink);
}
.site-footer__legal {
  margin-left: auto;
  font-size: 0.72rem;
}
/* The nav's narrow-screen home: the same links, collapsed behind a hamburger. A hidden checkbox
   drives it, so the static site needs no JS; the panel wears the app menu's surface. */
.site-nav-menu {
  position: relative;
  display: none;
}
.site-nav-menu__toggle {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.site-nav-menu__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-2);
  color: var(--ink);
  border-radius: var(--radius-sm);
}
.site-nav-menu__toggle:focus-visible ~ .site-nav-menu__button {
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}
.site-nav-menu__panel {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 50;
  margin: 0;
  padding: var(--sp-1);
  list-style: none;
  min-width: 11rem;
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 16px 40px -20px color-mix(in srgb, #000 50%, transparent);
}
.site-nav-menu__toggle:checked ~ .site-nav-menu__panel {
  display: block;
}
.site-nav-menu__panel a {
  display: block;
  padding: 0.55rem 0.6rem;
  border-radius: var(--radius-sm);
  color: var(--ink-muted);
  text-decoration: none;
}
.site-nav-menu__panel a:hover,
.site-nav-menu__panel a.is-active {
  color: var(--ink);
  background: var(--paper-sunken);
}
@media (max-width: 640px) {
  .site-nav {
    display: none;
  }
  /* Full column height so the panel drops flush beneath the header, not under the button. */
  .site-header__actions {
    align-self: stretch;
  }
  .site-nav-menu {
    display: flex;
    align-items: center;
    align-self: stretch;
  }
}

/* Long-form article — case studies and news posts share it, so the two read as one page type. */
.article h1 {
  margin-top: var(--space-hair);
  line-height: 1.15;
}
.article__standfirst {
  margin-top: var(--space-within);
  line-height: 1.55;
  color: var(--ink-muted);
}
.article__meta {
  margin-top: var(--space-within);
  padding-top: var(--space-within);
  border-top: 1px solid var(--line);
  color: var(--ink-faint);
}

/* The article reads as one column, so a section keeps the same distance from the block above it
   that the title block's own parts keep from each other. */
/* The article ends on the same run-out a section's own padding gives, so the distance into the
   footer is the one every page uses. */
.article {
  --page-end: var(--space-section);
}
.site-main:has(.article) + .site-footer {
  margin-top: var(--space-section);
}
.article__section {
  margin-top: var(--space-between);
}
.article__section h2 {
  line-height: 1.25;
}
.article__section > * + * {
  margin-top: var(--space-within);
}
.article__back {
  margin-top: var(--space-between);
  padding-top: var(--space-within);
  border-top: 1px solid var(--line);
}

/* A quoted fragment of the filing. */
.excerpt__caption {
  color: var(--ink-faint);
  margin-bottom: var(--space-hair);
}
.excerpt__page {
  margin: 0;
  padding: var(--space-tight) 0 var(--space-tight) var(--space-within);
  border-left: 2px solid var(--ink);
  color: var(--ink);
  line-height: 1.6;
}
.excerpt__page > p + p {
  margin-top: var(--space-tight);
}
.excerpt__page > p {
  padding-left: calc(var(--excerpt-depth, 0) * var(--space-within));
}
.excerpt__clause {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-tight);
}
/* Columns, so alignment survives without a monospace grid and preserved tabs. */
.excerpt__page--columns > p + p {
  margin-top: var(--space-hair);
}
.excerpt__row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-within);
  font-variant-numeric: tabular-nums;
}
.excerpt__row > span:only-child {
  grid-column: 1 / -1;
}
/* A row that prints no title still hangs its page number off the right edge. */
.excerpt__row > span:nth-child(2):last-child {
  grid-column: 3;
}
.excerpt__row > span:last-child:not(:only-child) {
  text-align: right;
}

/* The bar carries the way back and the way forward, so the title is a link and its kind sits
   beside it rather than under a second heading. */
.subhead-bar__title a {
  color: inherit;
  text-decoration: none;
}
.subhead-bar__kind {
  margin-left: var(--space-within);
  font-size: var(--step-1);
  color: var(--ink-faint);
  font-weight: 400;
  white-space: nowrap;
}
.subhead-bar__inner .btn {
  white-space: nowrap;
}
@media (max-width: 560px) {
  /* The bar trades its desktop line for two lanes: text on the left, button on the right, still
     vertically centred against each other. Only the text stacks — the title over the kind. */
  .subhead-bar__inner {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
  }
  .subhead-bar__inner > * {
    text-align: center;
  }
  .subhead-bar__inner > :not(.btn) {
    grid-column: 1;
    grid-row: 1;
    justify-self: center;
  }
  /* A bar with no button (contact pages) keeps its text centred across the whole width. */
  .subhead-bar__inner > :not(.btn):only-child {
    grid-column: 1 / -1;
  }
  .subhead-bar__inner > .btn {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }
  .subhead-bar__kind {
    display: block;
    margin-left: 0;
  }
}

/* ------------------------------------------------------- hidden, for real --- */
/* Any author `display` (.field, .row, .grid…) outranks the UA sheet's `[hidden] { display: none }`,
   so the attribute silently does nothing without this. Last in the file and !important so it wins
   on source order too — jsdom's cascade ignores !important, and the tests read this sheet. */
[hidden] {
  /* biome-ignore lint/complexity/noImportantStyles: beating the cascade is the whole point here */
  display: none !important;
}
