/* =========================================================================
   Tsoden Design System v4 — "living product"
   Single source of truth for every surface: site pages, guides, legal,
   generated reports. Nothing may re-declare these tokens locally — the old
   per-file <style> copies are exactly what caused the drift DESIGN.md warns
   about. Import with:  <link rel="stylesheet" href="/assets/tsoden.css">
   ========================================================================= */

/* ---------------------------------------------------------------- tokens */
:root {
  color-scheme: light;

  /* ink ramp — cool near-black, reads as "product", not "beige report" */
  --ink:        #0E1116;
  --ink-2:      #232A34;
  --ink-soft:   #59616F;   /* 6.24:1 on paper */
  --ink-faint:  #68707E;   /* 4.99:1 on paper — captions and axis ticks are body text */

  /* surfaces — warm off-white keeps the human, non-clinical feel */
  --paper:      #FFFFFF;
  --sand:       #F7F5F0;
  --sand-deep:  #EFEBE2;

  --line:       #E6E2DA;
  --line-strong:#D3CEC3;

  /* brand: action / energy.
     Two steps on purpose. --brand fills buttons and must clear 4.5:1 with white
     label text (#D13F0E → 4.74:1); --brand-vivid is the louder orange, used only
     for marks that carry no text — rules, numerals, the progress rail, focus.
     Filling a button with the vivid step gave a 3.12:1 label, which axe flags. */
  --brand:       #D13F0E;
  --brand-deep:  #B8380D;
  --brand-vivid: #FF5A1F;
  --brand-tint:  #FFF0E9;
  --brand-ink:   #8F2A05;

  /* verify: carried over from the live cold emails, now the "good" signal */
  --verify:     #0F766E;   /* 5.47:1 */
  --verify-deep:#0A544E;
  --verify-tint:#E6F2F0;

  --warn:       #9E6304;   /* 4.95:1 — #A96A05 sat at 4.42 and failed AA text */
  --warn-tint:  #FBF1DF;
  --risk:       #BE2C1D;   /* 5.89:1 */
  --risk-tint:  #FCECE9;

  /* on the ink band */
  --on-ink:       #F5F2EC;
  --on-ink-soft:  #A8AEB9;
  --on-ink-line:  #2A313C;
  --band:         #0E1116;

  /* type */
  --font-display: 'Bricolage Grotesque', 'General Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body:    'General Sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Consolas, monospace;

  --t-display: clamp(38px, 5.6vw, 72px);
  --t-h1:      clamp(32px, 4.4vw, 54px);
  --t-h2:      clamp(25px, 3.1vw, 38px);
  --t-h3:      clamp(19px, 1.9vw, 23px);
  --t-lead:    clamp(17px, 1.5vw, 20px);
  --t-body:    17px;
  --t-small:   14.5px;
  --t-label:   12px;

  /* space — 4pt base */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px; --s-10: 128px;

  --r-1: 6px; --r-2: 12px; --r-3: 20px; --r-pill: 999px;

  --shadow-1: 0 1px 2px rgba(14,17,22,.05), 0 1px 1px rgba(14,17,22,.04);
  --shadow-2: 0 4px 12px rgba(14,17,22,.06), 0 12px 32px rgba(14,17,22,.07);
  --shadow-3: 0 18px 40px rgba(14,17,22,.10), 0 40px 90px rgba(14,17,22,.12);

  --wrap: 1120px;
  --measure: 66ch;

  --ease: cubic-bezier(.16,1,.3,1);
  --dur: 220ms;

  /* motion — one vocabulary, so a hover on the landing and a hover in the
     funnel are the same gesture. --ease (expo-out: fast off the mark, long
     settle) is the house curve; --ease-spring overshoots ~8% and is reserved
     for state the reader just caused with a tap. Never spring an entrance —
     an overshoot on a page that is still painting reads as jitter, not life. */
  --ease-out:    cubic-bezier(.22,.61,.36,1);
  --ease-spring: cubic-bezier(.34,1.42,.64,1);
  --dur-1: 120ms;   /* echo: hover, press, focus ring */
  --dur-2: 220ms;   /* alias of --dur, kept for reading symmetry */
  --dur-3: 420ms;   /* something travelling across the layout */
  --dur-4: 700ms;   /* an entrance */
  --stagger: 60ms;  /* between siblings in one choreographed group */
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ink: #F2F0EB; --ink-2: #DAD7D0; --ink-soft: #A2A8B4; --ink-faint: #838A97;
  --paper: #14171C; --sand: #0E1116; --sand-deep: #191D24;
  --line: #262B33; --line-strong: #343A44;
  --brand: #FF7A47; --brand-deep: #FF9468; --brand-vivid: #FF7A47; --brand-tint: #2A1810; --brand-ink: #FFB894;
  --verify: #38A99C; --verify-deep: #55C3B6; --verify-tint: #10231F;
  --warn: #D9A03F; --warn-tint: #2A2113;
  --risk: #E4695A; --risk-tint: #2B1512;
  --on-ink: #F2F0EB; --on-ink-soft: #9AA1AD; --on-ink-line: #2B323C; --band: #08090C;
  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 4px 12px rgba(0,0,0,.35), 0 12px 32px rgba(0,0,0,.4);
  --shadow-3: 0 18px 40px rgba(0,0,0,.45), 0 40px 90px rgba(0,0,0,.5);
}

/* Honour the OS setting on every page. The funnel and the landing set
   data-theme from a head script, but the guides, the legal pages and the
   unsubscribe form carry no script — without this they stayed light for a
   reader whose system is dark. Guarded so an explicit "light" choice wins. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ink: #F2F0EB; --ink-2: #DAD7D0; --ink-soft: #A2A8B4; --ink-faint: #838A97;
    --paper: #14171C; --sand: #0E1116; --sand-deep: #191D24;
    --line: #262B33; --line-strong: #343A44;
    --brand: #FF7A47; --brand-deep: #FF9468; --brand-vivid: #FF7A47; --brand-tint: #2A1810; --brand-ink: #FFB894;
    --verify: #38A99C; --verify-deep: #55C3B6; --verify-tint: #10231F;
    --warn: #D9A03F; --warn-tint: #2A2113;
    --risk: #E4695A; --risk-tint: #2B1512;
    --on-ink: #F2F0EB; --on-ink-soft: #9AA1AD; --on-ink-line: #2B323C; --band: #08090C;
    --shadow-1: 0 1px 2px rgba(0,0,0,.4);
    --shadow-2: 0 4px 12px rgba(0,0,0,.35), 0 12px 32px rgba(0,0,0,.4);
    --shadow-3: 0 18px 40px rgba(0,0,0,.45), 0 40px 90px rgba(0,0,0,.5);
  }
  /* same reason as the explicit-attribute rule below: filled buttons only */
  :root:not([data-theme="light"]) .btn:not(.btn--ghost):not(.btn--quiet) { --btn-fg: #0E1116; }
}

