/* SectorTrace public portal: a dense, modern research desk. */

@font-face { font-family: 'Manrope'; src: url('/fonts/manrope-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('/fonts/manrope-600.woff2') format('woff2'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('/fonts/manrope-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Grotesk'; src: url('/fonts/space-grotesk-500.woff2') format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Grotesk'; src: url('/fonts/space-grotesk-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Archivo Narrow'; src: url('/fonts/archivo-narrow-500.woff2') format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Archivo Narrow'; src: url('/fonts/archivo-narrow-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

:root {
  /* Backgrounds */
  --bg-base:        #08111f;
  --bg-surface:     #101d2e;
  --bg-elevated:    #17283d;

  /* Accents */
  --accent-teal:    #21d4d0;
  --accent-amber:   #fbbf24;
  --accent-green:   #4ade80;
  --accent-red:     #fb7185;
  --accent-purple:  #a78bfa;

  /* Text */
  --text-primary:   #f4f8ff;
  --text-secondary: #b2c0d3;
  --text-muted:     #8293aa;

  /* Borders */
  --border-subtle:  #24364d;
  --border-accent:  #38516f;

  /* Semantic */
  --caveat-bg:      rgba(245, 158, 11, 0.08);
  --caveat-border:  rgba(245, 158, 11, 0.40);
  --unverified-bg:  repeating-linear-gradient(45deg,
                      rgba(245, 158, 11, 0.06), rgba(245, 158, 11, 0.06) 4px,
                      transparent 4px, transparent 12px);

  /* Spacing */
  --space-1: 4px;  --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-6: 24px; --space-8: 32px;  --space-12: 48px; --space-16: 64px;

  /* Radii */
  --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-xl: 16px;

  /* Glass */
  --glass-bg:     rgba(22, 27, 34, 0.72);
  --glass-blur:   blur(12px);
  --glass-border: 1px solid rgba(48, 54, 61, 0.60);

  --sans: "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --serif: "Space Grotesk", "Manrope", system-ui, sans-serif;
  --display: "Archivo Narrow", "Space Grotesk", sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html { background: var(--bg-base); overflow-x: clip; }
body {
  margin: 0;
  background: var(--bg-base);
  color: var(--text-primary);
  font: 15px/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.2; margin: 0 0 var(--space-3); }
h1 { font-family: var(--serif); font-size: clamp(32px, 5vw, 56px); font-weight: 700; letter-spacing: -0.045em; }
h2 { font-family: var(--serif); font-size: 22px; font-weight: 700; letter-spacing: -0.03em; }
h3 { font-size: 16px; font-weight: 700; }
p { margin: 0 0 var(--space-3); }
a { color: var(--accent-teal); text-decoration-color: rgba(56, 189, 248, 0.4); }
a:hover { text-decoration-color: currentColor; }
.muted { color: var(--text-secondary); }
.small { font-size: 13px; }
.mono { font-family: var(--mono); font-size: 13px; }
.spacer { flex: 1; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--accent-teal); color: #04121d; padding: var(--space-2) var(--space-4);
}
.skip:focus { left: var(--space-4); top: var(--space-2); }

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

/* --- top bar ------------------------------------------------------------- */

.topbar {
  display: flex; align-items: center; gap: var(--space-6);
  padding: var(--space-3) var(--space-6);
  background: color-mix(in srgb, var(--bg-base) 88%, transparent);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--border-subtle);
  position: sticky; top: 0; z-index: 40;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: var(--space-2); text-decoration: none; color: inherit; }
.brand-mark {
  width: 22px; height: 22px; border-radius: 6px;
  background: linear-gradient(135deg, var(--accent-teal), #4f8cff 52%, var(--accent-amber));
  box-shadow: 0 0 20px rgba(33, 212, 208, .25);
}
.brand-text { font-family: var(--serif); font-size: 18px; letter-spacing: -0.035em; font-weight: 500; }
.brand-text strong { font-weight: 750; }

.mainnav { display: flex; gap: var(--space-1); flex-wrap: wrap; }
.mainnav a {
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-md);
  color: var(--text-secondary); text-decoration: none; font-size: 14px;
  border: 1px solid transparent;
}
.mainnav a:hover { color: var(--text-primary); background: var(--bg-elevated); }
.mainnav a[aria-current="page"] {
  color: var(--text-primary); background: var(--bg-elevated);
  border-color: var(--border-accent); font-weight: 600;
}
.lens-menu { position: relative; align-self: center; }
.lens-menu summary { cursor: pointer; list-style: none; padding: var(--space-2) var(--space-3); border: 1px solid var(--border-accent); border-radius: var(--radius-md); color: var(--accent-amber); font-size: 13px; }
.lens-menu summary::-webkit-details-marker { display: none; }
.lens-menu-panel { position: absolute; z-index: 60; top: calc(100% + 10px); left: 0; display: grid; grid-template-columns: repeat(5, minmax(130px, 1fr)); gap: var(--space-4); width: min(760px, calc(100vw - 32px)); padding: var(--space-4); background: var(--bg-surface); border: 1px solid var(--border-accent); border-radius: var(--radius-md); box-shadow: 0 16px 40px rgba(0,0,0,.35); }
.lens-menu-panel div { display: flex; flex-direction: column; gap: 4px; }
.lens-menu-panel strong, .eyebrow, .finding-kicker { font: 700 13px/1.2 var(--display); letter-spacing: .09em; text-transform: uppercase; color: var(--accent-amber); }
.lens-menu-panel a { color: var(--text-secondary); text-decoration: none; font-size: 13px; }
.lens-menu-panel a:hover { color: var(--text-primary); }

/* De-emphasised on purpose: the operator tools are for whoever runs the
   pipeline, not for the researchers this portal is built for. */
.adminlink {
  font-size: 12.5px; color: var(--text-muted);
  text-decoration: none; padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
}
.adminlink:hover { color: var(--text-secondary); border-color: var(--border-accent); }

/* "Find your council" (W-17): a navigator in the top bar, not a filter.
   Right-aligned with the admin links; the list drops below the input. */
.findcouncil { position: relative; margin-left: auto; }
.findcouncil input { min-width: 190px; }
.findcouncil .typeahead-list { min-width: 260px; right: 0; left: auto; }

/* --- filter bar ---------------------------------------------------------- */

.filterbar {
  display: flex; gap: var(--space-4); align-items: flex-end; flex-wrap: wrap;
  padding: var(--space-3) var(--space-6);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-subtle);
  position: sticky; top: 57px; z-index: 30;
}
.filter { display: flex; flex-direction: column; gap: var(--space-1); }
.filter label { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
.filter-note { font-size: 12.5px; color: var(--text-muted); }
.yearrange { display: flex; align-items: center; gap: var(--space-2); color: var(--text-muted); }
.yearrange input { width: 76px; }

input, select, button, textarea { font: inherit; color: inherit; }
input[type="search"], input[type="number"], input[type="text"], select {
  background: var(--bg-base); border: 1px solid var(--border-accent);
  border-radius: var(--radius-sm); padding: 6px 10px; color: var(--text-primary);
  min-width: 150px;
}

.typeahead { position: relative; }
.typeahead-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 50;
  margin: 0; padding: var(--space-1); list-style: none; max-height: 280px; overflow: auto;
  background: var(--bg-elevated); border: 1px solid var(--border-accent);
  border-radius: var(--radius-md); box-shadow: 0 12px 32px rgba(0,0,0,0.5);
}
.typeahead-list li { padding: 6px 10px; border-radius: var(--radius-sm); cursor: pointer; font-size: 14px; }
.typeahead-list li:hover, .typeahead-list li[aria-selected="true"] { background: var(--bg-surface); }
.typeahead-list .target { color: var(--accent-amber); }

.btn {
  background: var(--bg-elevated); border: 1px solid var(--border-accent);
  color: var(--text-primary); border-radius: var(--radius-sm);
  padding: 6px 12px; cursor: pointer; font-size: 14px;
}
.btn:hover { border-color: var(--accent-teal); }
.btn.ghost { background: none; color: var(--text-secondary); }
.btn.primary { background: var(--accent-teal); border-color: var(--accent-teal); color: #04121d; font-weight: 600; }
.btn[disabled] { opacity: 0.5; cursor: default; }
.btn.tiny { padding: 2px 8px; font-size: 12px; }

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

main { padding: var(--space-8) var(--space-6) var(--space-16); max-width: 1440px; margin: 0 auto; }
.route-lens { display: flex; align-items: center; gap: 10px; margin-bottom: calc(var(--space-4) * -1); color: var(--text-muted); }
.route-lens .eyebrow { color: var(--text-muted); font-size: 11px; }
.route-lens.lens-money .eyebrow, .route-lens.lens-accountability .eyebrow { color: var(--accent-amber); }
main:focus { outline: none; }
.section { margin-bottom: var(--space-12); }

/* Scroll-triggered reveal (components.js's revealOnScroll). `.reveal` is
   only ever added by that JS, immediately before it starts observing --
   never a bare CSS rule on `.section` itself -- so a page that does not
   call it, or a browser without IntersectionObserver, shows every section
   at full opacity by default rather than losing content permanently. */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s ease; }
.reveal.is-visible { opacity: 1; transform: none; }
.section > header { margin-bottom: var(--space-4); }
.section > header p { color: var(--text-secondary); max-width: 76ch; }
.section-action { margin: 0 0 var(--space-4); }

.panel {
  background: var(--bg-surface); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg); padding: var(--space-6); box-shadow: 0 18px 55px rgba(0, 0, 0, .12);
}
.grid { display: grid; gap: var(--space-4); }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); }
.grid.cards { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }
.snapshot-bands { display: grid; gap: var(--space-6); }
.snapshot-band { border-top: 1px solid var(--border-subtle); padding-top: var(--space-4); }
.snapshot-band:first-child { border-top: 0; padding-top: 0; }
.snapshot-band > header { margin-bottom: var(--space-3); }
.snapshot-band h3 { font-size: 15px; margin: 0; }
.snapshot-band header p { margin: var(--space-1) 0 0; color: var(--text-secondary); font-size: 13px; max-width: 68ch; }

