/* --- fonts.css --------------------------------------------------------- */
/* Generated by tools/fetch-fonts.mjs — do not edit by hand. */

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/bricolage-grotesque-normal-600-1.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/assets/fonts/bricolage-grotesque-normal-800-2.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/public-sans-normal-400-1.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/public-sans-normal-500-2.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/public-sans-normal-700-3.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-normal-400-1.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-normal-600-2.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --- tokens.css -------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   Design tokens.

   Every colour, size and duration on this site resolves to something here.
   Reach for an existing token before inventing a value; if a new one is
   genuinely needed, add it here rather than inlining it.

   The palette has two halves that must not mix:

   - Neutrals and the one brand colour dress the page.
   - The semantic four (good / mixed / poor / gone) are spent only on meaning:
     a rating, a status, a verdict. If they appear as decoration they stop
     signalling, and signalling is the entire job of this site.
--------------------------------------------------------------------------- */

:root {
  /* --- surface ---------------------------------------------------------- */
  --paper: #f6f8fb;          /* cool near-white; the page */
  --card: #ffffff;           /* raised surfaces */
  --sunk: #eef1f6;           /* table headers, inset panels */
  --rule: #d9e0ea;           /* hairlines */
  --rule-strong: #b9c4d3;

  /* --- text -------------------------------------------------------------- */
  --ink: #141922;            /* body copy and headings */
  --ink-soft: #4d5766;       /* secondary copy */
  /* Darkened from #78838f, which measured 3.8:1 on white — under AA for the
     small sizes this token is actually used at. Now 4.7:1. */
  --ink-faint: #626d7a;      /* captions, table meta */

  /* --- brand ------------------------------------------------------------- */
  /* A deep research blue. One brand colour, held across the whole site. */
  --brand: #2a3a94;
  --brand-deep: #1d2a6e;
  --brand-tint: #eaeefb;
  --brand-ring: #8f9fe0;

  /* --- semantic: reserved for meaning ------------------------------------ */
  --good: #16704f;
  --good-tint: #e2f2ec;
  --mixed: #9a5a00;
  --mixed-tint: #fbeedd;
  --poor: #a52218;
  --poor-tint: #fbe9e7;
  --gone: #646e7b;
  --gone-tint: #eceff3;

  /* --- type -------------------------------------------------------------- */
  --font-display: 'Bricolage Grotesque', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Public Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace;

  /* A fifth-major scale, clamped so it holds together on a phone. */
  --t-xs: 0.75rem;
  --t-sm: 0.875rem;
  --t-base: 1.0rem;
  --t-md: 1.125rem;
  --t-lg: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
  --t-xl: clamp(1.5rem, 1.25rem + 1.2vw, 2rem);
  --t-2xl: clamp(2rem, 1.5rem + 2.4vw, 3.1rem);
  --t-3xl: clamp(2.4rem, 1.7rem + 3.4vw, 4rem);

  --leading-tight: 1.12;
  --leading-snug: 1.3;
  --leading-body: 1.65;

  /* --- space ------------------------------------------------------------- */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;

  /* --- shape ------------------------------------------------------------- */
  --r-sm: 4px;
  --r-md: 8px;
  --r-lg: 14px;
  --r-xl: 22px;

  --shadow-sm: 0 1px 2px rgb(20 25 34 / 0.06), 0 1px 3px rgb(20 25 34 / 0.04);
  --shadow-md: 0 2px 4px rgb(20 25 34 / 0.05), 0 8px 20px rgb(20 25 34 / 0.07);
  --shadow-lg: 0 4px 8px rgb(20 25 34 / 0.06), 0 20px 44px rgb(20 25 34 / 0.10);

  /* --- motion ------------------------------------------------------------ */
  /* Nothing on this site animates linearly. */
  --ease-out: cubic-bezier(0.22, 0.85, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0.02, 0.28, 1);
  --ease-spring: cubic-bezier(0.34, 1.42, 0.52, 1);
  --d-fast: 160ms;
  --d-mid: 280ms;
  --d-slow: 620ms;

  /* --- layout ------------------------------------------------------------ */
  --measure: 68ch;           /* reading column */
  --wide: 1180px;            /* table and index width */
  --gutter: clamp(1rem, 0.5rem + 2.4vw, 2.5rem);
}