/* ------------------------------------------------------------------ base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.65;
  font-weight: 400;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.022em;
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}
h1 { font-size: var(--t-h1); }
/* German and Dutch compounds overrun a 390px viewport on a display face — the
   pages this shipped on measured 9px of horizontal scroll before this rule. */
h1, h2, h3, h4, .lead, .quote blockquote { overflow-wrap: break-word; }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); font-weight: 600; line-height: 1.25; letter-spacing: -.012em; }
p  { margin: 0 0 var(--s-4); }
p:last-child { margin-bottom: 0; }

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

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

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

/* --------------------------------------------------------- layout tools */
.wrap { width: min(var(--wrap), calc(100% - var(--s-6))); margin-inline: auto; }
.wrap--narrow { width: min(760px, calc(100% - var(--s-6))); margin-inline: auto; }
.wrap > *, .split > *, .steps > *, .stats > * { min-width: 0; }

.section { padding-block: clamp(var(--s-7), 7vw, var(--s-9)); }
.section--tight { padding-block: clamp(var(--s-6), 5vw, var(--s-7)); }
.section--sand { background: var(--sand); }
.section--edge { border-top: 1px solid var(--line); }

/* the rhythm rule: alternate a full-bleed sand block against paper so the
   page has a pulse instead of twenty identical white cards on beige */
.band {
  background: var(--band);
  color: var(--on-ink);
  padding-block: clamp(var(--s-7), 6vw, var(--s-8));
}
.band h1, .band h2, .band h3 { color: var(--on-ink); }
.band p { color: var(--on-ink-soft); }
.band a:not(.btn) { color: var(--on-ink); }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand-ink);
  margin: 0 0 var(--s-3);
  display: flex; align-items: center; gap: var(--s-2);
}
.band .eyebrow { color: var(--brand); }
.eyebrow::before {
  content: ""; width: 18px; height: 1px; background: currentColor; opacity: .5; flex: none;
}

.lead { font-size: var(--t-lead); line-height: 1.55; color: var(--ink-soft); max-width: var(--measure); }
.small { font-size: var(--t-small); color: var(--ink-soft); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums lining-nums; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------- topbar */
.topbar {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line);
}
.topbar__inner { min-height: 64px; display: flex; align-items: center; gap: var(--s-5); }
.brand {
  font-family: var(--font-display); font-weight: 700; font-size: 20px;
  letter-spacing: -.03em; color: var(--ink); text-decoration: none;
  display: inline-flex; align-items: center; gap: var(--s-2);
}
.brand__mark {
  width: 22px; height: 22px; border-radius: 6px; background: var(--brand);
  display: grid; place-items: center; color: #fff; font-size: 13px; flex: none;
}
.topbar__nav { margin-left: auto; display: flex; align-items: center; gap: var(--s-5); }
.topbar__nav a:not(.btn) {
  color: var(--ink-soft); text-decoration: none; font-size: var(--t-small); font-weight: 500;
}
.topbar__nav a:not(.btn):hover { color: var(--ink); }

/* -------------------------------------------------------------- buttons */
.btn {
  --btn-bg: var(--brand); --btn-fg: #fff; --btn-bd: transparent;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 48px; padding: 0 var(--s-5);
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-bd); border-radius: var(--r-1);
  font: inherit; font-size: 15.5px; font-weight: 600; letter-spacing: -.005em;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* Dark mode lightens the orange for surface contrast, which flips the label:
   white on #FF7A47 is 2.58:1, ink is 7.32:1. FILLED buttons only — applying it
   to every .btn painted the ghost button near-black on a near-black surface
   (~1.1:1) and it disappeared. */
:root[data-theme="dark"] .btn:not(.btn--ghost):not(.btn--quiet) { --btn-fg: #0E1116; }
.btn:hover { --btn-bg: var(--brand-deep); color: var(--btn-fg); transform: translateY(-1px); box-shadow: var(--shadow-1); }
.btn:active { transform: translateY(0); }
.btn--lg { min-height: 56px; font-size: 17px; padding: 0 var(--s-6); }
.btn--ghost { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--line-strong); }
.btn--ghost:hover { --btn-bg: var(--sand); --btn-bd: var(--ink-faint); }
.btn--quiet { --btn-bg: transparent; --btn-fg: var(--ink-soft); --btn-bd: transparent; min-height: 40px; padding: 0 var(--s-3); }
.btn--quiet:hover { --btn-fg: var(--ink); --btn-bg: var(--sand); }
.band .btn--ghost { --btn-fg: var(--on-ink); --btn-bd: var(--on-ink-line); }
.band .btn--ghost:hover { --btn-bg: var(--on-ink-line); }
.btn--onlight-dark { --btn-bg: var(--ink); --btn-fg: var(--paper); }
.btn--onlight-dark:hover { --btn-bg: var(--ink-2); }

/* ---------------------------------------------------- the URL audit form */
/* the single most important control on the site — one field, one verb */
.urlbar { display: flex; gap: var(--s-2); flex-wrap: nowrap; max-width: 560px; }
.urlbar__field {
  flex: 1 1 auto; min-width: 0; height: 56px;
  padding: 0 var(--s-4);
  font: inherit; font-size: 16.5px; color: var(--ink);
  background: var(--paper);
  border: 1.5px solid var(--line-strong); border-radius: var(--r-1);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.urlbar__field::placeholder { color: var(--ink-faint); }
.urlbar__field:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 16%, transparent);
}
.urlbar .btn { flex: 0 0 auto; height: 56px; }
.urlbar__note {
  margin: var(--s-3) 0 0; font-size: var(--t-small); color: var(--ink-soft);
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
}
.urlbar__note span { display: inline-flex; align-items: center; gap: 6px; }
.urlbar__note span::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--verify); flex: none;
}

/* form fields (lead capture, legal forms) */
.field { display: grid; gap: var(--s-2); }
.field > label { font-size: var(--t-small); font-weight: 600; color: var(--ink); }
.field input, .field select, .field textarea {
  width: 100%; min-height: 48px; padding: 12px var(--s-4);
  font: inherit; color: var(--ink); background: var(--paper);
  border: 1px solid var(--line-strong); border-radius: var(--r-1);
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 16%, transparent);
}

/* ----------------------------------------------------------- containers */
.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-2); padding: var(--s-5);
}
.card--raised { box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--line) 60%, transparent); }
.card--flat { background: var(--sand); border-color: transparent; }