/* --- hero ---------------------------------------------------------------- */

.hero { padding: var(--space-12) 0 var(--space-8); }
.hero h1 { max-width: 20ch; }
.hero .lede { font-size: 18px; color: var(--text-secondary); max-width: 68ch; }
.hero .lede strong { color: var(--text-primary); font-weight: 600; }
.hero-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-4); }

/* Overview only: the England region silhouette sits beside the headline on
   wide viewports and drops below it on narrow ones. Every other page's hero
   stays the plain single column above. */
.hero-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 340px); gap: var(--space-8); align-items: center; }
.hero-map { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
.hero-map-svg { width: 100%; height: auto; max-height: 380px; filter: drop-shadow(0 18px 40px rgba(0, 0, 0, .35)); }
.hero-map-svg path { transition: fill-opacity .15s; }
.hero-map-svg path:hover { fill-opacity: 1; stroke: var(--accent-teal); }
.hero-map-caption { text-align: center; max-width: 30ch; }

/* The page-load sequence: hero children rise in, staggered, once. Reduced
   motion is handled by the sitewide `animation-duration: .01ms` override
   below rather than a second code path here. */
.hero-animated > * { opacity: 0; animation: hero-rise .6s ease forwards; }
.hero-animated > *:nth-child(1) { animation-delay: .05s; }
.hero-animated > *:nth-child(2) { animation-delay: .16s; }
.hero-animated > *:nth-child(3) { animation-delay: .27s; }
.hero-animated > *:nth-child(n+4) { animation-delay: .38s; }
@keyframes hero-rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
.hero-kicker { display: flex; align-items: center; gap: 8px; margin-bottom: var(--space-3); color: var(--text-muted); font: 700 13px/1.2 var(--display); letter-spacing: .08em; text-transform: uppercase; }
.lens-badge, .timing-badge { display: inline-flex; align-items: center; width: fit-content; padding: 3px 8px; border: 1px solid var(--border-accent); border-radius: 999px; font: 700 12px/1.2 var(--display); letter-spacing: .06em; text-transform: uppercase; }
.lens-accountability, .timing-current { color: var(--accent-amber); border-color: var(--caveat-border); background: var(--caveat-bg); }
.timing-snapshot, .timing-historical { color: var(--text-secondary); background: var(--bg-elevated); }
.timing-live { color: var(--accent-teal); border-color: rgba(33,212,208,.4); }
.evidence-strip { margin: var(--space-6) 0 var(--space-8); padding: var(--space-4); border: 1px solid var(--caveat-border); border-top: 3px solid var(--accent-amber); background: linear-gradient(120deg, var(--bg-surface), var(--bg-elevated)); }
.evidence-strip-head { display: flex; justify-content: space-between; gap: var(--space-4); align-items: flex-start; }
.evidence-strip h2 { margin: 4px 0 0; font-size: 20px; }
.evidence-strip-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); margin: var(--space-4) 0; }
.evidence-strip-grid div { padding: var(--space-3); border-left: 1px solid var(--border-accent); }
.evidence-strip-grid strong { display: block; font: 700 clamp(25px, 3vw, 36px)/1 var(--display); color: var(--text-primary); }
.evidence-strip-grid span { color: var(--text-secondary); font-size: 12px; }
.finding-block { margin: var(--space-4) 0; padding: var(--space-4); border-left: 3px solid var(--accent-amber); background: var(--caveat-bg); }
.finding-kicker { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.finding-kicker .timing-badge, .finding-kicker .badge { font-family: var(--sans); font-size: 11px; letter-spacing: .02em; text-transform: none; }
.finding-text { margin: var(--space-2) 0; color: var(--text-primary); font-weight: 600; max-width: 78ch; }
.finding-caveat, .finding-meta { margin: 0; color: var(--text-secondary); font-size: 13px; }
.finding-meta { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin-top: var(--space-3); }
.briefing-copy { padding: 4px 8px; font-size: 12px; }
.thin-evidence-control { display: inline-flex; align-items: center; gap: 6px; color: var(--text-secondary); font-size: 12px; }
.clipboard-fallback { position: fixed; left: -10000px; }
.read-first {
  margin-top: var(--space-6); max-width: 78ch;
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  background: var(--bg-surface); padding: var(--space-3) var(--space-4);
}
.read-first summary { cursor: pointer; color: var(--accent-teal); font-weight: 650; }
.read-first p { margin: var(--space-3) 0 0; color: var(--text-secondary); font-size: 14px; }
.read-first p + p { margin-top: var(--space-2); }
.share-button { min-width: 126px; }
.section-links { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-5); }
.section-links button { border: 1px solid var(--border-accent); border-radius: 999px; background: transparent; color: var(--text-secondary); cursor: pointer; font-size: 13px; padding: 5px 10px; }
.section-links button:hover, .section-links button:focus-visible { border-color: var(--accent-teal); color: var(--text-primary); }
.takeaway { display: flex; align-items: flex-start; gap: var(--space-3); max-width: 78ch; margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); background: var(--bg-elevated); border-left: 3px solid var(--accent-teal); border-radius: var(--radius-sm); }
.takeaway .badge { flex: 0 0 auto; margin-top: 2px; }
.takeaway p { margin: 0; color: var(--text-secondary); font-size: 14px; }
.context-note { margin: var(--space-3) 0; max-width: 78ch; }
.context-note summary { cursor: pointer; color: var(--accent-teal); font-size: 13px; font-weight: 650; }
.context-note p { margin: var(--space-2) 0 0; color: var(--text-secondary); font-size: 13px; }

