/* site.css — Bluebird FOI Insights chrome + chart system.

The chrome follows the Bluebird Horizon identity (horizon.axoquant.com):
a light surface masthead with a navy "Bluebird" word and a violet uppercase
"FOI INSIGHTS" product label, a violet hairline under it, a top-level nav of
five internal FOI sections, a two-column layout (sidenav + main), and a footer
on the light surface. DM Sans everywhere (the Horizon typeface — no display
serif). The reference site pins the palette to LIGHT: its head runs
setAttribute("data-theme","light") before any CSS, and the dark tokens only
apply under :root[data-theme=dark] / :root:not([data-theme=light]) — never
from a bare prefers-color-scheme match. This file replicates that exactly, so
the site renders light even on dark-OS machines.

Accessibility: body --ink #0f1e33 on --page #ffffff ≈ 13.9:1 (AAA);
secondary --ink-2 #4a5a72 ≈ 7:1 (AA); links --brand #5d4fff ≈ 5.2:1 (AA);
muted #7b8ca4 ≈ 3.4:1 is reserved for small decorative labels, not body text.
:focus-visible draws a 2px blue outline, ::selection fills violet.

The chart system follows the dataviz method: series colours are a validated
categorical palette, every figure renders into an ECharts .chartbox mount, and
text always wears ink rather than a series colour. A missing year renders as
"—"; a genuinely absent measure renders an explicit no-data placeholder.
*/

:root {
  /* Bluebird Horizon brand */
  --brand: #5d4fff;    /* primary accent / links / product label */
  --blue:  #0787d9;    /* hover / focus */
  --cyan:  #7ef9ff;    /* brand accent */
  --navy:  #00294b;    /* wordmark name / ribbon */
  /* chrome (light default) */
  --page:     #ffffff;
  --surface:  #f7f9fc;
  --ink:      #0f1e33;
  --ink-2:    #4a5a72;
  --muted:    #7b8ca4;
  --grid:     #e4eaf2;
  --baseline: #cbd5e1;
  --border:   rgba(15, 30, 51, 0.10);
  /* chart series */
  --c1: #5d4fff; --c2: #0787d9; --c3: #0ea5e9;
  --c4: #6366f1; --c5: #334155; --c6: #7c3aed;
  /* status / accents */
  --pos: #16a34a; --neg: #ea580c; --crit: #dc2626;
  --pos-ink: #0f7a37;  /* AA text on the pos wash (--pos is 3.4:1) */
  --neg-ink: #b23c06;  /* AA text on the neg wash (--neg is 3.0:1) */
  --evidence: #dc2626;   /* form errors (readable red) */
  --nodata:   #4a5a72;   /* placeholder text (AA on page) */
  --petal:    #edf1fa;   /* pale violet wash — active sidenav entry */
  --petal-ink:#22365b;   /* text on the pale wash */
  --link:          #5d4fff;
  /* type */
  --sans:  "DM Sans", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono:  "IBM Plex Mono", ui-monospace, Consolas, monospace;
  --shadow: 0 1px 2px rgba(15, 30, 51, 0.06), 0 6px 20px rgba(15, 30, 51, 0.06);
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  background: var(--page);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--sans); }

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

/* --- masthead + wordmark ---------------------------------------------------
   The layout is Tailwind utilities (flex / px-8 py-3 ...); colours and type
   are bespoke so the prefers-color-scheme override can flip them. */

.site-header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.logo { display: flex; align-items: center; gap: 10px; }

/* the Bluebird mark — same 34x34 flex-none as the Horizon masthead */
.bb-mark { width: 34px; height: 34px; flex: none; border-radius: 6px; }

.wordmark { text-decoration: none; color: inherit; display: flex; align-items: baseline; gap: 10px; }

.wordmark-name {
  font-family: var(--sans);
  font-size: 25px;
  font-weight: 700;
  letter-spacing: 0.2px;
  color: var(--navy);
}
.wordmark-product {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--brand);
}

/* the violet hairline under the masthead (Horizon signature) */
.hairlines {
  max-width: 1400px;
  margin: 10px auto 0;
  border-top: 2px solid var(--brand);
  border-bottom: 1px solid var(--border);
  height: 3px;
}