/* the hero product shot — the one place we allow real depth */
.shot {
  border-radius: var(--r-3); overflow: hidden;
  background: var(--paper); border: 1px solid var(--line);
  box-shadow: var(--shadow-3);
}
.shot__chrome {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 10px var(--s-4); border-bottom: 1px solid var(--line); background: var(--sand);
}
.shot__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line-strong); flex: none; }
.shot__url {
  margin-left: var(--s-2); flex: 1; min-width: 0;
  font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.shot__body { padding: var(--s-5); }

/* ------------------------------------------------------- score & grades */
.score { display: flex; align-items: baseline; gap: var(--s-3); }
.score__num {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600; font-size: clamp(52px, 9vw, 104px); line-height: .86;
  letter-spacing: -.04em; color: var(--ink);
}
.score__den { font-family: var(--font-mono); font-size: 18px; color: var(--ink-faint); }
.score__label {
  font-family: var(--font-mono); font-size: var(--t-label); letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-soft);
}

.meter { height: 8px; border-radius: var(--r-pill); background: var(--sand-deep); overflow: hidden; }
.meter > i { display: block; height: 100%; border-radius: inherit; background: var(--verify); }
.meter--warn > i { background: var(--warn); }
.meter--risk > i { background: var(--risk); }

/* F → A grade rail; the marker is the only moving part */
.grades { display: grid; grid-template-columns: repeat(5, 1fr); gap: 3px; }
.grades > i {
  height: 6px; border-radius: 2px; background: var(--sand-deep);
}
.grades > i[data-on] { background: var(--verify); }
.grades__legend {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-faint); letter-spacing: .1em;
}

/* ------------------------------------------------------- finding / leak */
.finding {
  display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: var(--s-3);
  padding: var(--s-4) 0; border-bottom: 1px solid var(--line);
}
.finding:last-child { border-bottom: 0; }
.finding__n {
  font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  color: var(--brand-ink); padding-top: 2px;
}
.finding__t { font-weight: 600; margin: 0 0 4px; line-height: 1.4; }
.finding__d { margin: 0; font-size: var(--t-small); color: var(--ink-soft); line-height: 1.55; }

/* status rows in the report: found / missing / unverified — three states,
   never a binary tick, because "we couldn't read it" is not "you failed" */
.status { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 500; }
.status__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.status--ok    { color: var(--verify); }  .status--ok    .status__dot { background: var(--verify); }
.status--miss  { color: var(--risk); }    .status--miss  .status__dot { background: var(--risk); }
.status--maybe { color: var(--ink-faint); } .status--maybe .status__dot { background: var(--line-strong); }

/* --------------------------------------------------------------- pieces */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: var(--r-pill);
  background: var(--sand); border: 1px solid var(--line);
  font-size: 13.5px; font-weight: 500; color: var(--ink-soft);
}
.pill--brand { background: var(--brand-tint); border-color: transparent; color: var(--brand-ink); }
.pill--verify { background: var(--verify-tint); border-color: transparent; color: var(--verify-deep); }

.tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 4px 9px; border-radius: var(--r-1);
  background: var(--sand-deep); color: var(--ink-soft);
}

/* big numbers as typographic moments, not icon-in-circle cards */
/* flex, not auto-fit grid: the band sometimes renders two stats (the live
   counter hides itself until the backend returns a real number) and auto-fit
   would leave them stranded in a seven-column track */
.stats { display: flex; flex-wrap: wrap; gap: var(--s-5) var(--s-6); }
.stats > * { flex: 1 1 220px; }
/* display face, not mono: mono gives the thousands separator its own full cell
   and "1,248" reads as "1 , 248" at large sizes */
.stat__n {
  font-family: var(--font-display); font-variant-numeric: tabular-nums lining-nums;
  font-weight: 700; font-size: clamp(34px, 4vw, 48px); line-height: 1;
  letter-spacing: -.035em; margin: 0 0 var(--s-2);
}
.stat__d { margin: 0; font-size: var(--t-small); color: var(--ink-soft); line-height: 1.5; max-width: 30ch; }
.band .stat__d { color: var(--on-ink-soft); }

/* numbered steps on a single rule — replaces the third identical card grid */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--s-6); counter-reset: step; }
.step { counter-increment: step; border-top: 2px solid var(--ink); padding-top: var(--s-4); }
.step::before {
  content: counter(step, decimal-leading-zero);
  display: block; font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  color: var(--brand-vivid); letter-spacing: .1em; margin-bottom: var(--s-3);
}
.step h3 { margin: 0 0 var(--s-2); }
.step p { margin: 0; font-size: var(--t-small); color: var(--ink-soft); }

/* asymmetric split — the antidote to endless 3-up grids */
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(var(--s-6), 5vw, var(--s-8)); align-items: center; }
.split--reverse > :first-child { order: 2; }
.split--top { align-items: start; }
/* text-led: give the copy room so a display headline doesn't stack six lines */
.split--wide-left  { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.split--wide-right { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }

.quote { max-width: 22ch; }
.quote blockquote {
  margin: 0 0 var(--s-4);
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(22px, 2.8vw, 32px); line-height: 1.25; letter-spacing: -.02em;
  max-width: 20ch;
}
.quote figcaption { font-size: var(--t-small); color: var(--ink-soft); }
.quote cite { font-style: normal; font-weight: 600; color: var(--ink); display: block; }

/* accordion FAQ — one column, generous, no coloured body text */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: var(--s-5) var(--s-6) var(--s-5) 0;
  font-size: clamp(17px, 1.6vw, 19px); font-weight: 600; letter-spacing: -.01em;
  position: relative; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 6px; top: 50%;
  width: 11px; height: 11px; margin-top: -7px;
  border-right: 1.5px solid var(--ink-faint); border-bottom: 1.5px solid var(--ink-faint);
  transform: rotate(45deg); transition: transform var(--dur) var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -3px; }