/* The one deliberate exception to the light palette: the masthead band and the
   footer sit on the brand colour, so they need inverted tokens. */
.on-brand {
  --ink: #f2f5ff;
  --ink-soft: #c3ccf0;
  --ink-faint: #9aa6d8;
  --rule: #45539f;
  --card: #33429c;
}

/* --- site.css ---------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   SurveysSay

   The site is a register: which survey companies pay, which stalled, which
   closed. So it is dressed like a public record — cool paper, one institutional
   blue, monospaced figures — and the only saturated colour is spent on the
   verdict itself.

   The signature is .gauge: two bars on one 0-5 scale showing what Trustpilot
   and SurveyPolice each say about a panel. They disagree constantly, and the
   disagreement is the most useful thing on the page.
--------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; }

/* --- type ---------------------------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: var(--leading-tight);
  letter-spacing: -0.018em;
  margin: 0 0 var(--s-3);
  text-wrap: balance;
}
h1 { font-size: var(--t-2xl); }
h2 { font-size: var(--t-xl); margin-top: var(--s-7); }
h3 { font-size: var(--t-lg); font-weight: 600; margin-top: var(--s-5); }
h4 { font-size: var(--t-md); font-weight: 600; margin-top: var(--s-5); }

p, ul, ol, blockquote, table { margin: 0 0 var(--s-4); }
li { margin-bottom: var(--s-2); }

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: 0.16em; }
a:hover { color: var(--brand-deep); }

:focus-visible {
  outline: 3px solid var(--brand-ring);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.skip {
  position: absolute; left: -9999px;
  background: var(--brand); color: #fff;
  padding: var(--s-3) var(--s-4); border-radius: 0 0 var(--r-md) 0; z-index: 99;
}
.skip:focus { left: 0; top: 0; }

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

.wrap { width: min(var(--wide), 100% - var(--gutter) * 2); margin-inline: auto; }
.prose { width: min(var(--measure), 100% - var(--gutter) * 2); margin-inline: auto; }
.prose > * + h2 { margin-top: var(--s-7); }

.section { padding-block: var(--s-8); }
.section--sunk { background: var(--sunk); }

/* Curved section transitions rather than a hard full-width rule. */
.section--curve {
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  margin-top: calc(var(--s-6) * -1);
  position: relative;
  background: var(--paper);
}

/* --- masthead ------------------------------------------------------------ */

.masthead {
  background: var(--brand);
  color: #f2f5ff;
  padding-block: var(--s-4);
}
.masthead__bar { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; }

.brandmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.3rem;
  letter-spacing: -0.03em;
  color: #fff;
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 0.12em;
}
.brandmark em { font-style: normal; color: var(--brand-ring); }