.explore-grid { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.explore-card {
  --lens: var(--accent-teal);
  min-height: 148px; display: flex; flex-direction: column; gap: var(--space-2);
  position: relative; padding: var(--space-5); border: 1px solid var(--border-subtle);
  border-top: 3px solid var(--lens);
  border-radius: var(--radius-lg);
  background: linear-gradient(165deg, var(--bg-surface), var(--bg-elevated) 160%);
  color: var(--text-primary);
  text-decoration: none;
  transition: border-color .15s, transform .15s, background .15s, box-shadow .15s;
}
/* Each card's `--lens` custom property is set inline per card (overview.js),
   tracing the same evidence "lens" the route carries elsewhere on the portal
   (the campaign-lens cue under the page h1) — the colour is telling the
   reader something true about the card, not just varying for its own sake. */
.explore-card:hover, .explore-card:focus-visible {
  border-color: var(--lens); background: var(--bg-elevated); color: var(--text-primary);
  transform: translateY(-3px);
  box-shadow: 0 16px 36px -16px var(--lens);
}
.explore-card-lens {
  display: inline-flex; align-items: center; gap: 6px;
  font: 700 11px/1.2 var(--display); letter-spacing: .08em; text-transform: uppercase;
  color: var(--lens);
}
.explore-card-lens::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--lens); }
.explore-card-title { font-size: 17px; font-weight: 700; }
.explore-card-description { color: var(--text-secondary); font-size: 13.5px; max-width: 34ch; }
.explore-card-arrow {
  margin-top: auto; align-self: flex-end;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border-accent); color: var(--lens);
  font-size: 15px; line-height: 1;
  transition: transform .15s, border-color .15s, background .15s;
}
.explore-card:hover .explore-card-arrow, .explore-card:focus-visible .explore-card-arrow {
  transform: translateX(3px); border-color: var(--lens);
  background: color-mix(in srgb, var(--lens) 18%, transparent);
}

.status-key { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin: calc(var(--space-2) * -1) 0 var(--space-4); }
.evidence-status-grid { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: stretch; }
.status-panel { height: 100%; }
.status-panel h3 { margin-bottom: var(--space-2); }
.status-footnote { margin-top: var(--space-4); }
.source-details { margin-top: var(--space-3); }
.source-details summary, .chart-data summary { cursor: pointer; color: var(--accent-teal); font-size: 13px; font-weight: 650; }
.chart-data { margin-top: var(--space-5); }
.chart-data .tablecard { margin-top: var(--space-3); }

.statcard {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: var(--glass-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  position: relative; overflow: hidden;
}
.statcard::before { content: ''; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--accent-teal); opacity: .85; }
.statcard .value {
  font-size: 30px; font-weight: 700; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; line-height: 1.15;
  background: linear-gradient(135deg, var(--accent-teal), var(--accent-amber));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.statcard .value.plain { background: none; color: var(--text-primary); -webkit-text-fill-color: currentColor; }
.statcard .label { font-size: 13px; color: var(--text-secondary); margin-top: var(--space-1); }
.statcard .sub { font-size: 12px; color: var(--text-muted); margin-top: var(--space-1); }
.statcard > .badge { margin-top: var(--space-3); }
.statcard.unverified { background-image: var(--unverified-bg); }
.statcard-actions { margin-top: var(--space-3); }
.statcard-actions .share-button { min-width: 0; padding: 4px 8px; font-size: 12px; }
.evidence-summary-card { cursor: pointer; transition: transform .15s ease, border-color .15s ease; }
.evidence-summary-card:hover, .evidence-summary-card:focus-visible { transform: translateY(-2px); border-color: var(--accent-amber); }
.evidence-modal { width: min(960px, calc(100vw - 32px)); max-width: none; max-height: min(780px, calc(100vh - 32px)); padding: var(--space-6); color: var(--text-primary); background: var(--bg-surface); border: 1px solid var(--border-accent); border-radius: var(--radius-lg); box-shadow: 0 24px 80px rgba(0,0,0,.5); }
.evidence-modal::backdrop { background: rgba(3, 8, 16, .72); backdrop-filter: blur(3px); }
.evidence-modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); }
.evidence-modal-head h2 { margin-top: 4px; }
.evidence-modal .tablecard { margin-top: var(--space-3); }