.faq details > div { padding: 0 var(--s-6) var(--s-5) 0; color: var(--ink-soft); max-width: var(--measure); }
.faq details > div p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- table */
.table { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.table th {
  text-align: left; font-family: var(--font-mono); font-size: 11.5px; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint);
  padding: 0 var(--s-3) var(--s-2) 0; border-bottom: 1px solid var(--line-strong);
}
.table td { padding: var(--s-3) var(--s-3) var(--s-3) 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.table tr:last-child td { border-bottom: 0; }
.table__scroll { overflow-x: auto; }
.table td, .table th { overflow-wrap: anywhere; }

/* ---------------------------------------------------------------- notes */
.note {
  border-left: 3px solid var(--line-strong); padding: var(--s-2) 0 var(--s-2) var(--s-4);
  color: var(--ink-soft); font-size: var(--t-small);
}
.note--warn { border-color: var(--warn); background: var(--warn-tint); border-radius: 0 var(--r-1) var(--r-1) 0; padding: var(--s-4); }
.note--risk { border-color: var(--risk); background: var(--risk-tint); border-radius: 0 var(--r-1) var(--r-1) 0; padding: var(--s-4); }
.note--ok   { border-color: var(--verify); background: var(--verify-tint); border-radius: 0 var(--r-1) var(--r-1) 0; padding: var(--s-4); }

/* --------------------------------------------------------------- footer */
.footer { border-top: 1px solid var(--line); padding-block: var(--s-7) var(--s-8); background: var(--sand); }
.footer__grid { display: grid; grid-template-columns: minmax(0, 2fr) repeat(2, minmax(0, 1fr)); gap: var(--s-6); }
.footer h4 {
  font-family: var(--font-mono); font-size: 11.5px; font-weight: 500; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-faint); margin: 0 0 var(--s-3);
}
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.footer a { color: var(--ink-soft); text-decoration: none; font-size: var(--t-small); }
.footer a:hover { color: var(--ink); text-decoration: underline; }
.footer__lang { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); margin-top: var(--s-6); }
.footer__lang a { font-size: 13px; color: var(--ink-faint); }
.footer__lang a[aria-current="page"] { color: var(--ink); font-weight: 600; text-decoration: none; cursor: default; }
.footer__legal { margin-top: var(--s-6); padding-top: var(--s-5); border-top: 1px solid var(--line); font-size: 13px; color: var(--ink-faint); max-width: 78ch; }

/* =========================================================================
   Motion layer
   Motion has exactly one job here: explain a change. Where a thing came from,
   that a number grew to its value, which control the reader just hit. Anything
   that explains nothing gets deleted, not tuned.

   Three standing rules:
     1. An entrance fires once, on scroll-in, and never replays.
     2. Only transform and opacity animate. A transition on width or height
        costs a layout every frame; the two exceptions (.bar-row__fill and
        .progress-rail i) are single elements that own their row.
     3. Every rule below has a reduced-motion escape at the end of the section,
        and the escape is "already arrived", never "the same thing but faster".
   ========================================================================= */

/* ---- entrance: .reveal, driven by the observer in tsoden.js ------------- */
/* The hidden start state sits inside @media (scripting: enabled) on purpose.
   Nothing but our script ever adds .is-in, so without that guard a browser
   with JS off — or any renderer that does not run scripts — would be handed a
   page of invisible text. With the guard it simply gets the finished page. */
.reveal {
  transition: opacity var(--dur-4) var(--ease) var(--rv-delay, 0ms),
              transform var(--dur-4) var(--ease) var(--rv-delay, 0ms);
}
@media screen and (scripting: enabled) {
  .reveal {
    opacity: 0;
    transform: translate3d(var(--rv-x, 0px), var(--rv-y, 14px), 0) scale(var(--rv-s, 1));
  }
}
.reveal.is-in { opacity: 1; transform: none; }
/* No will-change here on purpose. It was tried, along with an .is-settled class
   and a per-element timer to clear it — but nothing ever set the hint, so the
   rule reset a layer that did not exist and the timers did nothing but run.
   Browsers already promote an element for the duration of an opacity/transform
   transition; hinting dozens of them at once costs more than it buys. */

/* Direction variants — pick the one that matches where the thing belongs.
   The default is a short rise, which is the right answer for stacked prose. */
.reveal--far   { --rv-y: 30px; }
.reveal--fade  { --rv-y: 0px; }
.reveal--left  { --rv-x: -24px; --rv-y: 0px; }
.reveal--right { --rv-x: 24px;  --rv-y: 0px; }
.reveal--scale { --rv-y: 8px; --rv-s: .96; }

/* Stagger. tsoden.js numbers the .reveal descendants of a [data-stagger]
   container into --i. The cap is what keeps a twenty-row list from making its
   last row wait a second and a half for something already under the reader's
   eye — past the eighth sibling the delay simply stops growing. */
[data-stagger] .reveal         { --rv-delay: calc(min(var(--i, 0), 8) * var(--stagger)); }
[data-stagger="tight"] .reveal { --rv-delay: calc(min(var(--i, 0), 10) * 40ms); }

/* Choreograph a block without marking up its children. data-stagger-children
   on a container enters every direct child in order — which is what you want
   for a hero or a stat row, where the children are prose and there is no class
   to hang a .reveal on. It exists because the alternative was hand-tagging six
   elements in seven translated copies of the same page and keeping them in
   step forever. Same scripting guard as .reveal: no JS, nothing hidden. */
[data-stagger-children] > * {
  --rv-delay: calc(min(var(--i, 0), 8) * var(--stagger));
  transition: opacity var(--dur-4) var(--ease) var(--rv-delay),
              transform var(--dur-4) var(--ease) var(--rv-delay);
}
@media screen and (scripting: enabled) {
  [data-stagger-children] > * {
    opacity: 0;
    transform: translate3d(0, var(--rv-y, 14px), 0);
  }
}
[data-stagger-children].is-in > * { opacity: 1; transform: none; }

/* ---- press: the echo that says the tap registered ---------------------- */
/* Hover is a hint; press is a receipt. On touch there is no hover at all, so
   this is the only feedback a phone reader gets before the screen changes. */
.btn:active, .opt:active, .backlink:active, .themebtn:active {
  transform: translateY(0) scale(.985);
  transition-duration: var(--dur-1);
}

/* The chosen answer gets the one overshoot on the whole site. It is here
   because this is the single moment the reader decided something. */
.opt.sel::before { animation: ts-pop var(--dur-3) var(--ease-spring) both; }
.tick            { animation: ts-pop var(--dur-3) var(--ease-spring) both; }
@keyframes ts-pop { from { transform: scale(.55); } to { transform: scale(1); } }

/* ---- numbers that count up -------------------------------------------- */
/* Tabular figures are not decoration here: proportional digits change width as
   they tick, and the whole line jitters for the length of the count. */
[data-countup] { font-variant-numeric: tabular-nums; }

/* ---- charts ------------------------------------------------------------ */
/* tsoden.js adds .ts-armed to a chart it is holding at zero, and removes it
   when the chart scrolls into view, so the bar travels to its real length under
   the transition below.

   Why a class and not an inline width: an inline width cannot be overridden by
   a stylesheet, so a printed page kept whatever the script had pinned. A paid
   report came out of the printer with three of its six bars empty and every
   segment of its stacked bar at zero — the reader would have read that as a
   score of nothing. Scoped to "screen", these rules do not exist in print, and
   the bar is drawn at its measured length whether or not anyone scrolled to it.

   The stacked bar needs !important because viz.js writes each segment's
   percentage inline; that is also why releasing it must be a class removal. */