.nav { display: flex; gap: var(--s-4); flex-wrap: wrap; margin-left: auto; }
.nav a {
  color: #d7deff; text-decoration: none; font-size: var(--t-sm); font-weight: 500;
  padding: var(--s-1) 0; border-bottom: 2px solid transparent;
  transition: color var(--d-fast) var(--ease-out), border-color var(--d-fast) var(--ease-out);
}
.nav a:hover, .nav a[aria-current='page'] { color: #fff; border-bottom-color: var(--brand-ring); }

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

.hero { background: var(--brand); color: #f2f5ff; padding-block: var(--s-6) var(--s-9); }
.hero h1 { color: #fff; font-size: var(--t-3xl); max-width: 20ch; }
.hero__lede {
  font-size: var(--t-md); color: #c9d3ff; max-width: 58ch; margin-top: var(--s-4);
}
.hero__meta {
  margin-top: var(--s-5); display: flex; gap: var(--s-5); flex-wrap: wrap;
  font-family: var(--font-mono); font-size: var(--t-xs);
  /* Lighter than --brand-ring, which only reached 4.05:1 on the hero. */
  color: #adbaef;
  text-transform: uppercase; letter-spacing: 0.07em;
}
.hero__meta b { color: #fff; font-weight: 600; }

/* --- the gauge: this site's signature ------------------------------------ *
   Two sources, one 0-5 scale, stacked so the gap between them is the message.
   Bar width encodes the score; opacity encodes how much evidence is behind it,
   so a 4.7 from three reviews cannot masquerade as a 4.7 from forty thousand.
-------------------------------------------------------------------------- */

/*
  One grid for the whole gauge, not one per row.

  The rows use `display: contents` so their cells become items of this grid.
  That does two things: the label column sizes itself to the longest label
  instead of a guessed width, and both rows share the same columns so the bars
  line up under each other. A fixed 4.6em column previously clipped
  "Trustpilot" — set in mono at 0.6em per character it needs 6em — and the
  overflowing glyphs painted straight over the bar.
*/
.gauge {
  display: grid;
  grid-template-columns: auto minmax(56px, 1fr) auto;
  align-items: center;
  gap: 4px var(--s-2);
  min-width: 150px;
  font-size: var(--t-xs);
}

.gauge__row { display: contents; }

/*
  The label is a word, not a figure, so it is set in the body face. Mono is
  reserved for the numbers either side of it — that is what makes the scores
  line up, and it is why the label does not belong in it.
*/
.gauge__src {
  color: var(--ink-faint);
  font-family: var(--font-body);
  white-space: nowrap;
}
.gauge__track {
  position: relative; height: 7px; border-radius: 99px;
  background: var(--rule); overflow: hidden;
  min-width: 0; /* let the 1fr column actually shrink inside a table cell */
}
.gauge__fill {
  position: absolute; inset: 0 auto 0 0;
  width: var(--pct, 0%);
  border-radius: 99px;
  background: var(--tone, var(--gone));
  opacity: var(--confidence, 1);
  transform-origin: left center;
}
.gauge__val {
  text-align: right;
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.gauge__none { color: var(--ink-faint); font-style: italic; font-size: var(--t-xs); font-family: var(--font-body); }

/*
  Reveal by animating *from* the empty state, never *to* the filled one.

  An earlier version zeroed the width under `.js` and restored it on
  `.is-shown`. That made the resting state depend on the observer firing, so a
  script error, a blocked file, or a tab that never renders left every bar
  blank — and the bars are the whole point of the page. Inverting it into a
  keyframe means the correct width is the default and the animation is
  decoration on top of it.

  Each bar gets its own duration (set in site.js) so a pair never lands in
  lockstep; two bars arriving together read as one scripted effect, a beat
  apart they read as two measurements.
*/
@keyframes gauge-fill { from { width: 0; } }

.js .gauge.is-shown .gauge__fill {
  animation: gauge-fill var(--dur, 700ms) var(--ease-out);
}

/* --- tone: colour follows goodness, never the raw number ----------------- */
.t-good { --tone: var(--good); }
.t-mixed { --tone: var(--mixed); }
.t-poor { --tone: var(--poor); }
.t-gone { --tone: var(--gone); }

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

.chip {
  display: inline-flex; align-items: center; gap: 0.4em;
  padding: 0.2em 0.62em;
  border-radius: 99px;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  border: 1px solid transparent;
}
.chip::before {
  content: ''; width: 6px; height: 6px; border-radius: 99px; background: currentColor;
  flex: none;
}
.chip--active { color: var(--good); background: var(--good-tint); border-color: #bfe0d3; }
.chip--moved { color: var(--mixed); background: var(--mixed-tint); border-color: #efd6b0; }
.chip--closed { color: var(--poor); background: var(--poor-tint); border-color: #f0c6c1; }
.chip--unverified { color: var(--gone); background: var(--gone-tint); border-color: var(--rule-strong); }
.chip--router { color: var(--poor); background: var(--poor-tint); border-color: #f0c6c1; }

/* --- the comparison table ------------------------------------------------ */

.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  -webkit-overflow-scrolling: touch;
}

.ranking { width: 100%; border-collapse: collapse; font-size: var(--t-sm); min-width: 860px; }

.ranking thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--sunk);
  text-align: left;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap;
}

/* `all: unset` strips the padding too, so the tap area is restored explicitly —
   WCAG 2.2 wants 24px minimum and a bare inline button lands at 20. */
.ranking th button {
  all: unset;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  font: inherit; color: inherit; letter-spacing: inherit;
  min-height: 28px;
  padding-inline: 2px;
}
.ranking th button::after {
  content: '↕'; font-size: 0.85em; opacity: 0.35;
  transition: opacity var(--d-fast) var(--ease-out);
}
.ranking th button:hover::after { opacity: 0.7; }
.ranking th[aria-sort='ascending'] button::after { content: '↑'; opacity: 1; color: var(--brand); }
.ranking th[aria-sort='descending'] button::after { content: '↓'; opacity: 1; color: var(--brand); }

.ranking tbody td {
  padding: var(--s-4);
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
}
.ranking tbody tr:last-child td { border-bottom: 0; }
.ranking tbody tr { transition: background var(--d-fast) var(--ease-out); }
.ranking tbody tr:hover { background: var(--brand-tint); }

.ranking__name {
  font-weight: 700; font-size: var(--t-base); text-decoration: none; color: var(--ink);
  display: inline-flex; align-items: center; min-height: 28px;
}
.ranking__name:hover { color: var(--brand); text-decoration: underline; }
.ranking__row-note { display: block; color: var(--ink-faint); font-size: var(--t-xs); margin-top: 2px; }

.ranking__kind {
  font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint);
  text-transform: uppercase; letter-spacing: 0.05em;
}
.ranking__cash { font-family: var(--font-mono); font-size: var(--t-sm); white-space: nowrap; }
.ranking__cash--none { color: var(--ink-faint); }

/*
  Staggered reveal, same inversion as the gauge: the rows' resting state is
  visible, and `.is-shown` plays them in from below. `both` is needed here so
  the backwards fill holds a row hidden through its own delay — that is what
  makes the cascade read as a cascade rather than a single flash.

  The delay is set per row in site.js and capped there, so a hundred-row table
  still finishes briskly.
*/
@keyframes row-in {
  from { opacity: 0; transform: translateY(6px); }
}
.js .ranking.is-shown tbody tr {
  animation: row-in var(--d-mid) var(--ease-out) both;
  animation-delay: var(--stagger, 0ms);
}

/* Yield: once the reader sorts or filters, stop animating and stay stopped. */
.js .ranking.has-interacted tbody tr { animation: none; }

/* --- filters ------------------------------------------------------------- */

.filters { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-bottom: var(--s-4); align-items: center; }
.filters__label {
  font-family: var(--font-mono); font-size: var(--t-xs); text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--ink-faint); margin-right: var(--s-1);
}
.filter {
  all: unset; cursor: pointer;
  padding: 0.35em 0.8em; border-radius: 99px;
  border: 1px solid var(--rule-strong);
  background: var(--card);
  font-size: var(--t-sm); font-weight: 500; color: var(--ink-soft);
  transition: background var(--d-fast) var(--ease-out), color var(--d-fast) var(--ease-out),
              border-color var(--d-fast) var(--ease-out);
}
.filter:hover { border-color: var(--brand); color: var(--brand); }
.filter[aria-pressed='true'] { background: var(--brand); border-color: var(--brand); color: #fff; }
.filter__n { font-family: var(--font-mono); font-size: var(--t-xs); opacity: 0.7; margin-left: 0.35em; }

.ranking tr[hidden] { display: none; }

.result-count {
  font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint);
  margin-top: var(--s-3);
}

/* --- status banner: the "no longer active" notice ------------------------ */

.banner {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-4);
  align-items: start;
  padding: var(--s-5);
  border-radius: var(--r-lg);
  border: 1px solid;
  margin-bottom: var(--s-6);
}
.banner__icon {
  width: 40px; height: 40px; border-radius: 99px;
  display: grid; place-items: center;
  background: var(--card);
  flex: none;
}
.banner__icon svg { width: 22px; height: 22px; }
.banner h2 {
  font-size: var(--t-lg); margin: 0 0 var(--s-2); font-weight: 800; letter-spacing: -0.01em;
}
.banner p { margin: 0 0 var(--s-2); color: var(--ink-soft); }
.banner p:last-child { margin-bottom: 0; }
.banner__checked {
  font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint);
  letter-spacing: 0.02em;
}
.banner__go {
  display: inline-flex; align-items: center; gap: 0.4em;
  margin-top: var(--s-3); font-weight: 600; text-decoration: none;
  padding: 0.5em 0.95em; border-radius: var(--r-md);
  background: var(--card); border: 1px solid currentColor;
  transition: transform var(--d-fast) var(--ease-out), box-shadow var(--d-fast) var(--ease-out);
}
.banner__go:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.banner__go::after { content: '→'; transition: transform var(--d-fast) var(--ease-out); }
.banner__go:hover::after { transform: translateX(3px); }

.banner--closed { background: var(--poor-tint); border-color: #eec3be; color: var(--poor); }
.banner--moved { background: var(--mixed-tint); border-color: #efd6b0; color: var(--mixed); }
.banner--unverified { background: var(--gone-tint); border-color: var(--rule-strong); color: var(--gone); }
.banner--router { background: var(--poor-tint); border-color: #eec3be; color: var(--poor); }
.banner h2, .banner .banner__go { color: inherit; }

/* --- review page furniture ----------------------------------------------- */

.review-head { padding-block: var(--s-6) var(--s-5); }
.review-head h1 { margin-bottom: var(--s-3); }
.review-head__sub { color: var(--ink-soft); font-size: var(--t-md); max-width: 60ch; }

.factbox {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s-5);
  padding: var(--s-5);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--s-6);
}
.fact dt {
  font-family: var(--font-mono); font-size: var(--t-xs); text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--ink-faint); margin-bottom: var(--s-2);
}
.fact dd { margin: 0; font-weight: 500; }
.fact dd .chip { font-weight: 600; }

.verdict {
  border-left: 3px solid var(--brand);
  padding: var(--s-2) 0 var(--s-2) var(--s-5);
  margin: var(--s-6) 0;
  font-size: var(--t-md);
  color: var(--ink);
}
.verdict strong {
  display: block; font-family: var(--font-mono); font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--brand);
  margin-bottom: var(--s-2); font-weight: 600;
}

.archive-note {
  background: var(--sunk);
  border: 1px dashed var(--rule-strong);
  border-radius: var(--r-md);
  padding: var(--s-4);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  margin: var(--s-7) 0 var(--s-5);
}
.archive-note strong { color: var(--ink); }

/* --- cards / index listings ---------------------------------------------- */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: var(--s-4);
  list-style: none; padding: 0; margin: 0;
}
.card {
  display: flex; flex-direction: column; gap: var(--s-2);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: var(--s-4);
  text-decoration: none;
  color: inherit;
  transition: transform var(--d-fast) var(--ease-out), box-shadow var(--d-fast) var(--ease-out),
              border-color var(--d-fast) var(--ease-out);
}
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--brand-ring); }
.card h3 { margin: 0; font-size: var(--t-md); font-weight: 700; }
.card p { margin: 0; font-size: var(--t-sm); color: var(--ink-soft); }
.card__meta {
  margin-top: auto; padding-top: var(--s-2);
  font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint);
}