/* --- caveats ------------------------------------------------------------- */

.caveat-badge {
  background: none; border: none; cursor: pointer; padding: 0 var(--space-1);
  color: var(--accent-amber); font-size: 13px; line-height: 1;
  vertical-align: middle;
}
.caveat-badge:hover { color: var(--text-primary); }
.caveat-body {
  display: block; margin-top: var(--space-2);
  background: var(--caveat-bg); border: 1px solid var(--caveat-border);
  border-radius: var(--radius-sm); padding: var(--space-3);
  font-size: 13px; color: var(--text-primary); max-width: 78ch;
}
.caveat-body[hidden] { display: none; }

/* A caveat that cannot be dismissed, for figures that are routinely
   misread. Pinned open, not a popover. */
.caveat-pinned {
  background: var(--caveat-bg); border-left: 3px solid var(--accent-amber);
  border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4);
  font-size: 14px; margin: var(--space-4) 0; max-width: 88ch;
}
.caveat-pinned strong { color: var(--accent-amber); }

.badge {
  display: inline-block; border-radius: var(--radius-sm); padding: 1px 7px;
  font-size: 11.5px; font-weight: 650; letter-spacing: 0.02em;
  border: 1px solid transparent; vertical-align: middle;
}
.badge.target { background: rgba(245,158,11,0.15); color: var(--accent-amber); border-color: var(--caveat-border); }
.badge.unverified { background: rgba(245,158,11,0.12); color: var(--accent-amber); border-color: var(--caveat-border); }
.badge.good { background: rgba(52,211,153,0.12); color: var(--accent-green); }
.badge.bad { background: rgba(248,113,113,0.12); color: var(--accent-red); }
.badge.neutral { background: var(--bg-elevated); color: var(--text-secondary); border-color: var(--border-accent); }
/* Provider lifecycle: renamed / merged / dissolved. Muted, not alarming --
   a merged comparator is still a valid comparator for its own era. */
.badge.lifecycle { background: var(--bg-elevated); color: var(--text-secondary); border-color: var(--border-accent); text-transform: uppercase; letter-spacing: 0.05em; }
.badge.lifecycle.dissolved { color: var(--accent-red); border-color: rgba(248,113,113,0.35); }
.provider-lifecycle-note { color: var(--text-secondary); font-size: 13px; margin: 2px 0 0; }
.provider-lifecycle-note a { color: var(--text-primary); }

/* --- charts -------------------------------------------------------------- */

.chartwrap { position: relative; min-height: 320px; }

/* Always shown rather than revealed on hover: a control that only exists for
   a mouse is a control a touch reader does not have. Faded until wanted. */
.chart-save {
  position: absolute; top: 0; right: 0; z-index: 5;
  opacity: 0.45; transition: opacity 0.15s;
}
.chartwrap:hover .chart-save, .chart-save:focus-visible { opacity: 1; }
.chart { width: 100%; height: 380px; }
.chart.tall { height: 520px; }
.chart.short { height: 260px; }

.chart-empty, .chart-error {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2); min-height: 260px; text-align: center;
  border: 1px dashed var(--border-accent); border-radius: var(--radius-md);
  color: var(--text-secondary); padding: var(--space-6);
}
.chart-error { border-color: rgba(248,113,113,0.4); color: var(--accent-red); }
.chart-empty code {
  background: var(--bg-base); border: 1px solid var(--border-accent);
  border-radius: var(--radius-sm); padding: 2px 8px; color: var(--accent-teal);
}

.shimmer {
  min-height: 260px; border-radius: var(--radius-md);
  background: linear-gradient(100deg, var(--bg-surface) 20%, var(--bg-elevated) 40%, var(--bg-surface) 60%);
  background-size: 250% 100%; animation: shimmer 1.6s linear infinite;
}
.loading-state { display: grid; gap: var(--space-3); padding: var(--space-4) 0; }
.loading-state p { margin: 0; }
@keyframes shimmer { to { background-position: -250% 0; } }
@media (prefers-reduced-motion: reduce) { .shimmer { animation: none; } }

/* --- provenance ---------------------------------------------------------- */

.provenance { margin-top: var(--space-4); border-top: 1px solid var(--border-subtle); padding-top: var(--space-3); }
.provenance summary { cursor: pointer; font-size: 12.5px; color: var(--text-muted); }
.provenance summary:hover { color: var(--text-secondary); }
.provenance dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-1) var(--space-4); margin: var(--space-3) 0 0; font-size: 12.5px; }
.provenance dt { color: var(--text-muted); }
.provenance dd { margin: 0; overflow-wrap: anywhere; }
.provenance .hash { font-family: var(--mono); }

/* A licence that is not a plain open one gets the caveat colour, because that
   is what it is: a condition on reuse that a reader who skims will miss. */
.provenance .licence-caution { color: var(--accent-amber); margin-top: var(--space-1); }

/* --- tables -------------------------------------------------------------- */

.tablecard { margin-top: var(--space-4); }
.tablecard .toolbar { display: flex; gap: var(--space-2); align-items: center; margin-bottom: var(--space-2); flex-wrap: wrap; }
.tablecard .toolbar h3 { margin: 0; }

/* The row count, and the one case worth colouring: rows the page was not sent.
   "1,000 of 98,636" in amber is the honest half of a table that stops. */