.stackbar > span, .bar-row__fill {
  transform-origin: left center;
  transition: transform var(--dur-4) var(--ease);
}

@media screen and (scripting: enabled) {
  .bars.ts-armed .bar-row__fill,
  .stackbar.ts-armed > span { transform: scaleX(0); }
}

/* The runtime did not arrive.

   Every page carries a one-line load listener that sets this class when
   tsoden.js did not finish — a dropped request on a phone, a blocker, a bad
   deploy. Without it the reader gets a page of invisible text and, on the
   landing, no URL field and no CTA: the whole conversion path, gone silently.
   A timer cannot do this job. It would also fire on a healthy page, revealing
   everything below the fold before the reader ever scrolled to it. */
.ts-no-motion .reveal,
.ts-no-motion [data-stagger-children] > * { opacity: 1 !important; transform: none !important; }
.ts-no-motion .bars.ts-armed .bar-row__fill,
.ts-no-motion .stackbar.ts-armed > span { transform: none !important; }

/* Belt and braces for the one document people actually print. If a browser ever
   applies the "screen" rules above to a print job, this still lands the page in
   its finished state rather than a half-played animation. */
@media print {
  .reveal, [data-stagger-children] > * { opacity: 1 !important; transform: none !important; }
  .bars.ts-armed .bar-row__fill, .stackbar.ts-armed > span { transform: none !important; }
  /* Instantly, not over 700ms. Dropping the screen rules re-targets the
     transition, and a print job started at that moment renders whatever the
     frame holds — bars caught at 60% of their length, sections caught mid-fade.
     Measured on production: 500ms after switching to print media the bars were
     still at scaleX(0.9999). Printing is a snapshot; it must not animate. */
  .reveal, [data-stagger-children] > *,
  .bar-row__fill, .stackbar > span {
    transition: none !important;
    animation: none !important;
  }
}

/* ---- scroll progress --------------------------------------------------- */
/* Was an inline copy on every landing page. This is a utility, not decoration,
   so it keeps working under reduced motion. */
.progress-rail {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 60;
  background: transparent; pointer-events: none;
}
.progress-rail i { display: block; height: 100%; width: 0; background: var(--brand-vivid); }

/* ---- topbar lifts off the page once it is actually floating ------------ */
.topbar { transition: box-shadow var(--dur-3) var(--ease), border-color var(--dur-3) var(--ease); }
.topbar.is-stuck { box-shadow: var(--shadow-1); border-bottom-color: var(--line-strong); }

/* ---- reduced motion: everything is already where it belongs ------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;   /* a stagger is still motion */
  }
  .reveal,
  [data-stagger-children] > * { opacity: 1 !important; transform: none !important; }
  .bars.ts-armed .bar-row__fill, .stackbar.ts-armed > span { transform: none !important; }
  .btn:active, .opt:active, .backlink:active, .themebtn:active { transform: none; }
}

/* ------------------------------------------------------------ responsive */
@media (max-width: 860px) {
  .split, .split--wide-left, .split--wide-right { grid-template-columns: minmax(0, 1fr); gap: var(--s-6); }
  .split--reverse > :first-child { order: 0; }
  .footer__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .footer__grid > :first-child { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  /* brand + one action. The section links are anchors to content that is a
     thumb-flick away on a phone, and keeping them pushed the CTA off-screen. */
  .topbar__nav a:not(.btn) { display: none; }
  /* The label is translated, so its width is not ours to predict: German's
     "Überprüfen Sie meine Website" is 273px against a 390px viewport. Let the
     button wrap instead of nowrap-ing itself off the edge — a two-line button
     is fine, a horizontally scrolling page is not. This has to hold for every
     language we ship, not just the one it was designed in. */
  .topbar .btn {
    white-space: normal;
    line-height: 1.15;
    text-align: center;
    max-width: 58vw;
    padding-inline: var(--s-3);
    font-size: 14.5px;
  }
}
@media (max-width: 560px) {
  :root { --wrap: 100%; }
  .wrap, .wrap--narrow { width: calc(100% - var(--s-5)); }
  .topbar__nav { gap: var(--s-3); }
  .urlbar { max-width: none; flex-wrap: wrap; }
  .urlbar .btn, .urlbar__field { flex: 1 1 100%; }
}

/* =========================================================================
   Data visualisation
   Plain HTML + CSS — no chart library, so a generated report is one file that
   renders offline and prints. Rules held throughout:
     · marks ≤ 24px, 4px rounded data-end, 2px surface gap between fills
     · gridlines are solid hairlines one step off the surface, never dashed
     · text never wears the data colour — a coloured mark sits beside it
     · every value is directly labelled AND present in a <table> twin, so the
       hover tooltip only ever enhances; it never gates a number
     · score-type series wear the status scale (they mean good/bad) and always
       ship an icon or a named band, never colour alone
   ========================================================================= */
.viz { margin: 0 0 var(--s-6); }
.viz__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; margin-bottom: var(--s-4); }
.viz__title { font-size: 16.5px; font-weight: 600; margin: 0; letter-spacing: -.01em; }
.viz__sub { margin: 4px 0 0; font-size: 13.5px; color: var(--ink-soft); max-width: 60ch; }
.viz__legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); font-size: 13px; color: var(--ink-soft); }
.viz__legend span { display: inline-flex; align-items: center; gap: 6px; }
.viz__key { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.viz__note { margin: var(--s-3) 0 0; font-size: 12.5px; color: var(--ink-faint); max-width: 66ch; }

/* the table twin — every chart carries one, collapsed */
.viz__data { margin-top: var(--s-3); }
.viz__data > summary {
  list-style: none; cursor: pointer; font-size: 12.5px; color: var(--ink-faint);
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 0;
}
.viz__data > summary::-webkit-details-marker { display: none; }
.viz__data > summary::before { content: "▸"; font-size: 10px; transition: transform var(--dur) var(--ease); }
.viz__data[open] > summary::before { transform: rotate(90deg); }
.viz__data > summary:hover { color: var(--ink); }

/* ---- hover layer (enhancement only; every value is already labelled) ----
   Declared before the marks: it sets `position: relative` as the tooltip
   anchor, and marks that are absolutely positioned must be able to override
   that. Placed after them it silently un-positioned every dumbbell dot. */
[data-tip] { position: relative; }
[data-tip]:hover::after, [data-tip]:focus-visible::after {
  content: attr(data-tip);
  position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%);
  z-index: 20; padding: 7px 10px; border-radius: var(--r-1);
  background: var(--ink); color: var(--paper);
  font-size: 12.5px; font-weight: 500; line-height: 1.35; white-space: nowrap;
  box-shadow: var(--shadow-2); pointer-events: none;
}