.topnav .nav-link {
  color: var(--ink-2);
  text-decoration: none;
  font-size: 0.92rem;
  padding: 0.35rem 0.5rem;
  border-radius: 8px;
}
.topnav .nav-link:hover { background: var(--petal); color: var(--petal-ink); }
.topnav .nav-link.active {
  color: #fff;
  background: var(--brand);
  font-weight: 600;
}
.topnav .btn-login {
  background: var(--brand);
  color: #fff;
  padding: 0.4rem 0.9rem;
  border-radius: 8px;
  font-weight: 600;
}
.topnav .btn-login:hover { background: var(--blue); }
.nav-username { color: var(--ink-2); font-weight: 600; font-size: 0.9rem; padding: 0 0.4rem; }

/* signed-in account chip: a small avatar circle with the user's initial */
.user-chip { display: inline-flex; align-items: center; gap: 0.45rem; }
.user-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
}

/* --- breadcrumb ------------------------------------------------------------ */

.breadcrumb {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  color: var(--ink-2);
}

/* --- two-column layout: sidenav + main ---------------------------------------
   The flex layout, fixed sidenav width, sticky behaviour and main column are
   Tailwind utilities (layout flex items-start ... / sidenav shrink-0 w-sidenav
   sticky ... / main flex-1 max-w-main ...). The inner .group / .navbtn styling
   stays here, and main's background uses var(--page) so it flips with the
   theme. */

main#main { background: var(--page); color: var(--ink); }

.sidenav .group {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 1.1rem 0 0.3rem;
}
.sidenav .group:first-child { margin-top: 0; }

.sidenav .navbtn {
  display: block;
  color: var(--ink-2);
  text-decoration: none;
  font-size: 0.9rem;
  padding: 0.32rem 0.6rem;
  border-radius: 8px;
}
.sidenav .navbtn:hover { background: var(--petal); color: var(--petal-ink); }
.sidenav .navbtn.active {
  background: var(--petal);
  color: var(--petal-ink);
  font-weight: 650;
}

h1 {
  font-size: 2rem;
  font-weight: 700;
  margin: 0 0 0.25rem;
  color: var(--ink);
}

.intro { color: var(--ink-2); max-width: 60ch; margin: 0 0 1.25rem; }

/* A scoped page names its selection beside the title. The badge rides in the
   h1 and wears the petal wash (the same pale-violet treatment as the active
   sidenav entry), so it reads as a marker rather than a heading of its own. */
.scope-badge {
  display: inline-block;
  vertical-align: middle;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--petal-ink);
  background: var(--petal);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.15rem 0.65rem;
  margin-left: 0.5rem;
}
/* The narrative block's lead sentence on a scoped page: names the selection
   the following figures describe. Body text, so it takes --ink-2. */
.scope-sentence { color: var(--ink-2); margin: 0 0 0.5rem; }

/* --- KPI tiles ------------------------------------------------------------- */

.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.75rem;
  margin: 1.25rem 0;
}

.kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 3px solid var(--brand);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.kpi .label { font-size: 0.8rem; color: var(--ink-2); text-transform: uppercase; letter-spacing: 0.02em; }
.kpi .tlabel { font-size: 0.78rem; color: var(--muted); }
.kpi .value { font-size: 1.9rem; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.kpi .basis { font-size: 0.78rem; color: var(--ink-2); border-top: 1px dashed var(--border); padding-top: 0.3rem; margin-top: 0.3rem; }
.kpi .source, .figure-card .source {
  display: block; font-size: 0.72rem; color: var(--muted); margin-top: 2px;
}
.kpi .delta { display: block; font-size: 0.85rem; margin-top: 2px; font-variant-numeric: tabular-nums; }
.kpi .delta.pos { color: #1a7f37; }
.kpi .delta.neg { color: #c0392b; }
.kpi .delta.dim { color: var(--muted); }
/* .fignote carries every honesty caveat the chart engine emits — the ranking
   pool, the axis-rescale and axis-extension disclaimers, the single-year
   explanation. It is body text, not a decorative label, so it takes --ink-2
   (6.64:1 on the card surface); --muted put the disclaimer at 3.25:1 — under
   the 4.5:1 AA bar, and the least legible line on the page. */
.fignote {
  font-size: 0.78rem; color: var(--ink-2); margin: 6px 0 0;
}
/* Each chart card ships an EMPTY .fignote (pages.py _chart_container) so the
   engine writes into a live region that already exists — a note created fresh
   on each render is a new node, and a screen reader announces nothing when the
   caveat under a chart changes. Empty, it must occupy no space.

   It must NOT be display:none while it does so. A live region that is
   display:none at the moment it is mutated is the case screen readers most
   often skip — the region is not in the accessibility tree when the text
   lands, so the announcement is lost — and empty -> text is exactly the FIRST
   filter selection of a session, which is when the honesty caveats first
   appear. visibility:hidden has the same defect (it removes the subtree from
   the accessibility tree too). The clip pattern below keeps the element
   mounted, exposed and announceable while taking it out of flow, so it
   contributes no height between the chart and the next card. */
.fignote:empty {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- movers tables (the FY-pair change analysis beside each change chart) --- */

.movers { width: 100%; border-collapse: collapse; margin: 0.75rem 0 0; }
.movers th, .movers td {
  border-bottom: 1px solid var(--border);
  padding: 0.45rem 0.6rem;
  text-align: left;
}
.movers th { font-size: 0.78rem; color: var(--ink-2); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.02em; }
.movers th:not(:first-child), .movers td:not(:first-child) {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.movers tbody tr:last-child td { border-bottom: none; }

/* --- figure cards ---------------------------------------------------------- */

.figure-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 1.25rem 1.5rem 1.5rem;
  margin: 1.5rem 0;
}
.figure-card h2 {
  font-size: 1.35rem;
  margin: 0 0 0.25rem;
  color: var(--ink);
}
.figure-card .basis { color: var(--ink-2); font-size: 0.8rem; margin: 0 0 1rem; }

.note {
  color: var(--ink-2);
  font-size: 0.92rem;
  border-left: 3px solid var(--neg);
  padding: 0.4rem 0.75rem;
  margin: 0 0 1rem;
}

/* --- login form + hint ------------------------------------------------------ */

.login-form { max-width: 26rem; margin: 1.25rem 0; }
.login-form label {
  display: block;
  font-size: 0.85rem;
  color: var(--ink-2);
  margin: 0.9rem 0 0.3rem;
}
.login-form input {
  display: block;
  width: 100%;
  padding: 0.55rem 0.7rem;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 1rem;
}
.login-form input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(7, 135, 217, 0.14);
}
.login-form button {
  margin-top: 1.1rem;
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  padding: 0.5rem 1.1rem;
  border: none;
  border-radius: 8px;
  font-size: 1rem;
  cursor: pointer;
}
.login-form button:hover { background: var(--blue); }
.form-error {
  color: var(--evidence);
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.9rem;
  max-width: 26rem;
}
.hint { color: var(--ink-2); font-size: 0.88rem; max-width: 60ch; }

/* --- chat (gated Q&A) ------------------------------------------------------ */

.chatlog {
  max-width: 760px;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: 1.25rem 0 0.25rem;
  max-height: 62vh;
  overflow-y: auto;
  padding-right: 0.25rem;
}

.msg {
  max-width: 82%;
  padding: 0.6rem 0.85rem;
  border-radius: 14px;
  font-size: 0.95rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}
.msg p { margin: 0 0 0.4rem; }
.msg p:last-child { margin-bottom: 0; }
.msg ul { margin: 0.2rem 0; padding-left: 1.1rem; }

.msg.user {
  align-self: flex-end;
  background: var(--brand);
  color: #fff;
  border-bottom-right-radius: 4px;
}

.msg.assistant {
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink);
  border-bottom-left-radius: 4px;
}
.msg.assistant strong { color: var(--ink); }
.msg.typing {
  color: var(--muted);
  font-style: italic;
  background: transparent;
  border: none;
  padding-left: 0.25rem;
}

.msg .cite {
  margin-top: 0.5rem;
  padding-top: 0.45rem;
  border-top: 1px dashed var(--border);
  font-size: 0.74rem;
  color: var(--muted);
  white-space: normal;
}
.msg .cite a { color: var(--link); text-decoration: none; }
.msg .cite a:hover { text-decoration: underline; }

.escalate {
  margin-top: 0.5rem;
  font-size: 0.82rem;
  color: var(--ink-2);
}

.chat-input {
  max-width: 760px;
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
}
.chat-input input {
  flex: 1;
  padding: 0.6rem 0.8rem;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-size: 0.95rem;
}
.chat-input input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(7, 135, 217, 0.14);
}
.chat-input button {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  padding: 0.6rem 1.1rem;
  border: none;
  border-radius: 8px;
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}
.chat-input button:hover { background: var(--blue); }

/* --- risk sections --------------------------------------------------------- */

.risk-section { margin: 1.5rem 0; }
.risk-absent {
  color: var(--ink-2);
  font-style: italic;
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: var(--surface);
  padding: 0.9rem 1.1rem;
  max-width: 70ch;
}
.risk-summary { font-size: 1.02rem; color: var(--ink); max-width: 70ch; }
.provenance { color: var(--ink-2); font-size: 0.8rem; margin: 1.5rem 0 0; }

.risk-details { margin: 1rem 0 0; font-size: 0.85rem; color: var(--ink-2); }
.risk-details summary { cursor: pointer; color: var(--link); font-weight: 600; }
.risk-details .provenance { margin: 0.5rem 0 0; font-size: 0.78rem; }

/* --- provenance page --------------------------------------------------------
   The sources, publication history and revision record carry their evidence in
   the open; the meta line under each source and the history dates are the one
   place the reader scans for a date or a hash. */
.sources, .history { margin: 0.5rem 0; }
.sources li, .history li { margin: 0 0 1rem; }
.sources .src-meta { font-size: 0.85rem; color: var(--ink-2); margin: 0.2rem 0 0; }
.sources .src-meta a, .sources .src-meta a:visited { color: var(--link); }
.sources .notes { margin: 0.5rem 0 0; }
.hash { font-family: var(--mono); font-size: 0.9em; }
.history .when { font-weight: 600; color: var(--ink); }
.history .hist-note { display: block; color: var(--ink-2); font-size: 0.9rem; margin-top: 0.25rem; }
.revisions { margin-top: 0.25rem; }
.revisions th { white-space: nowrap; }

/* risk-tier badges — the reader-facing rating, not the model internals */
.tier {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
}
.tier-low    { background: #e7f6ec; color: #15803d; }
.tier-medium { background: #fdeede; color: #c2410c; }
.tier-high   { background: #fee9e9; color: #b91c1c; }

.risk-search { max-width: 26rem; margin: 0.5rem 0; }
.risk-search input {
  width: 100%;
  padding: 0.5rem 0.7rem;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-size: 0.9rem;
}
.risk-search input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(7, 135, 217, 0.14);
}

.chartbox-sm { min-height: 220px; }

/* report + risk data tables (rendered by report.js / risk.js) */
.report-table { width: 100%; border-collapse: collapse; margin: 0.75rem 0; }
.report-table th, .report-table td {
  border-bottom: 1px solid var(--border);
  padding: 0.45rem 0.6rem;
  text-align: left;
}
.report-table th { font-size: 0.78rem; color: var(--ink-2); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.02em; }
.report-table td:not(:first-child) { font-variant-numeric: tabular-nums; }

/* --- reports page (deterministic lookup + built dashboard) --- */
.report-input {
  max-width: 760px;
  display: flex;
  gap: 0.5rem;
  margin: 1rem 0;
}
.report-input input {
  flex: 1;
  padding: 0.6rem 0.8rem;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-size: 0.95rem;
}
.report-input input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(7, 135, 217, 0.14);
}
.report-input button {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  padding: 0.6rem 1.2rem;
  border: none;
  border-radius: 8px;
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}
.report-input button:hover { background: var(--blue); }

.report-out { max-width: 760px; }
.report-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 1rem 1.25rem 1.1rem;
  margin: 1rem 0;
}
.report-card h2 { margin-top: 0; }
.report-card .value { font-size: 2rem; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; margin: 0.2rem 0; }
.report-card .basis { color: var(--ink-2); font-size: 0.8rem; }
.report-card .cite { color: var(--muted); font-size: 0.76rem; }
.report-card .cta {
  display: inline-block;
  margin-top: 0.6rem;
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  text-decoration: none;
}
.report-card .cta:hover { background: var(--blue); }

/* "Your reports" index table (reports page) */
.reports-index td { vertical-align: middle; }
.reports-index .report-req { max-width: 28rem; overflow-wrap: anywhere; }
.reports-index .report-when { white-space: nowrap; color: var(--ink-2); font-size: 0.85rem; }
.reports-index .report-actions { white-space: nowrap; text-align: right; }
.reports-index .report-actions .nav-link { margin-right: 0.6rem; }

.status-badge {
  display: inline-block;
  font-size: 0.74rem;
  font-weight: 600;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
}
.status-ready    { background: #e7f6ec; color: #15803d; }
.status-building { background: #eaf2fd; color: #1d4ed8; }
.status-error    { background: #fee9e9; color: #b91c1c; }
.status-unknown  { background: #f1f5f9; color: #64748b; }

.report-delete {
  background: transparent;
  color: var(--ink-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.2rem 0.6rem;
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}
.report-delete:hover { border-color: #b91c1c; color: #b91c1c; }

/* risk ranking: sortable, filterable, clickable */
.risk-controls {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
  margin: 0.5rem 0;
}
.risk-filter-label {
  font-size: 0.85rem;
  color: var(--ink-2);
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.risk-filter-label select {
  padding: 0.35rem 0.5rem;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-size: 0.85rem;
}
.risk-table tbody tr { cursor: pointer; }
.risk-table tbody tr:hover td { background: #f3f1ff; }
.risk-table tbody tr.selected td { background: #ece9ff; }
.risk-table th.sortable, .compliance-tbl th.sortable,
.agency-preview th.sortable { cursor: pointer; user-select: none; }
.risk-table th.sortable:hover, .compliance-tbl th.sortable:hover { color: var(--blue); }
.risk-table th.sort-asc::after, .compliance-tbl th.sort-asc::after { content: " \2191"; color: var(--blue); }
.risk-table th.sort-desc::after, .compliance-tbl th.sort-desc::after { content: " \2193"; color: var(--blue); }
.detail-close {
  float: right;
  background: transparent;
  border: none;
  color: var(--ink-2);
  cursor: pointer;
  font: inherit;
  font-size: 0.8rem;
  text-decoration: underline;
}
.detail-close:hover { color: var(--blue); }

/* build theatre (queued job cards) */
.job-card .statusline { display: flex; align-items: center; gap: 0.5rem; }
.job-card .job-status { font-weight: 600; }
.job-steps { list-style: none; margin: 0.4rem 0 0; padding: 0; }
.job-steps li {
  color: var(--ink-2);
  font-size: 0.8rem;
  padding: 0.15rem 0;
  border-left: 2px solid var(--border);
  padding-left: 0.6rem;
}
.job-steps li:last-child { color: var(--ink); border-left-color: var(--blue); }
.job-step { margin-left: 0.4rem; font-size: 0.78rem; }
.job-retry {
  margin-top: 0.6rem;
  background: transparent;
  color: var(--blue);
  border: 1px solid var(--blue);
  border-radius: 6px;
  padding: 0.3rem 0.8rem;
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}
.job-retry:hover { background: var(--blue); color: #fff; }
.spin {
  display: inline-block;
  width: 0.9rem;
  height: 0.9rem;
  border: 2px solid var(--border);
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* --- ECharts containers ---------------------------------------------------- */

.chartbox { min-height: 320px; }

/* A horizontal ranking draws every category label (interval: 0), so its 20
   bands need room: at the 320px default they share ~280px — ~14px a band
   against an 11px font — and the labels collide. pages.py (_chart_container)
   now emits .topn with the markup for a top_n figure, so the tall box is there
   before any script runs. foi-charts.js re-adds it on mount (a no-op on a
   server-classed box) and REMOVES it when the same box falls back to a trend or
   a placeholder — a one-agency selection turns a ranking into a trend. */
.chartbox.topn { min-height: 560px; }

/* --- no-data placeholders -------------------------------------------------- */

.nodata {
  color: var(--nodata);
  font-style: italic;
  border: 1px dashed var(--border);
  border-radius: 10px;
  padding: 1rem;
  margin: 0.5rem 0;
  max-width: 70ch;
}

/* --- lineage page ---------------------------------------------------------- */

.lineage { margin-top: 2rem; font-size: 0.95rem; }
pre {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.85rem 1rem;
  font-family: var(--mono);
  font-size: 0.82rem;
  line-height: 1.45;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
section { margin: 1.4rem 0; }
.op, .call { margin: 0.9rem 0; }
.meta { color: var(--muted); font-size: 0.8rem; }
.apitable { width: 100%; border-collapse: collapse; margin: 1rem 0; }
.apitable th, .apitable td {
  border: 1px solid var(--border);
  padding: 0.55rem 0.75rem;
  text-align: left;
  vertical-align: top;
}
.apitable th { background: var(--surface); font-weight: 600; }
.apitable code { background: var(--surface); padding: 0.1rem 0.3rem; border-radius: 3px;
  font-size: 0.85em; }

/* --- data notes (verbatim corpus) ------------------------------------------ */

.notes { max-width: 78ch; }

/* Tailwind preflight zeroes all element margins; bare paragraphs/pre blocks
   on the prose pages (how-to-use, api) get their vertical rhythm back. */
main p, main pre { margin: 0.75rem 0; }
.notes h1 { font-size: 1.6rem; }
.notes h2 { font-size: 1.25rem; margin: 1.6rem 0 0.5rem; }
.notes p { margin: 0.75rem 0; }
.notes ul { list-style: disc; padding-left: 1.25rem; }
.notes em { font-style: italic; }

/* --- filters + how-to ------------------------------------------------------ */

.filters {
  border: 1px dashed var(--border);
  border-radius: 10px;
  color: var(--ink-2);
  font-size: 0.88rem;
  padding: 0.6rem 1rem;
  margin: 1rem 0 1.5rem;
}
.filter-select {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--grid);
  border-radius: 8px;
  padding: 0.3rem 0.5rem;
  font: inherit;
}
.filter-select:focus { outline: none; border-color: var(--blue); }
/* A scoped page's bar is a <form>: the submit button keeps it working without
   JavaScript and the hint names what the two groups of controls do. */
.filters .scope-submit {
  background: var(--brand);
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: 0.35rem 0.9rem;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.filters .scope-submit:hover { background: var(--blue); }
.scope-hint { color: var(--ink-2); font-size: 0.85rem; margin: 0 0 1.5rem; }
h2 { font-size: 1.3rem; margin: 1.5rem 0 0.5rem; }
/* Tailwind's preflight resets ul/ol to list-style:none; the prose lists
   (how-to-use, data-notes) render with bullets again here. */
ul { list-style: disc; padding-left: 1.25rem; }

/* --- footer ----------------------------------------------------------------
   The band bg, text colour and padding are bespoke + Tailwind layout (bg via
   var(--surface) so it flips; px-8 py-7 via utilities). */

.sitefoot { background: var(--surface); border-top: 1px solid var(--border); }
.sitefoot .country { margin-bottom: 0.4rem; color: var(--ink-2); }
.sitefoot .legal { margin-bottom: 0.4rem; color: var(--ink-2); }
.sitefoot .legal a { color: var(--link); }
.sitefoot .legal .sep { color: var(--muted); padding: 0 0.3em; }
.sitefoot .stack { color: var(--muted); }
.sitefoot a { color: var(--link); }

/* --- focus states ---------------------------------------------------------- */

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

::selection { background: var(--brand); color: #fff; }

/* --- skip link (WCAG 2.4.1): visually hidden until focused ------------------ */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
}
.skip-link:focus {
  left: 0;
  top: 0;
  background: var(--surface);
  color: var(--ink);
  padding: 0.6rem 1rem;
  border: 2px solid var(--blue);
  border-radius: 0 0 6px 0;
  text-decoration: none;
}

/* --- dark variant (opt-in, never auto) ----------------------------------------
   Exactly the reference site's mechanism: the palette only goes dark when the
   root carries data-theme=dark, or when prefers-color-scheme is dark AND the
   page did not pin data-theme=light. chrome() pins data-theme=light in the head
   before any CSS, so on the live site this block is inert — the page stays
   light regardless of OS theme, matching horizon.axoquant.com. Tailwind
   utilities are static hex, so the chrome colours ride on the var() tokens
   above rather than utilities. */

:root[data-theme=dark] {
  --page:     #0b1b33;
  --surface:  #10274a;
  --ink:      #e8f0fa;
  --ink-2:    #b0c2d9;
  --muted:    #7e93ad;
  --grid:     #1d3a5f;
  --baseline: #2a4a74;
  --border:   rgba(232, 240, 250, 0.12);
  --c1: #8b81ff; --c2: #3fa2e8; --c3: #4fc1f0;
  --c4: #7c8cff; --c5: #9fb2cc; --c6: #a78bfa;
  --navy:     #e8f0fa;        /* wordmark name flips to light */
  --petal:    #123055;        /* active sidenav wash on dark */
  --petal-ink:#c6d6ec;
  --nodata:   #b0c2d9;
  --pos-ink:  #4ade80;
  --neg-ink:  #fdba74;
  --link:          #3fa2e8;
  --link-visited:  #a78bfa;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme=light]) {
    --page:     #0b1b33;
    --surface:  #10274a;
    --ink:      #e8f0fa;
    --ink-2:    #b0c2d9;
    --muted:    #7e93ad;
    --grid:     #1d3a5f;
    --baseline: #2a4a74;
    --border:   rgba(232, 240, 250, 0.12);
    --c1: #8b81ff; --c2: #3fa2e8; --c3: #4fc1f0;
    --c4: #7c8cff; --c5: #9fb2cc; --c6: #a78bfa;
    --navy:     #e8f0fa;        /* wordmark name flips to light */
    --petal:    #123055;        /* active sidenav wash on dark */
    --petal-ink:#c6d6ec;
    --nodata:   #b0c2d9;
    --pos-ink:  #4ade80;
    --neg-ink:  #fdba74;
    --link:          #3fa2e8;
    --link-visited:  #a78bfa;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3);
  }
}

/* --- responsive collapse under 900px --------------------------------------- */

/* The < 900px collapse restyles the chrome the way Tailwind utilities own it
   (layout / sidenav / main / header / breadcrumb), so those selectors carry
   !important to beat the utility layer. `.sidenav .group` / `.sidenav .navbtn`
   are bespoke-only (utilities never touch them) and need no override. */

@media (max-width: 900px) {
  .layout { flex-direction: column !important; }
  .sidenav {
    flex: none !important;
    width: 100% !important;
    position: static !important;
    max-height: none !important;
    overflow-y: visible !important;
    padding: 1rem 1.5rem !important;
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 0.25rem 0.5rem !important;
    border-bottom: 1px solid var(--border);
  }
  .sidenav .group {
    flex: 0 0 100%;
    margin: 0.5rem 0 0.1rem;
  }
  .sidenav .navbtn {
    display: inline-block;
    border-radius: 8px;
    padding: 0.3rem 0.55rem;
  }
  main { padding: 1.5rem !important; }
  .site-header { padding: 0.7rem 1.25rem !important; }
  .breadcrumb { padding: 0.5rem 1.25rem !important; }
}

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

/* --- year-over-year paired bars --------------------------------------------- */

.bar-chart { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.bar-end.none { background: var(--muted); width: 6px; opacity: .5; }
.bval { font-variant-numeric: tabular-nums; min-width: 70px; text-align: right; }
.bcat { min-width: 90px; color: var(--ink-2); }
.bseries { margin-left: auto; font-size: .8rem; color: var(--muted); }
.pair-label { font-weight: 600; margin: 10px 0 4px; font-size: .9rem; }

/* --- landing v3: page wash, elevated cards, hero, chips, tables, bar grid ---
   v2 painted white cards on a white page behind hairline borders, so a card
   separated from the page by nothing and the landing page read as one flat
   sheet. The page is now the light wash and each card is a white surface with
   the existing shadow token. Every value below reuses an existing token except
   the two --pos-ink/--neg-ink ink tokens, which exist only so the pills meet
   AA text on a status wash (--pos is 3.4:1, --neg is 3.0:1). */

body { background: var(--surface); }

.card {
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: 1rem;
  box-shadow: var(--shadow);
  padding: 1.5rem;
  margin: 0 0 2.5rem;
}
.card > h2 { font-size: 1.35rem; font-weight: 650; margin: 0 0 .35rem; }
.card > p.sub { color: var(--ink-2); font-size: .95rem; margin: 0 0 1.25rem; max-width: 72ch; }
.card .source { font-size: .78rem; color: var(--ink-2); margin: .75rem 0 0; }
.card .figure-card { border: 0; box-shadow: none; padding: 0; margin: 0 0 1.25rem; background: transparent; }
.card .more { margin: 0 0 1rem; }

.hero { display: grid; grid-template-columns: 7fr 5fr; gap: 1.5rem; align-items: center; }
@media (max-width: 900px) { .hero { grid-template-columns: 1fr; } }
.hero .eyebrow { text-transform: uppercase; letter-spacing: .06em; font-size: .75rem; color: var(--muted); margin: 0 0 .5rem; }
.hero .hero-title { font-size: 1.05rem; font-weight: 600; color: var(--ink-2); margin: 0 0 .25rem; }
.hero .hero-value { font-size: clamp(2.75rem, 6vw, 3.5rem); font-weight: 700; line-height: 1.05; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.hero .hero-line { color: var(--ink-2); font-size: .95rem; margin: .6rem 0 0; max-width: 46ch; }
.hero .basis { display: block; font-size: .78rem; color: var(--ink-2); margin: .6rem 0 0; }
.hero-chart { min-height: 340px; }
.hero-chart .chartbox { min-height: 340px; }
.hero-caption { color: var(--ink-2); font-size: .82rem; margin: .6rem 0 0; max-width: 46ch; }

.delta-pill { display: inline-block; font-size: .95rem; font-weight: 600; padding: .2rem .65rem; border-radius: 999px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.delta-pill.pos { color: var(--pos-ink); background: color-mix(in srgb, var(--pos) 14%, transparent); }
.delta-pill.neg { color: var(--neg-ink); background: color-mix(in srgb, var(--neg) 14%, transparent); }
.delta-pill.dim { color: var(--ink-2); background: var(--petal); }

.chips { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .75rem; margin: 0; }
.chips.wrap { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { .chips { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px) { .chips { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.chip { background: var(--petal); border-radius: .75rem; padding: .8rem .9rem; }
.chip .chip-label { display: block; font-size: .78rem; color: var(--petal-ink); text-transform: uppercase; letter-spacing: .03em; }
.chip .chip-value { display: block; font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; margin: .15rem 0 .35rem; }
.chip .delta-pill { font-size: .8rem; padding: .15rem .5rem; }
.chip .chip-basis { display: block; font-size: .72rem; color: var(--ink-2); margin-top: .35rem; }
.chip .chip-context { display: block; font-size: .72rem; color: var(--ink-2); margin-top: .3rem; line-height: 1.35; }

.says { margin: 0; padding: 0; list-style: none; }
.says li { border-left: 3px solid var(--brand); padding: .1rem 0 .1rem .9rem; margin: 0 0 1.1rem; font-size: 1rem; }
.says li:last-child { margin-bottom: 0; }
.says .cite { display: block; font-size: .78rem; color: var(--ink-2); margin-top: .2rem; }

.agency-preview { width: 100%; border-collapse: collapse; font-size: .85rem; }
.agency-preview caption { caption-side: top; text-align: left; font-size: .85rem; color: var(--ink-2); padding: 0 0 .5rem; }
.agency-preview th, .agency-preview td { border-bottom: 1px solid var(--grid); padding: .45rem .5rem; text-align: left; }
.agency-preview td.num, .agency-preview th.num { text-align: right; font-variant-numeric: tabular-nums; }
.agency-preview tbody tr:hover { background: var(--surface); }

.compliance-tbl { width: 100%; border-collapse: collapse; font-size: .85rem; }
.compliance-tbl th, .compliance-tbl td { border-bottom: 1px solid var(--grid); padding: .45rem .5rem; text-align: left; white-space: nowrap; }
.compliance-tbl td.num, .compliance-tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.compliance-tbl tbody tr:hover { background: var(--surface); }
.compliance-tbl thead th { position: sticky; top: 0; background: var(--page); }

.bar-legend { display: flex; gap: 1.25rem; font-size: .8rem; color: var(--ink-2); margin: 0 0 1rem; }
.bar-legend .swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: .35rem; vertical-align: -1px; }
.bar-row { display: grid; grid-template-columns: 88px 1fr 88px; align-items: center; gap: .6rem; min-height: 26px; }
.bar-track { background: var(--surface); border-radius: 3px; height: 14px; }
.bar-row .bar-end { display: block; height: 14px; border-radius: 3px; min-width: 2px; }
.bar-row .bval { text-align: right; font-variant-numeric: tabular-nums; font-size: .9rem; }
.bar-row .bcat { font-size: .85rem; color: var(--ink-2); white-space: nowrap; }
.pair-measure { font-weight: 650; margin: 1.25rem 0 .4rem; font-size: .95rem; }
.pair-measure:first-of-type { margin-top: 0; }