/* --- callout / methodology ----------------------------------------------- */

.method {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: var(--s-5);
}
.method summary {
  cursor: pointer; font-weight: 700; font-family: var(--font-display);
  font-size: var(--t-md); list-style: none;
}
.method summary::-webkit-details-marker { display: none; }
.method summary::before {
  content: '+'; display: inline-block; width: 1.2em;
  font-family: var(--font-mono); color: var(--brand);
  transition: transform var(--d-fast) var(--ease-out);
}
.method[open] summary::before { content: '−'; }
.method > *:not(summary) { margin-top: var(--s-4); }
.method p, .method li { font-size: var(--t-sm); color: var(--ink-soft); }

/* --- CTA ----------------------------------------------------------------- */

.cta {
  display: inline-flex; align-items: center; gap: 0.5em;
  background: var(--brand); color: #fff;
  padding: 0.7em 1.3em; border-radius: var(--r-md);
  font-weight: 700; text-decoration: none;
  transition: background var(--d-fast) var(--ease-out), transform var(--d-fast) var(--ease-out),
              box-shadow var(--d-fast) var(--ease-out);
}
.cta:hover {
  background: var(--brand-deep); color: #fff;
  transform: translateY(-2px); box-shadow: var(--shadow-md);
}
.cta:active { transform: translateY(0); }