/* ---- horizontal bars: one row per category, value at the tip ------------ */
.bars { display: grid; gap: var(--s-3); }
.bar-row {
  display: grid; grid-template-columns: minmax(90px, 22%) minmax(0, 1fr) 46px;
  align-items: center; gap: var(--s-3);
}
.bar-row__label { font-size: 13.5px; color: var(--ink); line-height: 1.3; }
.bar-row__track {
  position: relative; height: 14px; border-radius: 3px;
  background: var(--sand-deep);
}
.bar-row__fill {
  /* a measured zero still gets a 3px stub: an empty track must not look the same
     as a row we could not read at all */
  position: absolute; inset: 0 auto 0 0; width: var(--v, 0%); min-width: 3px;
  border-radius: 0 4px 4px 0;                 /* square at the baseline */
  background: var(--verify);
  /* the growth is transform-driven — see the chart block in the motion layer */
}
.bar-row[data-band="warn"] .bar-row__fill { background: var(--warn); }
.bar-row[data-band="risk"] .bar-row__fill { background: var(--risk); }
.bar-row[data-band="none"] .bar-row__fill { display: none; }
.bar-row__value {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 600; color: var(--ink); text-align: right;
}
.bar-row__value[data-unknown] { color: var(--ink-faint); font-weight: 400; }

/* ---- one stacked bar: part-to-whole, status scale ---------------------- */
.stackbar { display: flex; height: 20px; border-radius: 4px; overflow: hidden; background: var(--sand-deep); }
.stackbar > span {
  display: block; height: 100%;
  /* 2px of surface does the separating — never a stroke around a segment */
  box-shadow: 2px 0 0 0 var(--paper);
}
.stackbar > span:last-child { box-shadow: none; }
.stackbar__ok   { background: var(--verify); }
.stackbar__miss { background: var(--risk); }
.stackbar__unk  { background: var(--line-strong); }
.stackbar + .viz__legend { margin-top: var(--s-3); }

/* ---- dumbbell: your page against the typical page --------------------- */
.dumbbell { display: grid; gap: var(--s-5); }
.dumb-row { display: grid; grid-template-columns: minmax(90px, 24%) minmax(0, 1fr); align-items: center; gap: var(--s-3); }
.dumb-row__label { font-size: 13.5px; }
.dumb-row__plot { display: block; position: relative; height: 22px; }
.dumb-row__rule { position: absolute; inset: 50% 0 auto 0; height: 1px; background: var(--line); }
.dumb-row__link { position: absolute; top: 50%; height: 2px; margin-top: -1px; background: var(--line-strong); }
.dumb-row__dot {
  position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px;
  border-radius: 50%; box-shadow: 0 0 0 2px var(--paper);   /* surface ring */
}
.dumb-row__dot--them { background: var(--line-strong); }
/* one hue, two shades — the reader's job is the size of the gap, not which
   side is "good". Colouring the you-dot by status made it contradict its own
   legend key, which is worse than no colour at all. */
.dumb-row__dot--you  { background: var(--ink); }
.dumb-row__tip {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 600; color: var(--ink);
  background: var(--paper); padding: 0 4px; white-space: nowrap;
}

/* ---- score scale: where this page sits on 0–100 ----------------------- */
.scale { position: relative; padding-top: 26px; }
.scale__track { display: flex; height: 10px; border-radius: 3px; overflow: hidden; }
.scale__track > span { flex: 1; box-shadow: 2px 0 0 0 var(--paper); }
.scale__track > span:last-child { box-shadow: none; }
.scale__you {
  position: absolute; top: 0; left: var(--at, 50%); transform: translateX(-50%);
  display: grid; justify-items: center; gap: 2px;
}
.scale__you b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 600; background: var(--ink); color: var(--paper);
  padding: 1px 7px; border-radius: 3px; white-space: nowrap;
}
.scale__you i { display: block; width: 2px; height: 10px; background: var(--ink); }
.scale__legend {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; color: var(--ink-faint);
}

/* ---- callout figure: one number that carries a whole section ---------- */
.figure {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-4);
  align-items: center; padding: var(--s-4) 0; border-top: 1px solid var(--line);
}
.figure__n {
  /* proportional figures: tabular-nums makes a big standalone number look loose */
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(38px, 5vw, 54px); line-height: 1; letter-spacing: -.035em;
}
.figure__d { margin: 0; font-size: var(--t-small); color: var(--ink-soft); max-width: 42ch; }
.figure--ok   .figure__n { color: var(--verify); }
.figure--warn .figure__n { color: var(--warn); }
.figure--risk .figure__n { color: var(--risk); }