.rowcount { font-size: 12.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.rowcount.truncated { color: var(--accent-amber); }

.tabulator { background: var(--bg-base); border-color: var(--border-subtle); font-size: 13px; }
.tabulator .tabulator-header { background: var(--bg-elevated); border-color: var(--border-subtle); }
.tabulator-row.unverified-row { background-image: var(--unverified-bg); }
.tabulator .tabulator-header-filter input {
  min-width: 0; width: 100%; padding: 2px 6px; font-size: 12px;
}
.tabulator .tabulator-footer { background: var(--bg-elevated); border-color: var(--border-subtle); }

/* --- map ----------------------------------------------------------------- */

.maplayout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.maplayout > * { min-width: 0; }
@media (max-width: 1100px) { .maplayout { grid-template-columns: 1fr; } }
.map { width: 100%; height: 620px; }
.map-workspace { min-width: 0; max-width: 100%; border: 1px solid var(--border-accent); border-radius: var(--radius-lg); overflow: hidden; background: var(--bg-base); box-shadow: 0 20px 55px rgba(0, 0, 0, .22); }
.map-canvas { width: 100%; min-width: 0; height: 620px; }
.map-preview { border-top: 1px solid var(--border-subtle); background: var(--bg-surface); padding: var(--space-4); }
.map-preview h3 { margin-bottom: var(--space-1); }
.map-preview-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-3); }
.maplibregl-popup-content { font: 13px/1.45 var(--sans); color: #142033; padding: 12px 14px; border-radius: 8px; }
.maplibregl-popup-content strong { display: block; font-family: var(--serif); font-size: 15px; margin-bottom: 3px; }
.maplibregl-ctrl-group { border-radius: 8px; overflow: hidden; box-shadow: 0 4px 18px rgba(0,0,0,.2); }
.maplibregl-ctrl button:focus-visible { outline: 3px solid var(--accent-teal); outline-offset: -3px; }
.map-cluster { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 999px; background: #102a43; color: white; border: 2px solid var(--accent-amber); font: 700 13px/1 var(--sans); box-shadow: 0 5px 15px rgba(8, 17, 31, .35); }
.map path { stroke: var(--bg-base); stroke-width: 0.4; cursor: pointer; }
.map path:hover { stroke: var(--text-primary); stroke-width: 1.2; }
.map.cqc-location-map path { fill: var(--bg-elevated) !important; stroke: var(--border-accent); stroke-width: .7; }
.map.cqc-location-map .overlay circle { r: 4.5; }
.map path.nodata { fill: var(--bg-elevated); }
.maptip {
  position: fixed; pointer-events: none; z-index: 60; max-width: 280px;
  background: rgba(13, 17, 23, 0.94); border: 1px solid var(--accent-teal);
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); font-size: 13px;
  box-shadow: 0 8px 28px rgba(0,0,0,0.6);
}
.legend { display: flex; align-items: center; gap: var(--space-2); font-size: 12px; color: var(--text-secondary); margin-top: var(--space-2); }
.legend-scale { height: 10px; flex: 1; border-radius: 999px; border: 1px solid var(--border-subtle); }

.metrictabs { display: flex; gap: var(--space-1); flex-wrap: wrap; margin-bottom: var(--space-3); }
.metrictabs button { border-radius: 999px; }
.metrictabs button[aria-pressed="true"] { background: var(--accent-teal); border-color: var(--accent-teal); color: #04121d; font-weight: 600; }

/* An offer to go and check, not a claim that the register agrees. Styled as a
   quiet aside rather than as a badge for that reason. */
.registers { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: baseline; }
.registerlink { white-space: nowrap; }

/* --- authority page -------------------------------------------------------- */

/* W-12: which evidence kinds the warehouse holds for one authority. A chip
   per kind, filled when rows exist; the empty state must read as "not
   collected" rather than as a zero figure, which is what the pinned caveat
   next to the row says in prose. */
.coverage-ticks { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.coverage-tick {
  display: inline-flex; align-items: baseline; gap: 6px;
  border-radius: 999px; padding: 4px 12px; font-size: 12.5px;
  border: 1px solid var(--border-subtle); color: var(--text-secondary);
}
.coverage-tick.yes { border-color: var(--border-accent); color: var(--text-primary); }
.coverage-tick.yes .tick-mark { color: var(--accent-green); }
.coverage-tick .tick-count { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* W-27: grant and budget sit side by side on the same page and are never
   combined into one axis — the caveat pinned above both is why the section
   exists. */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
@media (max-width: 1100px) { .split { grid-template-columns: 1fr; } }

/* --- compare page (W-11) ---------------------------------------------------- */

/* The selection: a chip per chosen entity, removable, with the URL as the
   state. The chips and the pickers sit in one panel so the reader sees the
   selection and the way to change it together. */
.compare-chips { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 999px; padding: 4px 6px 4px 12px; font-size: 12.5px;
  border: 1px solid var(--border-accent); color: var(--text-primary);
  background: var(--bg-surface);
}
.chip-remove {
  border: 0; background: none; color: var(--text-muted); cursor: pointer;
  font-size: 14px; line-height: 1; padding: 2px 6px; border-radius: 50%;
}
.chip-remove:hover { color: var(--accent-red); background: var(--bg-elevated); }
.compare-pickers { display: flex; gap: var(--space-3); flex-wrap: wrap; }

/* --- geography layers (W-19) ------------------------------------------------ */

/* Each overlay layer is a checkbox with its caveat pinned underneath it the
   moment it is checked — a layer never appears without the warning that
   governs it, which is the finding's own test. */
.layerpanel { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-2) 0; }
.layer-toggle {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 13.5px; color: var(--text-secondary); width: fit-content;
}
.layer-toggle input { accent-color: var(--accent-teal); }
.layer-caveat { margin-left: 24px; }

/* --- timeline ------------------------------------------------------------ */

.timeline { list-style: none; margin: 0; padding: 0 0 0 var(--space-6); border-left: 1px solid var(--border-accent); }
.timeline li { position: relative; padding: 0 0 var(--space-4) var(--space-4); }
.timeline li::before {
  content: ""; position: absolute; left: calc(var(--space-4) * -1 - 5px); top: 7px;
  width: 9px; height: 9px; border-radius: 50%; background: var(--accent-teal);
  box-shadow: 0 0 0 3px var(--bg-base);
}
.timeline li.contract_award::before { background: var(--accent-teal); }
.timeline li.tribunal::before { background: var(--accent-red); }
.timeline li.charity_accounts::before { background: var(--accent-green); }
.timeline li.nhs_job_advert::before { background: var(--accent-amber); }
.timeline .when { font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.timeline .what { font-weight: 600; }
.timeline .detail { color: var(--text-secondary); font-size: 13.5px; }

/* --- pipeline status ----------------------------------------------------- */

.sourcestrip { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.sourcechip {
  display: flex; align-items: center; gap: var(--space-2);
  background: var(--bg-surface); border: 1px solid var(--border-subtle);
  border-radius: 999px; padding: 4px 12px; font-size: 12.5px;
}
  .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); }
  .dot.green { background: var(--accent-green); }
  .dot.amber { background: var(--accent-amber); }

  /* The overview's flow bars (verification funnel and freshness). A plain
   * div track rather than a chart on purpose: a zero renders as the text
   * "0" next to an empty track, which an empty canvas would not say. */
  .flowrows { display: grid; gap: var(--space-3); }
  .flowrow { display: grid; grid-template-columns: minmax(180px, 1fr) 3fr;
    gap: var(--space-3); align-items: center; }
  .flowlabel { display: flex; justify-content: space-between; gap: var(--space-2);
    font-size: 13.5px; }
  .flowvalue { color: var(--text-muted); font-variant-numeric: tabular-nums; }
  .flowbar { height: 10px; border-radius: 5px; background: var(--bg-elevated);
    border: 1px solid var(--border-subtle); overflow: hidden; }
  .flowbar-fill { height: 100%; border-radius: 4px;
    background: linear-gradient(90deg, #1f6feb, #38bdf8); }
  .flowbar-fill.never { background: var(--border-subtle); }
  @media (max-width: 720px) {
    .flowrow { grid-template-columns: 1fr; gap: var(--space-1); }
  }
  
.sitefoot {
  border-top: 1px solid var(--border-subtle); padding: var(--space-8) var(--space-6);
  color: var(--text-secondary); font-size: 13px; max-width: 1440px; margin: 0 auto;
}
.sitefoot-nav { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-bottom: var(--space-6); padding-bottom: var(--space-4); border-bottom: 1px solid var(--border-subtle); }
.sitefoot-nav a { color: var(--text-primary); text-decoration: none; font-weight: 600; }
.sitefoot-nav a:hover { color: var(--accent-teal); }

/* Bootstrap is the layout foundation; these tokens keep its components in
 * the portal's evidence palette. The application rules below remain the
 * authority for the intentionally distinctive SectorTrace cards and tables. */
:root {
  --bs-body-bg: var(--bg-base);
  --bs-body-color: var(--text-primary);
  --bs-secondary-color: var(--text-secondary);
  --bs-border-color: var(--border-subtle);
  --bs-primary: var(--accent-teal);
  --bs-warning: var(--accent-amber);
  --bs-danger: var(--accent-red);
  --bs-success: var(--accent-green);
  --bs-font-sans-serif: var(--sans);
  --bs-border-radius: var(--radius-md);
  --bs-link-color: var(--accent-teal);
}

html[data-bs-theme="light"] {
  --bg-base: #f4f7fb; --bg-surface: #ffffff; --bg-elevated: #e8eef7;
  --text-primary: #132238; --text-secondary: #455a73; --text-muted: #5e7188;
  --border-subtle: #d3dfed; --border-accent: #aebfd3;
  --glass-bg: rgba(255, 255, 255, .88); --glass-border: 1px solid rgba(184,197,208,.8);
  --caveat-bg: rgba(245,158,11,.10); --unverified-bg: repeating-linear-gradient(45deg, rgba(245,158,11,.10), rgba(245,158,11,.10) 4px, transparent 4px, transparent 12px);
}

html[data-bs-theme="light"] .topbar { background: rgba(244,247,251,.92); }
.topbar { min-height: 64px; flex-wrap: nowrap; }
.portal-nav { display: flex; flex: 1 1 auto; min-width: 0; }
.portal-nav .offcanvas-body { display: flex; align-items: center; padding: 0; }
.mainnav { align-items: center; min-width: 0; }
.menu-toggle { display: none; }
.theme-control { display: flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: 12px; white-space: nowrap; }
.theme-control select { min-width: 0; width: auto; padding: 5px 24px 5px 7px; font-size: 12px; }
/* The mobile-only duplicate (see index.html) is hidden here and shown only
   in the sub-900px media queries below, styled to sit in the offcanvas nav
   list rather than the topbar. */
.theme-control-mobile { display: none; }
.search-icon { color: var(--accent-teal); font-size: 20px; line-height: 1; }
.findcouncil { display: flex; align-items: center; gap: 5px; flex: 0 0 auto; }
.findcouncil input { min-width: 175px; }

.filterbar.offcanvas { z-index: 45; }
.filterbar.offcanvas:not(.is-mobile-filter) { position: sticky; top: 64px; visibility: visible; transform: none; width: auto; height: auto; max-width: none; flex-direction: row; }
.filterbar-body { display: flex; gap: var(--space-4); align-items: flex-end; flex-wrap: wrap; padding: var(--space-3) var(--space-6); }
.filterbar .offcanvas-header { display: none; }
.filters-toggle { display: none; }
.filter-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; max-width: 1440px; margin: 16px auto -16px; padding: 0 24px; }
.filter-summary-label { color: var(--text-muted); font-size: 12px; }
.filter-chip, .filter-clear { border: 1px solid var(--border-accent); border-radius: 999px; background: var(--bg-elevated); color: var(--text-primary); padding: 4px 10px; font-size: 12px; cursor: pointer; }
.filter-clear { background: transparent; color: var(--accent-teal); border-color: transparent; }

@media (max-width: 1100px) {
  .topbar { gap: var(--space-3); }
  .mainnav a { padding-left: 8px; padding-right: 8px; }
  .findcouncil input { min-width: 145px; }
}

@media (max-width: 720px) {
  .topbar { min-height: 58px; padding: 8px 16px; }
  .menu-toggle { display: block; order: 4; }
  .portal-nav { position: fixed; flex: 0 0 auto; max-width: 100vw; }
  /* Bootstrap parks a closed offcanvas one viewport to the right. That
     transformed box still increases document scrollWidth in Chromium, so
     remove it from layout until Bootstrap marks it open. */
  .portal-nav:not(.show) { display: none; }
  .portal-nav .offcanvas-body { display: block; padding: 16px; }
  .portal-nav .mainnav { display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 4px; }
  .portal-nav .mainnav a { padding: 10px 12px; font-size: 15px; }
  .portal-nav .lens-menu { order: 0; }
  .portal-nav .lens-menu-panel { position: static; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; max-width: 100%; margin: 4px 0 8px; box-shadow: none; }
  .findcouncil { order: 3; margin-left: auto; }
  .findcouncil input { min-width: 0; width: min(35vw, 150px); }
  /* Was `display: none` outright below 900px, with nothing replacing it --
     a phone reader had no way to override "system" theme at all. Now it
     sits in the offcanvas nav like any other item, below the lens menu,
     with a top rule instead of the desktop left rule. */
  .topbar > .theme-control { display: none; }
  .theme-control-mobile { display: flex; margin: 16px 0 0; padding: 12px 0 0; border-top: 1px solid var(--border-subtle); }
  .filterbar.offcanvas.is-mobile-filter { position: fixed; top: 0; right: 0; bottom: 0; visibility: hidden; transform: translateX(100%); width: min(92vw, 380px); height: 100%; flex-direction: column; }
  .filterbar.offcanvas.is-mobile-filter:not(.show) { display: none; }
  .filterbar.offcanvas.is-mobile-filter.show { visibility: visible; transform: none; }
  .filterbar .offcanvas-header { display: flex; }
  .filterbar-body { display: flex; flex-direction: column; align-items: stretch; padding: 0 24px 24px; }
  .filterbar-body .filter { width: 100%; }
  .filterbar-body input { width: 100%; }
  .filters-toggle { display: inline-flex; margin: 12px 16px 0 auto; }
  .filter-summary { margin: 12px 0 -12px; padding: 0 16px; }
  /* The kbd hint is a desktop affordance; on a phone there is no keyboard to
     name and the topbar's width is better spent on the button's label. */
  .palette-open kbd { display: none; }
  main { padding-top: 24px; }
  .evidence-strip-grid { grid-template-columns: 1fr 1fr; }
  .evidence-strip-head { flex-direction: column; }
}

@media (min-width: 721px) and (max-width: 900px) {
  .topbar { min-height: 58px; padding: 8px 16px; }
  .menu-toggle { display: block; order: 4; }
  .portal-nav { position: fixed; flex: 0 0 auto; max-width: 100vw; }
  .portal-nav:not(.show) { display: none; }
  .portal-nav .offcanvas-body { display: block; padding: 16px; }
  .portal-nav .mainnav { display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 4px; }
  .portal-nav .mainnav a { padding: 10px 12px; font-size: 15px; }
  .portal-nav .lens-menu-panel { position: static; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; max-width: 100%; margin: 4px 0 8px; box-shadow: none; }
  .findcouncil { order: 3; margin-left: auto; }
  .findcouncil input { min-width: 0; width: min(24vw, 170px); }
  .topbar > .theme-control { display: none; }
  .theme-control-mobile { display: flex; margin: 16px 0 0; padding: 12px 0 0; border-top: 1px solid var(--border-subtle); }
}

@media (max-width: 340px) {
  .topbar { gap: 6px; padding-left: 10px; padding-right: 10px; }
  .brand-text { font-size: 16px; }
  .findcouncil input { width: 88px; }
  .palette-open { padding: 6px 8px; }
  .menu-toggle { padding-left: 6px; padding-right: 6px; }
}

.busybar { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 100; overflow: hidden; contain: paint; }
.busybar-run { width: 40%; height: 100%; background: var(--accent-teal); animation: busyslide 1.1s ease-in-out infinite; }
@keyframes busyslide { 0% { transform: translateX(-100%); } 100% { transform: translateX(350%); } }
@media (prefers-reduced-motion: reduce) { .busybar-run { animation: none; width: 100%; opacity: 0.5; } }

@media (max-width: 960px) {
  .hero-split { grid-template-columns: 1fr; }
  .hero-map { max-width: 320px; margin: 0 auto; }
}

@media (max-width: 720px) {
  .topbar { gap: var(--space-3); padding: var(--space-3) var(--space-4); }
  .filterbar { top: 0; position: static; padding: var(--space-3) var(--space-4); }
  main { padding: var(--space-6) var(--space-4) var(--space-12); }
  .hero { padding-top: var(--space-6); }
  .hero-actions .btn { flex: 1 1 auto; text-align: center; }
  .explore-grid, .evidence-status-grid { grid-template-columns: 1fr; }
  .explore-card { min-height: 112px; }
  .chart { height: 300px; }
  .map, .map-canvas { height: 420px; }
}

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

/* No JavaScript. The page is rendered entirely from /api/v1/, so without it
 * the reader gets chrome and nothing else -- on a site whose whole purpose is
 * to be citable. This says where the evidence actually is. */
.noscript {
  max-width: 70ch; margin: 0 auto; padding: var(--space-8) var(--space-6);
  color: var(--text-secondary); font-size: 14.5px; line-height: 1.6;
}
.noscript h1 { color: var(--text-primary); font-size: 20px; margin: 0 0 var(--space-4); }
/* --space-6, not --space-5: there is no --space-5 token, and an undefined
 * custom property makes the whole declaration invalid, so this list had no
 * indent at all. Found while adding the API page's list beside it. */
.noscript ul { padding-left: var(--space-6); }
.noscript li { margin-bottom: var(--space-2); }
.noscript code { font-family: var(--mono); color: var(--accent-teal); }
.noscript strong { color: var(--accent-amber); }

/* The API documentation at /api.
 *
 * A document rather than an application: no script on that page at all, so
 * everything here is layout for prose, and it reuses the portal's tokens so
 * the two do not look like different sites. Measure is capped at ~78ch —
 * these are paragraphs a researcher reads, not a dashboard they scan. */
.apidoc { max-width: 900px; }
.apidoc .lede { font-size: 17px; color: var(--text-secondary); max-width: 72ch; }
.apidoc p, .apidoc li { max-width: 78ch; }
.apidoc h1 { margin-bottom: var(--space-4); }
.apisection { margin: var(--space-12) 0 0; }
.apisection > h2 {
  padding-bottom: var(--space-2); border-bottom: 1px solid var(--border-subtle);
}
.apisection > ul { padding-left: var(--space-6); color: var(--text-secondary); }
.apisection > ul li { margin-bottom: var(--space-2); }

.apiroute {
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  background: var(--bg-surface); padding: var(--space-4) var(--space-6);
  margin-bottom: var(--space-4);
}
.apiroute h3 { margin-bottom: var(--space-2); font-size: 15px; }
.apiroute h3 code { font-size: 15px; color: var(--text-primary); }
.apiroute code { font-family: var(--mono); font-size: 13px; color: var(--accent-teal); }
.apiroute p { color: var(--text-secondary); }

.params { width: 100%; border-collapse: collapse; margin: 0 0 var(--space-3); }
.params th, .params td {
  text-align: left; padding: 6px 10px 6px 0; vertical-align: top;
  border-bottom: 1px solid var(--border-subtle); font-size: 13.5px;
}
.params th { color: var(--text-muted); font-weight: 600; font-size: 12px;
  text-transform: uppercase; letter-spacing: 0.05em; }
.params td:first-child { white-space: nowrap; width: 1%; padding-right: var(--space-4); }

/* What we can say — the claims index (Phase 17).
 *
 * A claim is a statement, so it is set as a quotation rather than as data:
 * the blockquote is the claim, the citations list is what it rests on, and
 * the caveats underneath are the lines that govern it. Nothing here is
 * computed, and the page's job is to make that visible — the reader should
 * see at a glance which parts of the card are the campaign's words and which
 * are the evidence rows behind them. */
.claim {
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  background: var(--bg-surface); padding: var(--space-4) var(--space-6);
  margin-bottom: var(--space-4);
}
.claim-text {
  margin: 0; padding: 0 0 var(--space-2) var(--space-3);
  border-left: 3px solid var(--accent-teal);
  font-size: 17px; line-height: 1.5; color: var(--text-primary);
}
.claim-caveats { margin: var(--space-2) 0; }
.claim-caveats .caveat-pinned { margin-bottom: var(--space-2); }
.claim-citations { margin-top: var(--space-3); }
.claim-citations h3 {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); margin: 0 0 var(--space-2);
}
.claim-citations ul { list-style: none; margin: 0; padding: 0; }
.claim-citations li { padding: var(--space-2) 0; border-top: 1px solid var(--border-subtle); }
.claim-citations li:first-child { border-top: none; }

/* Document-search result snippets (pages/documents.js). The matched terms
   are marked with the portal's amber rather than Bootstrap's default mark
   yellow, and the text colour is pinned dark on both themes: the highlight
   is opaque, so it must carry its own contrast instead of inheriting a body
   colour that goes near-white in dark mode. */
.doc-snippet { margin: var(--space-2) 0; color: var(--text-secondary); }
.doc-snippet mark {
  background: var(--accent-amber); color: #08111f;
  padding: 0 2px; border-radius: var(--radius-sm);
}
.citation-unresolved {
  color: var(--accent-red); font-family: var(--mono); font-size: 12.5px;
  word-break: break-all;
}

/* Coverage is deliberately prose-first: it explains the boundary around the
   evidence before showing recency. The status terms are not controls, so they
   read as a compact reference list on a phone as well as on a wide display. */
.coverage-statuses { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-3); }
.coverage-status { border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--bg-surface); padding: var(--space-3); }
.coverage-status h3 { margin-bottom: var(--space-1); }
.coverage-status p { margin: 0; color: var(--text-secondary); font-size: 13px; }
.freshness-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-3); }
.freshness-item { border-left: 3px solid var(--accent-teal); background: var(--bg-surface); padding: var(--space-3) var(--space-4); }
.freshness-item .small { display: block; color: var(--text-secondary); }