/* --- prose content ------------------------------------------------------- */

.prose table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.prose th, .prose td { padding: var(--s-2) var(--s-3); border: 1px solid var(--rule); text-align: left; }
.prose th { background: var(--sunk); font-weight: 700; }
.prose blockquote {
  margin: var(--s-5) 0; padding-left: var(--s-5);
  border-left: 3px solid var(--rule-strong); color: var(--ink-soft); font-style: italic;
}
.prose img { border-radius: var(--r-md); margin-block: var(--s-4); }
.prose hr { border: 0; border-top: 1px solid var(--rule); margin: var(--s-7) 0; }
.prose code {
  font-family: var(--font-mono); font-size: 0.9em;
  background: var(--sunk); padding: 0.1em 0.35em; border-radius: var(--r-sm);
}

/* --- footer -------------------------------------------------------------- */

.footer {
  background: var(--brand-deep);
  color: #c3ccf0;
  padding-block: var(--s-7);
  margin-top: var(--s-9);
  font-size: var(--t-sm);
}
.footer a { color: #fff; }
.footer__cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-5); margin-bottom: var(--s-6);
}
.footer h2 {
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.09em;
  color: #8f9fe0; margin: 0 0 var(--s-3); font-family: var(--font-body); font-weight: 700;
}
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer li { margin-bottom: var(--s-1); }
/* Give the footer links a real tap area rather than a 16px line box. */
.footer li a { display: inline-block; padding-block: var(--s-1); min-height: 24px; }
.footer__fine {
  border-top: 1px solid #3b4a9e; padding-top: var(--s-4);
  font-size: var(--t-xs); color: #9aa6d8; display: flex; gap: var(--s-4);
  flex-wrap: wrap; justify-content: space-between;
}

/* --- utilities ----------------------------------------------------------- */

.eyebrow {
  font-family: var(--font-mono); font-size: var(--t-xs); text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--ink-faint); margin-bottom: var(--s-2);
}
.lede { font-size: var(--t-md); color: var(--ink-soft); max-width: 62ch; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.stack > * + * { margin-top: var(--s-4); }

/* --- responsive ---------------------------------------------------------- */

@media (max-width: 640px) {
  .hero { padding-block: var(--s-5) var(--s-7); }
  .banner { grid-template-columns: 1fr; }
  .factbox { padding: var(--s-4); gap: var(--s-4); }
  .nav { gap: var(--s-3); font-size: var(--t-xs); }
}

/* --- reduced motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  /* Both reveals animate from a hidden state toward the element's own resting
     style, so suppressing them outright leaves the correct thing on screen. */
  .js .gauge.is-shown .gauge__fill,
  .js .ranking.is-shown tbody tr { animation: none; }
}

/* --- print --------------------------------------------------------------- */

@media print {
  .masthead, .footer, .filters, .skip { display: none; }
  body { background: #fff; }
  .ranking { min-width: 0; font-size: 10pt; }
}