@media (max-width: 560px) {
  .bar-row { grid-template-columns: minmax(0, 1fr) 46px; }
  .bar-row__track { grid-column: 1 / -1; }
  .dumb-row { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  .bar-row__fill { transition: none; }
}
@media print {
  .viz__data { display: none; }
  .stackbar > span, .scale__track > span { box-shadow: 2px 0 0 0 #fff; }
}

/* =========================================================================
   Legacy token aliases
   quiz.html, src/report.js and the email templates carry inline styles that
   reference the v3 variable names. Aliasing them here means one palette, not
   four — and no find-and-replace sweep through generated HTML that is already
   sitting in customers' inboxes as a link.
   ========================================================================= */
:root {
  --white: var(--paper);
  --muted: var(--ink-soft);
  /* --ink-faint and --warn-tint used to be aliased here to themselves. A custom
     property defined in terms of itself is invalid at computed-value time, so
     both resolved to nothing page-wide: every caption, axis tick and muted line
     that asked for var(--ink-faint) — 24 rules in this file, plus the funnel and
     the report — silently rendered at full ink instead. They are real tokens in
     the block above (and in the dark ramp), so the aliases are simply deleted;
     the surrounding lines alias a v3 name to a DIFFERENT v4 token, which is what
     this block is for. */
  --teal: var(--verify);
  --teal-deep: var(--verify-deep);
  --teal-tint: var(--verify-tint);
  --gold: var(--brand);
  --score-good: var(--verify);
  --score-warn: var(--warn);
  --score-bad: var(--risk);
  --good-tint: var(--verify-tint);
  --bad-tint: var(--risk-tint);
  --r-sm: var(--r-1);
  --r-md: var(--r-1);
  --shadow-sm: var(--shadow-1);
  --shadow-md: var(--shadow-2);
}

/* =========================================================================
   Funnel — the multi-step check on the home page.
   Restyles the existing markup in site/quiz.html; the ids, data-testids and
   the JS behind them are untouched, so the e2e suite still targets the same
   nodes.
   ========================================================================= */
.shell { width: min(760px, calc(100% - var(--s-5))); margin-inline: auto; }
.funnel-nav {
  min-height: 64px; display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); border-bottom: 1px solid var(--line);
}
.langsel {
  border: 1px solid var(--line-strong); border-radius: var(--r-1);
  padding: 8px 10px; font: inherit; font-size: 13.5px; font-weight: 500;
  background: var(--paper); color: var(--ink); cursor: pointer;
}

/* the legacy .button maps onto .btn so both spellings render identically */
.button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 52px; padding: 0 var(--s-5);
  background: var(--brand); color: #fff; border: 1px solid transparent; border-radius: var(--r-1);
  font: inherit; font-size: 16px; font-weight: 600; text-decoration: none; cursor: pointer;
  transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.button:hover { background: var(--brand-deep); color: #fff; transform: translateY(-1px); }
.button:active { transform: translateY(0); }
.button.secondary { background: var(--paper); color: var(--ink); border-color: var(--line-strong); }
.button.secondary:hover { background: var(--sand); color: var(--ink); }
.button[disabled] { opacity: .45; cursor: not-allowed; transform: none; }

.steplabel {
  margin: var(--s-5) 0 0; color: var(--ink-faint);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; font-weight: 500; text-transform: uppercase; letter-spacing: .1em;
}
.steplabel b { font-weight: 600; color: var(--ink-soft); }
.rail { display: flex; gap: 5px; margin: var(--s-2) 0 6px; max-width: 320px; }
/* A done segment fills left-to-right rather than flipping colour: on a
   four-step funnel that growth is the whole of the "you moved" signal. */
.rail i { position: relative; overflow: hidden; flex: 1; height: 4px; border-radius: 2px; background: var(--sand-deep); }
.rail i::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: var(--brand-vivid);
  transform: scaleX(0); transform-origin: left center;
  transition: transform var(--dur-3) var(--ease);
}
.rail i.done::after { transform: scaleX(1); }
.rail[hidden] { display: none; }

.screen { display: none; }
.screen.active { display: block; }

.trustline { color: var(--verify); font-weight: 600; font-size: 13.5px; margin: var(--s-4) 0 2px; }
.statline { margin: var(--s-4) 0 0; font-size: 14.5px; color: var(--ink-soft); font-weight: 500; }
.statline b { color: var(--ink); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 600; }

/* the "what we check" trio — a rule and a numeral, not three boxes */
.vcards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5) var(--s-6); margin: var(--s-7) 0 var(--s-4); }
.vcard { background: none; border: 0; border-top: 2px solid var(--ink); padding: var(--s-4) 0 0; }
.vcard .vnum {
  display: block; font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  color: var(--brand); letter-spacing: .1em; margin-bottom: var(--s-3);
}
.vcard .vicon { display: block; width: 24px; height: 24px; color: var(--ink); margin-bottom: var(--s-3); }
.vcard b { display: block; font-size: 16px; font-weight: 600; margin-bottom: 6px; }
.vcard p { color: var(--ink-soft); font-size: var(--t-small); line-height: 1.5; margin: 0; }
.checks-strip { color: var(--ink-faint); font-size: 13px; line-height: 1.6; margin: var(--s-3) 0 0; }

.miniscale { display: flex; align-items: center; gap: var(--s-3); margin: var(--s-4) 0 0; font-size: 12px; color: var(--ink-faint); font-weight: 500; font-family: var(--font-mono); letter-spacing: .08em; }
.miniscale .bands { display: flex; flex: 1; height: 8px; border-radius: var(--r-pill); overflow: hidden; }
.miniscale .bands span { flex: 1; }

.urlrow { display: flex; gap: var(--s-2); flex-wrap: nowrap; background: none; border: 0; padding: 0; box-shadow: none; }
.urlrow input {
  flex: 1 1 auto; min-width: 0; width: auto; height: 56px; padding: 0 var(--s-4);
  font: inherit; font-size: 16.5px; color: var(--ink); background: var(--paper);
  border: 1.5px solid var(--line-strong); border-radius: var(--r-1); box-shadow: none;
}
.urlrow input:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 16%, transparent);
}
.urlrow .button { flex: 0 0 auto; min-height: 56px; }