/* --- command palette (js/palette.js) ---------------------------------------
 *
 * One search box for the whole portal. The trigger sits with the council
 * search in the topbar's right-hand group; the overlay is built lazily on
 * first open, so a reader who never opens it pays for the button only.
 * Class names mirror the operator UI's palette so the two feel identical to
 * anyone who uses both; colours come from this stylesheet's own tokens so
 * light and dark themes both hold.
 */
.palette-open {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--bg-base); border: 1px solid var(--border-accent);
  border-radius: var(--radius-sm); color: var(--text-secondary);
  padding: 6px 10px; font-size: 13.5px; cursor: pointer;
}
.palette-open:hover { color: var(--text-primary); border-color: var(--accent-teal); }
.palette-open kbd, .palette-esc {
  font-family: var(--mono); font-size: 11px; color: var(--text-muted);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 0 5px; background: var(--bg-elevated);
}
.palette-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(4, 9, 18, 0.66);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  display: flex; justify-content: center; align-items: flex-start;
  padding: 10vh var(--space-4) var(--space-8);
  overscroll-behavior: contain;
}
.palette-backdrop[hidden] { display: none; }
.palette {
  width: min(680px, 100%);
  background: var(--bg-elevated);
  border: 1px solid var(--border-accent); border-radius: var(--radius-lg);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
  display: flex; flex-direction: column;
  max-height: 70vh; overflow: hidden;
}
.palette-head {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}
.palette-head input {
  flex: 1; min-width: 0; border: 0; background: transparent;
  color: var(--text-primary); font: inherit; font-size: 15px;
  padding: 4px 0; outline: none;
}
.palette-head .search-icon { color: var(--text-muted); font-size: 15px; }
.palette-list { overflow-y: auto; padding: var(--space-2); overscroll-behavior: contain; }
.palette-item {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr) auto;
  gap: 10px; align-items: baseline;
  padding: 7px var(--space-3); cursor: pointer;
  border-left: 2px solid transparent; border-radius: var(--radius-sm);
}
.palette-item.active { background: var(--bg-surface); border-left-color: var(--accent-teal); }
.palette-kind {
  font: 700 10.5px/1.2 var(--display); text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-muted);
}
.palette-label {
  color: var(--text-primary); font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Same highlight treatment as document snippets: an opaque amber chip with
   its own dark text, so the mark is readable on either theme. */
.palette-label mark {
  background: var(--accent-amber); color: #08111f;
  padding: 0 2px; border-radius: var(--radius-sm);
}
.palette-detail { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.palette-empty { padding: var(--space-6) var(--space-3); text-align: center; color: var(--text-muted); font-size: 13.5px; }
.palette-foot {
  display: flex; gap: var(--space-4); padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border-subtle);
  font-size: 12px; color: var(--text-muted);
}
.palette-foot kbd {
  font-family: var(--mono); font-size: 11px; margin-right: 3px;
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 0 4px; background: var(--bg-base);
}

/* Print.

 * This evidence gets printed and carried into rooms, and the failure this
 * guards against is specific: a figure arriving on paper without the caveat
 * that governs it. So caveat bodies are forced open regardless of the
 * disclosure state they were left in on screen, provenance drawers print
 * expanded, and link targets are written out -- a citation whose URL only
 * existed as an href is not a citation once it is on paper.
 *
 * Backgrounds are dropped rather than fought with: the screen palette is dark
 * by design and printing it wastes toner and reads worse.
 */
@media print {
  :root {
    --bg-base: #fff; --bg-surface: #fff; --bg-elevated: #fff;
    --text-primary: #000; --text-secondary: #1a1a1a; --text-muted: #333;
    --border-subtle: #bbb; --border-accent: #888;
    --caveat-bg: transparent; --caveat-border: #000; --unverified-bg: none;
  }
  body { background: #fff; color: #000; }

  /* Navigation, filters and the busy indicator are controls, not content. */
  .topbar, .filterbar, .busybar, .skip, .adminlink, .btn { display: none !important; }

  main { padding: 0; max-width: none; }
  .panel { border: 1px solid #bbb; break-inside: avoid; page-break-inside: avoid; }

  /* The point of the whole block: a caveat that was collapsed on screen is
   * still the caveat that belongs to the number above it. */
  .caveat-body[hidden] { display: block !important; }
  .caveat-badge { display: none; }
  .caveat-pinned { border: 1px solid #000; }
  .provenance[open] > *, .provenance > * { display: revert; }
  .provenance summary { list-style: none; font-weight: 600; color: #000; }

  /* A table's search boxes and page buttons are controls. Its row counter is
     not: "showing 1-25 of 98,636" is the fact that the printed page is a
     fraction of the corpus, which is exactly what must survive printing. */
  .tabulator-header-filter,
  .tabulator-paginator > button,
  .tabulator-paginator > .tabulator-pages,
  .tabulator-paginator > select { display: none !important; }

  /* A link is only a citation on paper if its target is on the paper. */
  .provenance a[href]::after,
  .sitefoot a[href]::after { content: " (" attr(href) ")"; word-break: break-all; }

  /* Charts are canvas and print as an opaque block; the table or the figures
   * beside them carry the same values, and the provenance drawer names the
   * source either way. */
  .chart, .map { display: none; }
  .chart-empty { display: block; border: 1px dashed #888; }
}