/* answers: ruled list, one accent, generous target */
.opts { margin: var(--s-4) 0 var(--s-6); border-top: 1px solid var(--line-strong); counter-reset: opt; }
.opt {
  display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; align-items: center;
  column-gap: var(--s-4); width: 100%; min-height: 56px;
  padding: 20px var(--s-3) 20px var(--s-4);
  border: 0; border-bottom: 1px solid var(--line); border-left: 2px solid transparent;
  background: transparent; color: var(--ink); cursor: pointer; text-align: left;
  font: inherit; font-size: 16.5px; font-weight: 600; line-height: 1.4;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
              transform var(--dur-1) var(--ease-out);
}
.opt::before {
  content: counter(opt, upper-alpha) / ""; counter-increment: opt;
  width: 28px; height: 28px; display: inline-grid; place-items: center;
  border: 1px solid var(--line-strong); border-radius: 50%;
  font-family: var(--font-body); font-size: 12.5px; font-weight: 600; color: var(--ink-faint);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.opt:hover { border-left-color: var(--brand); background: var(--sand); }
.opt:hover::before { border-color: var(--brand); color: var(--brand); }
.opt.sel { border-left-color: var(--brand); background: var(--brand-tint); }
.opt.sel::before { border-color: var(--brand); background: var(--brand); color: #fff; }
.opt .sub { font-weight: 400; color: var(--ink-soft); font-size: 13.5px; line-height: 1.45; max-width: 240px; text-align: right; justify-self: end; }
.backlink { background: none; border: 0; color: var(--ink-soft); font: inherit; font-size: 14.5px; cursor: pointer; padding: var(--s-2) 0; }
.backlink:hover { color: var(--ink); text-decoration: underline; }

/* scanning */
.scan-list { list-style: none; padding: 0; margin: var(--s-5) 0 0; border-top: 1px solid var(--line-strong); }
.scan-list li {
  display: flex; align-items: center; gap: var(--s-3); padding: 14px 2px;
  border-bottom: 1px solid var(--line); color: var(--ink-faint);
  font-size: 15.5px; font-weight: 500; opacity: .5; transition: opacity .25s var(--ease);
}
.scan-list li.on { opacity: 1; color: var(--ink); }
.tick { width: 22px; height: 22px; border-radius: 50%; flex: none; display: grid; place-items: center; background: var(--verify-tint); color: var(--verify); font-size: 12px; font-weight: 600; }
.spin { width: 18px; height: 18px; border: 2px solid color-mix(in srgb, var(--brand) 25%, transparent); border-top-color: var(--brand); border-radius: 50%; animation: ts-rot .7s linear infinite; }
@keyframes ts-rot { to { transform: rotate(360deg); } }

/* results */
.scorecard { display: flex; align-items: center; gap: var(--s-6); flex-wrap: wrap; }
.gauge { position: relative; width: 200px; flex: none; }
.gauge svg { display: block; width: 200px; height: auto; }
.gauge .gnum { position: absolute; inset: auto 0 4px; text-align: center; }
.gauge .gnum strong {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 52px; line-height: 1; font-weight: 600; letter-spacing: -.03em;
}
.gauge .gnum span { color: var(--ink-faint); font-family: var(--font-mono); font-weight: 500; font-size: 15px; }
.scoremeta { flex: 1 1 240px; }
#gaugeArc { transition: stroke-dashoffset 1.2s var(--ease); }

.metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: var(--s-2) 0 var(--s-6); border-top: 1px solid var(--line-strong); }
.metric { background: none; border: 0; border-left: 1px solid var(--line); padding: var(--s-4) var(--s-5) var(--s-4); }
.metric:first-child { border-left: 0; padding-left: 2px; }
.metric b { display: block; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 600; font-size: 30px; letter-spacing: -.02em; }
.metric span { color: var(--ink-soft); font-size: 12.5px; line-height: 1.4; display: block; margin-top: 6px; }
.metric b.up { color: var(--verify); }

.elist { display: grid; border-top: 1px solid var(--line-strong); }
.erow { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: var(--s-3); align-items: start; padding: var(--s-4) 2px; border-bottom: 1px solid var(--line); }
.erow .ic { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-weight: 600; font-size: 12px; }
.erow.ok  .ic { background: var(--verify-tint); color: var(--verify); }
.erow.miss .ic { background: var(--risk-tint); color: var(--risk); }
.erow.unk  .ic { background: var(--sand-deep); color: var(--ink-faint); }
.erow .t { font-weight: 600; font-size: 15.5px; }
.erow .d { color: var(--ink-soft); font-size: 13.5px; line-height: 1.5; margin-top: 3px; }
.erow .ev {
  color: var(--ink); font-size: 13px; font-family: var(--font-mono);
  background: var(--sand); border-left: 2px solid var(--line-strong);
  padding: 6px 10px; border-radius: 0 var(--r-1) var(--r-1) 0; margin-top: var(--s-2);
  overflow-wrap: anywhere;
}
.blocknote { background: var(--risk-tint); border-left: 3px solid var(--risk); border-radius: 0 var(--r-1) var(--r-1) 0; padding: var(--s-4); margin: var(--s-4) 0; color: var(--ink); font-size: 14.5px; line-height: 1.55; }

.acats { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3) var(--s-5); }
.acat-h { display: flex; justify-content: space-between; align-items: baseline; font-size: 13.5px; font-weight: 600; margin-bottom: 5px; }
.acat-h span:last-child { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.acat-t { height: 6px; border-radius: var(--r-pill); background: var(--sand-deep); overflow: hidden; }
.acat-t i { display: block; height: 100%; border-radius: inherit; }

.chart-disclosure { border-top: 1px solid var(--line-strong); margin: 0 0 var(--s-4); }
.chart-disclosure summary { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-4) 2px; font-weight: 600; font-size: 14.5px; color: var(--ink-soft); cursor: pointer; list-style: none; }
.chart-disclosure summary::-webkit-details-marker { display: none; }
.chart-disclosure summary:hover { color: var(--ink); }
.chart-disclosure summary .ct-icon { width: 14px; height: 14px; flex: none; transition: transform var(--dur) var(--ease); }
.chart-disclosure[open] summary .ct-icon { transform: rotate(180deg); }
.chart-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); margin-bottom: 6px; }
.chart-head h3 { margin: 0; font-size: 16px; }
.legend { display: flex; gap: var(--s-4); font-size: 12px; color: var(--ink-soft); font-weight: 500; }
.legend i { display: inline-block; width: 18px; height: 0; border-top: 3px solid; vertical-align: middle; margin-right: 5px; border-radius: 3px; }

/* email gate */
.gate { background: none; border: 0; border-top: 2px solid var(--ink); border-radius: 0; padding: var(--s-6) 0 0; }
.gate .field input { max-width: 420px; }
#leadForm .button { min-width: 280px; }
.packages { margin-top: var(--s-5); border-top: 1px solid var(--line-strong); }
.pkg { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; padding: var(--s-4) 2px; border-bottom: 1px solid var(--line); }
.pkg b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 600; font-size: 22px; }
.pkg .button.secondary { background: none; border: 0; min-height: 44px; padding: 0; color: var(--verify); font-size: 14.5px; text-decoration: underline; text-underline-offset: 3px; }
.pkg .button.secondary:hover { background: none; color: var(--verify-deep); }

.infographic { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-2); padding: var(--s-4) var(--s-5); margin: var(--s-5) 0 var(--s-2); }
.ig-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin-bottom: 4px; }
.ig-head h3 { margin: 0; font-size: 16px; }
.ig-tag { font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; text-transform: uppercase; letter-spacing: .1em; color: var(--ink-faint); border: 1px solid var(--line); border-radius: var(--r-pill); padding: 3px 9px; white-space: nowrap; }
.ig-legend { display: flex; gap: var(--s-4); font-size: 12px; color: var(--ink-soft); font-weight: 500; margin: 2px 0 4px; }
.ig-legend i { display: inline-block; width: 18px; height: 0; border-top: 3px solid; vertical-align: middle; margin-right: 5px; border-radius: 3px; }

@media (max-width: 640px) {
  .vcards { grid-template-columns: minmax(0, 1fr); }
  .metrics { grid-template-columns: minmax(0, 1fr); }
  .metric { border-left: 0; border-bottom: 1px solid var(--line); padding: var(--s-3) 2px; }
  .metric:last-child { border-bottom: 0; }
  .acats { grid-template-columns: minmax(0, 1fr); }
  .urlrow { flex-wrap: wrap; }
  .urlrow input, .urlrow .button { flex: 1 1 100%; }
  #leadForm .button { min-width: 0; width: 100%; }
}
@media (max-width: 560px) {
  .scorecard { justify-content: center; text-align: center; }
  .scoremeta { text-align: center; }
}
@media (max-width: 430px) {
  .opt { grid-template-columns: 28px minmax(0, 1fr); }
  .opt .sub { grid-column: 2; justify-self: start; max-width: none; text-align: left; margin-top: 2px; }
}

/* --------------------------------------------------------------- print */
@media print {
  .topbar, .band .btn, .urlbar { display: none !important; }
  body { background: #fff; color: #000; }
  .card, .shot { box-shadow: none; border-color: #ccc; }
}
