/* ============================================================
   Plagcheck — design tokens
   ============================================================ */
:root {
  --ink: #14161A;
  --ink-2: #161622;
  --ink-soft: #262A30;
  --muted: #525252;
  --muted-2: #9A9A95;
  --line: #E8E7E6;
  --line-2: #EDEDED;
  --paper: #FFFFFF;
  --paper-2: #F7F7F5;
  --paper-3: #F4F7F7;
  --paper-4: #F2F5F4;
  /* Mono-accent palette (client call: no greens). Brand blue carries every
     action and accent; soft periwinkle tints are the second tonality for
     washed surfaces. Neutrals stay neutral. */
  --primary: #3566EF;      /* brand blue — primary action and accent */
  --primary-2: #2450CC;    /* deeper blue: hover endpoint and blue-as-text roles */
  --primary-soft: #E9EEFD; /* pale blue wash for soft fills */
  --secondary: #3566EF;    /* same blue — kept as a slot so variant markup keeps working */
  --secondary-2: #2450CC;
  --secondary-soft: #E9EEFD;
  --secondary-ink: #FFFFFF;
  /* Soft tonality (reference): lavender → ice gradient for washed panels. */
  /* Pastel bloom — the wash under every "soft" surface: the hero panel, the
     CTA banner, the audience tint card. Defined once; it was copy-pasted
     into three rules before. */
  --bloom:
    radial-gradient(52% 72% at 12% 78%, #C7D7FA 0%, rgba(199, 215, 250, 0) 70%),
    radial-gradient(46% 64% at 84% 14%, #CFEDF4 0%, rgba(207, 237, 244, 0) 70%),
    radial-gradient(42% 58% at 63% 88%, #DFD6F9 0%, rgba(223, 214, 249, 0) 72%),
    radial-gradient(70% 90% at 42% 28%, #EDF1F9 0%, rgba(237, 241, 249, 0) 82%),
    #F2F4F8;
  --tint-1: #DDE4FA;
  --tint-2: #D9F0F6;
  --grad-soft: linear-gradient(115deg, var(--tint-1) 0%, #EAF0FC 55%, var(--tint-2) 100%);
  /* Semantic aliases so components read by intent, not by slot number. */
  --accent-blue: var(--secondary);
  --accent-cyan: #47B3DD;  /* reserved for data-viz series, use sparingly */
  --focus-ring: 0 0 0 3px rgba(53,102,239,0.35);
  --primary-ink: #FFFFFF; /* text on the blue primary; auto-contrast JS re-resolves at runtime */
  --btn-primary-fill: var(--primary); --btn-primary-text: var(--primary-ink);
  --btn-secondary-fill: var(--secondary); --btn-secondary-text: var(--secondary-ink);
  --btn-dark-fill: var(--ink); --btn-dark-text: #F4F3F2;
  --btn-outline-fill: var(--surface); --btn-outline-text: var(--text);
  --btn-ghost-fill: transparent; --btn-ghost-text: var(--text);
  --success: #2450CC;
  --alert: #E26A3B;

  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 18px;
  --r-xl: 22px;
  --r-2xl: 28px;
  --r-pill: 999px;

  --shadow-1: 0 7px 30px -12px rgba(15,18,20,0.04);
  --shadow-2: 0 10px 36px -12px rgba(15,18,20,0.06);
  --shadow-3: 0 24px 50px -12px rgba(15,18,20,0.10);
  --shadow-primary: 0 18px 40px -16px rgba(53,102,239,0.42);

  --font-sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --max-w: 1300px;
  --pad-x: clamp(20px, 4vw, 60px);

  /* Gap between a .section-head and the content block beneath it.
     Owned by .section-head (margin-bottom); responsive steps below. */
  --section-head-gap: 60px;
  /* Section-head rhythm — one gap and one measure for every head on the site. */
  --head-gap: 18px;
  --head-measure: 640px;

  /* Gap from the nav down to the top of a hero. ONE value, or the pages drift:
     index used --space-lg (60) while the checker and the detector hard-coded
     72, so their heroes sat 12px lower than the landing's. The nav overlaps the
     first 12px of the section (it is sticky at top:12 but occupies flow from 0),
     so the *visible* gap is this minus 12 → 48px. */
  --hero-top: 60px;

  /* Fluid type-scale. Edit one token here → propagates to every page.
     Each is clamp(min, vw-scaled, max). Mins are tuned so .h-display and
     .h-1 fit a 375px viewport without overflow; smaller scales (body,
     eyebrow, mono) compress only modestly because they already fit.
     Four heading steps, and every heading picks one — no bespoke clamps:
       display  hero h1
       h-1      section titles that own the full row
       h-2      statements set inside a column or panel
       h-3      card titles */
  --fs-display: clamp(36px, 5.6vw, 68px);
  --fs-h-1:     clamp(28px, 3.6vw, 48px);
  --fs-h-2:     clamp(22px, 2.3vw, 30px);
  --fs-h-3:     clamp(18px, 1.8vw, 22px);
  --fs-body-lg: clamp(16px, 1.3vw, 18px);
  --fs-body:    clamp(14px, 1vw, 15px);
  --fs-eyebrow: clamp(11px, 0.85vw, 12px);
  --fs-mono:    clamp(10px, 0.8vw, 11px);
  /* Bespoke 11/11.5px sizes used across kickers, labels, captions —
     tokenised so they collapse to 10px on phone via the clamp floor. */
  --fs-11:      clamp(10px, 0.8vw, 11px);
  --fs-11-5:    clamp(10px, 0.85vw, 11.5px);

  /* Card padding tokens — semantic sizes that auto-compact on phone
     (see @media ≤720px). Components consume these instead of literal
     px values so a single edit propagates everywhere. */
  --pad-snug:  22px;
  --pad-card:  24px;
  --pad-roomy: 28px;
  --pad-xl:    48px;
  /* Big section-internal spacing (between section-head and content,
     between hero/section blocks, etc). Phone override below shrinks
     it proportionally so layouts don't feel airy on small viewports. */
  --space-lg:  60px;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  --bg: #FFFFFF;
  --bg-start: var(--paper-4);
  --bg-stop: 200px;
  --surface: #FFFFFF;
  --surface-2: var(--paper-2);
  --surface-3: var(--paper-3);
  --text: var(--ink);
  --text-muted: var(--muted);
  --text-muted-2: var(--muted-2);
  --border: var(--line);
  --nav-bg: rgba(255,255,255,0.78);
  --code-bg: #0F1116;
  --link: var(--secondary);
  --link-hover: var(--secondary-2);
  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html {
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  background-color: var(--bg);
  background-image: linear-gradient(180deg, var(--bg-start) 0%, var(--bg) var(--bg-stop, 200px));
  background-repeat: no-repeat;
}
body {
  font-family: var(--font-sans);
  color: var(--text);
  font-feature-settings: "ss01", "ss02", "cv11";
  text-wrap: pretty;
}
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background: url("../assets/images/pattern-bg.png") repeat 0 0;
  opacity: 0.7;
  pointer-events: none;
  z-index: -1;
}


a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; }
img { display: block; max-width: 100%; }
ul { list-style: none; margin: 0; padding: 0; }

/* ============================================================
   Type utilities
   ============================================================ */
.mono { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; font-size: var(--fs-mono); color: var(--text); }
.mono.muted { color: var(--text-muted-2); }
/* Eyebrow — a soft blue-tint pill with a brand dot (client pick). Sentence
   case, sans, no mono/caps: the reference's chip shape carried into our
   palette. The dot rhymes with the CTA kicker and the logo mark; it no
   longer pulses (motion inside a pill reads as noise). */
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px 7px 11px; border-radius: 999px;
  background: var(--primary-soft);
  font-family: var(--font-sans); font-weight: 600; font-size: 13px;
  letter-spacing: 0; text-transform: none; color: #1448E3;
  width: fit-content;
}
.eyebrow::before {
  content: ""; width: 7px; height: 7px; border-radius: 999px;
  background: #1448E3; flex-shrink: 0;
}

h1, h2, h3, h4 { margin: 0; letter-spacing: -0.035em; font-weight: 600; }
.h-display {
  font-size: var(--fs-display);
  line-height: 0.96;
  letter-spacing: -0.04em;
}
.h-1 {
  font-size: var(--fs-h-1);
  line-height: 1.04;
  letter-spacing: -0.04em;
}
.h-2 {
  font-size: var(--fs-h-2);
  line-height: 1.18;
  letter-spacing: -0.03em;
}
.h-3 {
  font-size: var(--fs-h-3);
  line-height: 1.22;
  letter-spacing: -0.02em;
}
/* Two-tone headline (reference signature): one phrase of the heading drops
   to the brand blue while the rest stays ink. Applied to a span inside a
   heading — same colour on every surface, plain or pastel (client call). */
.h-muted { color: #1448E3; }
.body-lg { font-size: var(--fs-body-lg); line-height: 1.58; letter-spacing: -0.01em; color: var(--text-muted); }
.body { font-size: var(--fs-body); line-height: 1.55; color: var(--text-muted); }
.body-sm { font-size: 13.5px; line-height: 1.55; color: var(--text-muted); }

.block { display: block; }
.flex-spacer { flex: 1; }
/* Responsive text helpers — swap a full label for a shorter one on phone
   without duplicating components. .phone-only hidden ≥721, shown ≤720;
   .phone-hide is the inverse. */

/* ============================================================
   Layout
   ============================================================ */
.wrap { width: 100%; max-width: var(--max-w); margin: 0 auto; padding-left: var(--pad-x); padding-right: var(--pad-x); }
.section { padding: clamp(72px, 9vw, 120px) 0; }
/* Dark first section extends its dark surface up behind the sticky nav (admin section tool). */

/* ============================================================
   Buttons / chips / cards / pills
   ============================================================ */
/* Schema: pill button with optional .ico circle on the right.
   Sizes: btn-lg (56px) · btn-md (48px, default) · btn-sm (42px) — match Figma 114:3380.
   Colors: btn-dark · btn-primary · btn-outline (gray) · btn-ghost (white).
   Ico-circle rule: contrast vs button bg — dark bg → lime ico, light bg → ink ico. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: transform .25s var(--ease-out), background .2s, color .2s, box-shadow .25s;
  will-change: transform;
}
/* Buttons are plain text pills — the arrow-in-circle .ico was retired
   (client call), and the class is now gone from the markup entirely.

   The button's own padding is symmetric on all four sides; the horizontal
   breathing room lives on the LABEL SPAN, which is why the markup convention
   is that a button's text must be wrapped in a <span>.

   These rules used to read `> span:not(.ico)` — the :not() excluded the icon
   span so it wouldn't get the label's padding. When .ico was pruned as dead,
   the pruner saw the class *inside the :not()* and deleted these rules with
   it, and every button in the site collapsed to the width of its text. The
   :not() is pointless now that .ico doesn't exist, so it's gone. */
.btn,
.btn-md {
  height: 48px;
  padding: 8px;
  font-size: 15px;
}
.btn > span,
.btn-md > span { padding: 0 16px; }
.btn-lg > span { padding: 0 18px; }
.btn-sm > span { padding: 0 14px; }
.btn-xs > span { padding: 0 12px; }
/* Full-width buttons centre their label rather than hugging it. */
.btn-block > span { flex: 1; text-align: center; }
.price-cta.btn-primary > span { flex: 1; text-align: center; }

.btn-lg {
  height: 56px;
  padding: 10px;
  font-size: 16px;
}

.btn-sm {
  height: 42px;
  padding: 6px;
  font-size: 14px;
}

.btn-xs {
  height: 36px;
  padding: 6px;
  font-size: 13px;
}

/* Label — markup convention: button text MUST be wrapped in a <span>,
   e.g. `<span>Label</span>`; the span carries the horizontal padding. */

/* Stretched modifier — button fills its container, the label-span takes the
   remaining width and centers the glyph; the .ico (if present) stays docked
   to the right. Works because the button's outer padding is already symmetric. */
.btn-block { width: 100%; }

/* Color variants */
.btn-primary { background: var(--btn-primary-fill); color: var(--btn-primary-text); }
.btn-primary:hover { background: var(--primary-2); box-shadow: var(--shadow-primary); }
.btn-primary:active { transform: translateY(1px); }
.btn-secondary { background: var(--btn-secondary-fill); color: var(--btn-secondary-text); }
.btn-secondary:hover { background: var(--secondary-2); }
.btn-secondary:active { transform: translateY(1px); }

.btn-dark { background: var(--btn-dark-fill); color: var(--btn-dark-text); }
.btn-dark:hover { background: #000; box-shadow: 0 14px 30px -16px rgba(0,0,0,0.6); }

.btn-outline {
  background: var(--btn-outline-fill); color: var(--btn-outline-text);
  box-shadow: inset 0 0 0 1px var(--border);
}
.btn-outline:hover {
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--text-muted-2);
}

.btn-ghost { background: var(--btn-ghost-fill); color: var(--btn-ghost-text); }
.btn-ghost:hover { background: var(--surface-2); }

.chip {
  display: inline-flex; align-items: center; gap: 8px;
  height: 30px; padding: 0 12px;
  border-radius: 999px; background: var(--surface-2);
  border: 1px solid var(--border);
  font-weight: 500; font-size: 12.5px; color: var(--text);
  transition: background .2s, transform .2s var(--ease-out);
}
.chip:hover { background: var(--surface); transform: translateY(-1px); }

.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--shadow-2); }

.tag-dark {
  display: inline-flex; align-items: center; gap: 8px;
  height: 26px; padding: 0 14px 0 10px; border-radius: 999px;
  background: var(--ink); color: #F4F3F2;
  font-family: var(--font-mono); font-size: var(--fs-11); letter-spacing: 0.04em;
}
.tag-dark::before { content: ""; width: 8px; height: 8px; border-radius: 999px; background: var(--primary); box-shadow: 0 0 12px rgba(53,102,239,0.55); animation: blip 1.6s ease-in-out infinite; }
@keyframes blip {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .65; transform: scale(.85); }
}

.status-pill {
  display: inline-flex; align-items: center; gap: 10px;
  height: 30px; padding: 0 12px;
  border-radius: 999px; background: var(--primary-soft);
  font-family: var(--font-mono); font-weight: 500; font-size: var(--fs-11);
  letter-spacing: 0.04em; color: var(--text); text-transform: uppercase;
}
.status-pill::before { content: ""; width: 8px; height: 8px; border-radius: 999px; background: var(--success); }

.divider { height: 1px; background: var(--border); width: 100%; }

/* Standalone section divider — drop between two sections (or anywhere in <main>)
   without nesting it inside either neighbour. Width matches the CONTENT area
   inside .wrap on every breakpoint (max-w outer minus pad-x on each side):
   - viewport < max-w → width = 100% - 2 * pad-x
   - viewport ≥ max-w → width = max-w - 2 * pad-x   (so it aligns with .wrap's
     inner content, not the outer max-w box)
   Vertical spacing is intentionally 0; surrounding .section padding provides it. */
hr.section-divider, .section-divider {
  display: block;
  border: 0;
  height: 1px;
  background: var(--border);
  margin: 0 auto;
  width: calc(min(100%, var(--max-w)) - 2 * var(--pad-x));
}

/* ============================================================
   Reveal animation (scroll-driven)
   ============================================================ */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); }
.reveal.in { opacity: 1; transform: none; }
.reveal-stagger > * { opacity: 0; transform: translateY(12px); transition: opacity .7s var(--ease-out), transform .7s var(--ease-out); }
.reveal-stagger.in > * { opacity: 1; transform: none; }
.reveal-stagger.in > *:nth-child(1) { transition-delay: 0ms; }
.reveal-stagger.in > *:nth-child(2) { transition-delay: 70ms; }
.reveal-stagger.in > *:nth-child(3) { transition-delay: 140ms; }
.reveal-stagger.in > *:nth-child(4) { transition-delay: 210ms; }
.reveal-stagger.in > *:nth-child(5) { transition-delay: 280ms; }
.reveal-stagger.in > *:nth-child(6) { transition-delay: 350ms; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* ============================================================
   Section heads — the canonical head for every section: an .eyebrow, an
   .h-1 title (two-tone via .h-muted), and an optional right slot holding
   support copy or a control. The head owns the gap to the block beneath
   it, so the block itself must not add a margin-top (see the two resets
   below, for grids that also render under a LEGACY head on inner pages).
   ============================================================ */
.section-head {
  display: grid; grid-template-columns: 1fr auto; gap: 32px; align-items: end;
  margin-bottom: var(--section-head-gap);
}
.section-head-main { display: flex; flex-direction: column; gap: var(--head-gap); max-width: var(--head-measure); }
.section-head-main h2 { max-width: var(--head-measure); }
.section-head-right { max-width: 380px; color: var(--muted); }
/* Right slot holding a control (the pricing tabs) instead of support copy. */
.section-head-right--control { max-width: none; color: inherit; display: inline-flex; align-items: center; gap: 14px; }
.section-head + .faq-grid, .section-head + .pricing-grid { margin-top: 0; }

/* ============================================================
   Logo
   ============================================================ */
.logo { display: inline-flex; align-items: center; color: var(--text); }
.logo-svg { display: block; height: auto; }
.nav .logo-svg { width: var(--logo-w, 160px); height: var(--logo-h, auto); }

/* ============================================================
   Nav
   ============================================================ */
.nav-wrap {
  position: sticky; top: 12px; z-index: 40;
  padding-left: var(--pad-x); padding-right: var(--pad-x);
  width: 100%; pointer-events: none;
}
/* ── SHELVED: nav riding ON the dark hero panel ─────────────────────────────
   Built, working, and reverted at the client's request — the classic sticky
   pill is back on every page. Kept because it is the harder half of the
   reference look and we may want it again.

   TO RESTORE, all four:
     1. uncomment the two CSS blocks below (this one and `.nav.is-over-hero`)
     2. uncomment the `is-over-hero` lines in the nav block of js/script.js
     3. add class="has-text-hero" to <body> on each page using .text-hero
     4. in .text-hero / .text-hero-panel, swap `padding-top: var(--hero-top)`
        back to 12px and restore the panel's asymmetric top padding
        (clamp(104px, 9vw, 132px)) — that space was headroom for the nav.

   Why fixed and not a negative margin: .nav-wrap is sticky, so it occupies
   62px of flow and would push the panel down below it. Fixed takes it out of
   flow entirely and the panel starts at the top of the page on its own, with
   no magic number to keep in sync with the nav's height.

body.has-text-hero .nav-wrap { position: fixed; left: 0; }
   ────────────────────────────────────────────────────────────────────────── */
.nav {
  margin: 0 auto;
  max-width: var(--max-w);
  background: var(--nav-bg);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border: 1px solid var(--border);
  opacity: 0.96;
  border-radius: 999px;
  box-shadow: 0 7px 30px -12px rgba(15,18,20,0.04);
  transition: box-shadow .35s var(--ease-out), border-color .35s, opacity .35s;
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px 10px 22px;
  height: 62px;
  pointer-events: auto;
}
.nav.scrolled {
  opacity: 1;
  box-shadow: 0 14px 40px -18px rgba(15,18,20,0.18);
}

/* ── SHELVED (2/2): the white nav over the dark panel — see the restore note
   above `body.has-text-hero .nav-wrap`.

   Recolouring the pill was not enough: --nav-bg is a 78% white with a backdrop
   blur, so over a photograph it reads as a murky grey rectangle, not a white
   pill. The rules below drop the background, border, shadow and blur outright.
   The logo SVG is ink + brand blue and vanishes on black, so brightness(0)
   invert(1) flattens it to a white silhouette — the same thing a white logo
   file would be, without shipping a second file.

.nav { transition: box-shadow .35s var(--ease-out), border-color .35s, opacity .35s, background .35s; }
.nav.is-over-hero {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  opacity: 1;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.nav.is-over-hero .logo-svg { filter: brightness(0) invert(1); }
.nav.is-over-hero .nav-link { color: #FFFFFF; }
.nav.is-over-hero .nav-link::after { background: #FFFFFF; }
.nav.is-over-hero .btn-ghost { color: #FFFFFF; }
.nav.is-over-hero .btn-ghost:hover { background: rgba(255, 255, 255, 0.14); }
.nav.is-over-hero > button[aria-label="Menu"] { color: #FFFFFF; }
.nav.is-over-hero > button[aria-label="Menu"]:hover { background: rgba(255, 255, 255, 0.14); }
   ────────────────────────────────────────────────────────────────────────── */
.nav-links { display: flex; gap: 28px; }
.nav-link {
  font-weight: 500; font-size: 14px; color: var(--text);
  position: relative; padding: 6px 2px; display: inline-block;
}
.nav-link::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: -2px;
  height: 2px; background: var(--accent-blue); border-radius: 2px;
  transition: right .35s var(--ease-out);
}
.nav-link:hover::after { right: 0; }
.nav-link[aria-current="page"]::after { right: 0; }
.nav-cta { display: flex; gap: 8px; align-items: center; }
/* Burger — direct child of .nav, positioned LEFT of logo on tablet/mobile.
   Hidden on desktop (>1100), shown at ≤1100. */
.nav > button[aria-label="Menu"] {
  display: none;
  width: 36px; height: 36px;
  align-items: center; justify-content: center;
  background: transparent; border-radius: 999px;
  color: var(--text);
  flex-shrink: 0;
  transition: background .2s;
}
.nav > button[aria-label="Menu"]:hover { background: var(--surface-2); }
.nav > button[aria-label="Menu"] { position: relative; }
.nav-menu-icon {
  position: absolute; inset: 0; margin: auto;
  transition: opacity .25s var(--ease-out), transform .25s var(--ease-out);
}
.nav-menu-icon-x { opacity: 0; transform: rotate(-45deg); }
.nav > button[aria-expanded="true"] .nav-menu-icon-burger {
  opacity: 0; transform: rotate(45deg);
}
.nav > button[aria-expanded="true"] .nav-menu-icon-x {
  opacity: 1; transform: rotate(0);
}
/* CTA suffix " — free" — visible on desktop, hidden at ≤1100px when the
   primary button shrinks to btn-xs sizing. */
.nav-cta-suffix { display: inline; }

/* ============================================================
   Mobile / tablet open menu (≤1100px)
   ============================================================ */
.nav-menu {
  position: fixed; inset: 0;
  z-index: 30;                       /* sits below .nav-wrap (z:40) so the X stays clickable */
  background: var(--bg);
  display: none;                     /* hidden on desktop — only shown ≤1100 */
  opacity: 0;
  pointer-events: none;
  transition: opacity .35s var(--ease-out);
}
.nav-menu.is-open { opacity: 1; pointer-events: auto; }
.nav-menu-inner {
  height: 100%;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 100px var(--pad-x) 40px;  /* 100px = nav-top(12) + nav-height(62) + breathing(26) */
  display: flex; flex-direction: column;
  gap: 28px;
  overflow-y: auto;
}
/* The burger menu's "Menu" label borrows .eyebrow for sizing only — it is a
   utility label, not a section eyebrow, so it opts out of the pill. */
.nav-menu-eyebrow {
  padding: 0; background: none; color: var(--text-muted);
  font-family: var(--font-mono); font-weight: 500; font-size: var(--fs-eyebrow);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.nav-menu-eyebrow::before { display: none; }
.nav-menu-links {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column;
}
.nav-menu-link {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 0;
  font-size: clamp(24px, 5.5vw, 36px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  border-bottom: 1px solid var(--border);
  transition: color .25s var(--ease-out);
  /* Per-link stagger reveal — initial state */
  opacity: 0; transform: translateY(10px);
}
.nav-menu-link:hover { color: var(--primary); }
.nav-menu-link > span:first-child { flex: 1; min-width: 0; }
.nav-menu-link-arrow {
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text);
  flex-shrink: 0;
  transition: background .25s var(--ease-out), color .25s, transform .25s;
}
.nav-menu-link:hover .nav-menu-link-arrow {
  background: var(--primary); color: var(--primary-ink, #FFFFFF);
  transform: translate(2px, -2px);
}
.nav-menu-link-arrow svg { width: 14px; height: 14px; }
.nav-menu-cta {
  margin-top: auto;
  display: flex; flex-direction: column;
  gap: 12px;
  opacity: 0; transform: translateY(10px);  /* whole block fades in last */
}
/* Reveal cascade on open — links 1..5 stagger, CTAs as final beat. */
.nav-menu.is-open .nav-menu-link,
.nav-menu.is-open .nav-menu-cta {
  opacity: 1; transform: translateY(0);
  transition: opacity .45s var(--ease-out), transform .45s var(--ease-out), color .25s, background .25s;
}
.nav-menu.is-open li:nth-child(1) .nav-menu-link { transition-delay: 80ms; }
.nav-menu.is-open li:nth-child(2) .nav-menu-link { transition-delay: 130ms; }
.nav-menu.is-open li:nth-child(3) .nav-menu-link { transition-delay: 180ms; }
.nav-menu.is-open li:nth-child(4) .nav-menu-link { transition-delay: 230ms; }
.nav-menu.is-open li:nth-child(5) .nav-menu-link { transition-delay: 280ms; }
.nav-menu.is-open .nav-menu-cta { transition-delay: 340ms; }

@media (max-width: 1100px) {
  .nav-menu { display: block; }
}

/* ============================================================
   Hero
   ============================================================ */
.hero { padding-top: var(--hero-top); padding-bottom: clamp(48px, 6.5vw, 80px); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.42fr) minmax(0, 1fr); gap: 24px; }
.hero-left { display: flex; flex-direction: column; gap: 32px; }
/* Hero "NEW" pill — eyebrow typography on the pill's own white surface;
   no leading dot (client call). Its ink text is what sets it apart from
   the blue .eyebrow chip. */
.pill-new {
  display: inline-flex; align-items: center;
  padding: 7px 14px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  width: fit-content;
}
.pill-new-text {
  font-family: var(--font-sans); font-weight: 600; font-size: 13px;
  letter-spacing: 0; text-transform: none; color: var(--text);
}

.hero-title { display: flex; flex-direction: column; }
.hero-title-row { display: inline-flex; align-items: center; gap: 18px; }

/* Per-line mask reveal — text rises from below an overflow:hidden mask.
   The stagger is --rise-delay, set on each line of the heading below.
   It inherits, so a line wrapped in .hero-title-row still picks its up.
   (The un-swept inner pages still set it with an inline style — those
   win over these rules, so their timings are untouched.) */
.line-rise {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.line-rise-inner {
  display: inline-block;
  transform: translateY(110%);
  animation: lineRise 1200ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: var(--rise-delay, 0ms);
  will-change: transform;
}
@keyframes lineRise { to { transform: translateY(0); } }

.hero-title > *:nth-child(1) { --rise-delay: 200ms; }
.hero-title > *:nth-child(2) { --rise-delay: 420ms; }
.hero-title > *:nth-child(3) { --rise-delay: 640ms; }
.cta-title > *:nth-child(1) { --rise-delay: 0ms; }
.cta-title > *:nth-child(2) { --rise-delay: 160ms; }
/* The inner pages' hero titles and the 404's giant digits stagger the same way
   — these used to be inline style="--rise-delay" attrs on every line, which
   broke the project's no-inline-style rule on five pages. */
:is(.check-hero-title, .ai-hero-title, .text-hero-title, .contact-title) > *:nth-child(1) { --rise-delay: 160ms; }
:is(.check-hero-title, .ai-hero-title, .text-hero-title, .contact-title) > *:nth-child(2) { --rise-delay: 360ms; }
.error-code > *:nth-child(1) { --rise-delay: 120ms; }
.error-code > *:nth-child(2) { --rise-delay: 240ms; }
.error-code > *:nth-child(3) { --rise-delay: 360ms; }

@media (prefers-reduced-motion: reduce) {
  .line-rise-inner { transform: none; animation: none; }
}

.hero-lead { max-width: 600px; margin: 0; }

.upload-card {
  padding: 16px; border-radius: 22px;
  border-color: var(--primary-2);
  animation: uploadCardPulse 2.6s var(--ease-in-out) infinite;
  transition: border-color .25s, box-shadow .25s, transform .25s var(--ease-out);
}
/* Idle border breathes from a very light line gray up to the brand blue
   — slow, subtle, paused once focused / drag-hovered / reduced-motion. */
@keyframes uploadCardPulse {
  0%, 100% { border-color: var(--line); }
  50%      { border-color: var(--primary-2); }
}
/* Hover: freezes the pulse at its blue endpoint and deepens the drop
   shadow — no positional lift, just the contrast change as the cue. */
.upload-card:hover {
  animation: none;
  border-color: var(--primary-2);
  box-shadow: var(--shadow-3);
}
/* Active state mirrors the .field-input focus signature (see #ds-last in the
   design system): ink border + soft-lime focus ring stacked over the card's
   own drop shadow so the lift is preserved. */
.upload-card:focus-within {
  animation: none;
  border-color: var(--accent-blue);
  box-shadow: var(--focus-ring), var(--shadow-2);
  outline: none;
}
.upload-card.is-over {
  animation: none;
  border-color: var(--primary-2);
  box-shadow: 0 24px 60px -22px rgba(53,102,239,0.45);
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .upload-card { animation: none; }
}
.upload-row { display: flex; flex-direction: column; gap: 16px; padding: 6px 0; }
.upload-input {
  border: 0; outline: 0; width: 100%; background: transparent;
  font-family: var(--font-sans); font-weight: 500; font-size: 15px; color: var(--text);
  padding: 0;
  /* Compose box: multi-line paste target is the hero's primary action.
     No manual resize handle (it would fight the card's rounded corner);
     the field grows only via the rows attribute / min-height. */
  display: block; resize: none; min-height: 104px; line-height: 1.55;
  caret-color: var(--accent-blue);
}
.upload-input::placeholder { color: var(--text-muted-2); }
.upload-controls { display: flex; align-items: center; gap: 12px; }
.upload-attach {
  width: 40px; height: 40px; border-radius: 12px; background: var(--paper-2);
  display: inline-flex; align-items: center; justify-content: center; color: var(--text);
  transition: background .2s, transform .2s var(--ease-out);
}
.upload-attach:hover { background: #EFEFEC; transform: rotate(90deg); }
.upload-hint { font-size: var(--fs-11-5); letter-spacing: 0.02em; text-transform: none; line-height: 1.4; }
.upload-divider { margin: 12px 0; }
.upload-foot { display: flex; align-items: center; gap: 8px; }
.upload-meta { letter-spacing: 0.04em; text-transform: none; }

/* "Paste URL" pill expands into a slim pill-shaped URL input + ink arrow
   submit button. Borrows the .chip pill geometry + .field-input focus signature
   (ink border on focus-within) so it sits in the same visual family.
   Explicit [hidden] override because .chip { display: inline-flex } and the
   .upload-url-form rule below both beat the UA `[hidden] { display: none }`. */
.upload-url-chip[hidden],
.upload-url-form[hidden] { display: none; }
.upload-url-form {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px;
  padding: 0 4px 0 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  flex: 1; min-width: 0; max-width: 360px;
  transition: border-color .2s var(--ease-out), background .2s;
}
.upload-url-form:focus-within {
  border-color: var(--text);
  background: var(--surface);
}
.upload-url-input {
  flex: 1; min-width: 0;
  border: 0; outline: 0; background: transparent;
  font-family: var(--font-sans); font-weight: 500; font-size: 12.5px;
  color: var(--text); height: 28px; padding: 0;
}
.upload-url-input::placeholder { color: var(--text-muted-2); }
.upload-url-submit {
  width: 22px; height: 22px; border-radius: 999px;
  background: var(--ink); color: #FFFFFF;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background .2s, transform .25s var(--ease-out);
}
.upload-url-submit:hover { background: #000; transform: translateX(2px); }

/* Hero right — the check form's column. Staggered below the headline's top
   edge (offset bento) and stretched so the form owns the column width. */
.hero-right { display: flex; flex-direction: column; gap: 20px; align-items: stretch; margin-top: 56px; }
.hero-form-wrap { width: 100%; }

/* ============================================================
   Hero — pastel gradient panel (Nucleate-style reference): a rounded
   block of soft blue / turquoise / violet blooms on a light base, ink
   text, the white check form floating as the hero's primary object.
   Pure CSS — repaints with the palette, no image asset.
   ============================================================ */
.hero--panel .hero-grid {
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
  background: var(--bloom);
  border-radius: 36px;
  padding: clamp(32px, 4.5vw, 56px);
  align-items: start;
}
.hero--panel .hero-lead { max-width: 520px; }
/* The form floats on the pastel wash — keep the stronger drop shadow. */
.hero--panel .upload-card { box-shadow: var(--shadow-3); }
.hero--panel .upload-input { min-height: 176px; }

/* ============================================================
   Mission (from the stat-cards reference): left text column —
   eyebrow, short heading, two-tone lead, link, and a footer note
   pinned to the bottom; right — a bento of flat grey stat cards
   (wide + two), each icon-label top, big stat + caption bottom.
   ============================================================ */
.mission { padding: 20px 0 0; }
.mission-grid {
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.14fr);
  gap: clamp(32px, 5vw, 80px);
  padding: 0 0 clamp(72px, 9vw, 120px);
  align-items: stretch;
}
/* .mission-head groups the copy (eyebrow → link) so it can be laid out as ONE
   unit against .mission-foot. On desktop both are just stacked, exactly as
   before the wrapper existed; on the collapsed grid they go side by side. */
.mission-left { display: flex; flex-direction: column; align-items: flex-start; gap: var(--head-gap); }
.mission-head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--head-gap); }
.mission-lead {
  margin: 0; max-width: 380px;
  font-size: 15px; line-height: 1.6; letter-spacing: -0.01em;
  color: var(--text-muted-2);
}
.mission-lead b { font-weight: 600; color: var(--text); }
.mission-link {
  font-size: 14px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--link); text-decoration: none;
}
.mission-link:hover { color: var(--link-hover); }
.mission-foot { margin-top: auto; padding-top: 48px; display: flex; flex-direction: column; gap: 14px; }
/* Reviewer cluster — overlapping circles with a white ring, each one lifted
   above the next so the stack reads left-to-right. */
.mission-avatars { display: flex; align-items: center; margin-bottom: 4px; }
.mission-avatars img {
  width: 40px; height: 40px; border-radius: 999px;
  border: 2px solid var(--surface);
  object-fit: cover; display: block;
  box-shadow: 0 2px 8px -3px rgba(15, 18, 20, 0.25);
}
.mission-avatars img + img { margin-left: -12px; }
.mission-avatars img:nth-child(1) { z-index: 5; }
.mission-avatars img:nth-child(2) { z-index: 4; }
.mission-avatars img:nth-child(3) { z-index: 3; }
.mission-avatars img:nth-child(4) { z-index: 2; }
.mission-avatars img:nth-child(5) { z-index: 1; }
.mission-foot-text {
  margin: 0; max-width: 360px;
  font-size: 13.5px; line-height: 1.6;
  color: var(--text-muted-2);
}
.mission-foot-text b { font-weight: 600; color: var(--text); }
.mission-rated { font-size: 11px; letter-spacing: 0.04em; color: var(--text-muted); }

.mission-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.mission-card {
  grid-column: span 1;
  background: var(--card-flat);
  border-radius: 20px;
  padding: var(--pad-card);
  min-height: 250px;
  display: flex; flex-direction: column;
}
.mission-card--wide { grid-column: span 2; }
.mission-card-label {
  display: inline-flex; align-items: center; gap: 12px;
  font-size: 13.5px; font-weight: 500; color: var(--text);
}
/* Icon sits on a dark rounded plate (reference style): ink square,
   white stroke, a step larger than the old bare 15px glyph. */
.mission-card-label svg {
  flex-shrink: 0;
  width: 18px; height: 18px;
  box-sizing: content-box;
  padding: 9px;
  background: var(--ink);
  color: #FFFFFF;
  border-radius: 12px;
}
.mission-card-stat {
  margin-top: auto;
  font-weight: 600;
  font-size: clamp(44px, 4.2vw, 60px);
  letter-spacing: -0.04em; line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.mission-card-unit { font-size: 0.5em; font-weight: 500; margin-left: 6px; letter-spacing: -0.01em; }
.mission-card-cap { margin-top: 12px; font-size: 13.5px; line-height: 1.5; color: var(--text-muted); }

/* ============================================================
   How it works — timeline panel (from the layout reference):
   a white rounded panel with a big statement, then a time axis of
   six hairline columns (mono 01–06 on top) and moment-pills
   scattered along it, descending left→right. The three step pills
   fill one by one (periwinkle sweep), then a schematic report card
   and the Get-started CTA appear; a chrome cursor crosses one pill.
   Pills reveal a mono hint above themselves on hover.
   ============================================================ */
.tl-panel {
  background: var(--surface);
  border-radius: 32px;
  padding: clamp(32px, 4.5vw, 60px);
}
.tl-statement { margin: var(--head-gap) 0 0; max-width: var(--head-measure); }
.tl-track { position: relative; margin-top: clamp(48px, 6vw, 84px); height: 380px; }
.tl-cols { position: absolute; inset: 30px 0 0 0; display: flex; justify-content: space-between; }
.tl-col { position: relative; width: 1px; background: var(--line); }
.tl-col i {
  position: absolute; top: -24px; left: 0;
  font-style: normal; font-family: var(--font-mono); font-weight: 500;
  font-size: 10px; letter-spacing: 0.08em; color: var(--text-muted-2);
}

.tl-pill {
  position: absolute; z-index: 2;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 20px; border-radius: 999px;
  background: var(--paper-2); color: var(--text);
  font-size: 14px; font-weight: 500; white-space: nowrap;
}
.tl-pill b { font-weight: 700; }
.tl-num { font-size: 10px; letter-spacing: 0.06em; color: var(--primary); font-weight: 700; }
.tl-pill--micro { padding: 10px 16px; font-size: 13px; color: var(--text-muted); }

/* Step pills — a soft periwinkle progress fill sweeps each one in turn
   (the sequence choreography lives in the animation block below). The
   default/base styles here are the FINISHED state, so reduced-motion
   users and late scrollers see a completed, legible sequence. */
.tl-pill--step > span { position: relative; z-index: 1; }
.tl-pill--step::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  width: 100%;
  border-radius: inherit;
  background: var(--tint-1);
}

/* Pill choreography (desktop) — three equal-width steps descending
   left→right in an even cascade; the finale sits clear of them on the
   right, inside the same track height. */
.tl-pill--step { width: 31%; }
.tl-p1 { left: 2%;  top: 40px; }
.tl-p3 { left: 20%; top: 150px; }
.tl-p5 { left: 38%; top: 260px; }

/* Final beat: the schematic report + Get started — logically after step 3,
   never overlapping it. The chrome cursor sits on the CTA as a "click me"
   nudge and appears together with the finale. */
.tl-final {
  position: absolute; right: 1%; bottom: 6px; z-index: 3;
  width: 224px;
  display: flex; flex-direction: column; gap: 14px;
}
.tl-final .tl-cursor {
  position: absolute; z-index: 4;
  right: -20px; bottom: 74px;
  width: 96px; height: 96px;
  transform: rotate(-6deg);
  filter: drop-shadow(0 14px 20px rgba(15, 18, 20, 0.22));
  pointer-events: none;
}
.tl-report {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 9px;
  box-shadow: var(--shadow-2);
}
.tl-report-head { display: flex; justify-content: space-between; align-items: center; }
.tl-report-tag { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--primary); font-weight: 700; }
.tl-report-meta { font-size: 9px; letter-spacing: 0.06em; color: var(--text-muted-2); }
.tl-report-line { height: 6px; border-radius: 999px; background: var(--paper-3); }
.tl-report-line--title { height: 8px; width: 58%; background: var(--tint-1); }
.tl-report-line--short { width: 72%; }
.tl-report-foot {
  margin-top: 3px;
  display: flex; align-items: center; gap: 8px;
  font-size: 10px; letter-spacing: 0.05em; color: var(--text-muted);
}
.tl-report-check {
  width: 18px; height: 18px; border-radius: 999px; flex-shrink: 0;
  background: var(--primary); color: #FFFFFF;
  display: inline-flex; align-items: center; justify-content: center;
}
.tl-final-cta { width: 100%; justify-content: center; }

/* Sequence: fill step 1 → 2 → 3, then reveal the report + CTA. Plays once
   when script.js flags the track .is-playing on scroll-in; without motion
   preference (or without the flag reaching us) the base finished state shows. */
@keyframes tlFill { from { width: 0; } to { width: 100%; } }
@keyframes tlNumOff { from { color: var(--text-muted); font-weight: 500; } to { color: var(--primary); font-weight: 700; } }
@keyframes tlAppear { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  .tl-track:not(.is-playing) .tl-pill--step::before { width: 0; }
  .tl-track:not(.is-playing) .tl-pill--step .tl-num { color: var(--text-muted); font-weight: 500; }
  .tl-track:not(.is-playing) .tl-final { opacity: 0; }
  .tl-track.is-playing .tl-step-1::before { width: 0; animation: tlFill 1.4s var(--ease-out) 0.2s forwards; }
  .tl-track.is-playing .tl-step-2::before { width: 0; animation: tlFill 1.4s var(--ease-out) 1.9s forwards; }
  .tl-track.is-playing .tl-step-3::before { width: 0; animation: tlFill 1.4s var(--ease-out) 3.6s forwards; }
  .tl-track.is-playing .tl-step-1 .tl-num { color: var(--text-muted); font-weight: 500; animation: tlNumOff 0.3s 1.5s forwards; }
  .tl-track.is-playing .tl-step-2 .tl-num { color: var(--text-muted); font-weight: 500; animation: tlNumOff 0.3s 3.2s forwards; }
  .tl-track.is-playing .tl-step-3 .tl-num { color: var(--text-muted); font-weight: 500; animation: tlNumOff 0.3s 4.9s forwards; }
  .tl-track.is-playing .tl-final { opacity: 0; animation: tlAppear 0.5s var(--ease-out) 5.2s forwards; }
}

/* Hover hint — mono tooltip rising above the pill */
.tl-hint {
  position: absolute; left: 16px; bottom: calc(100% + 9px);
  padding: 8px 13px; border-radius: 10px;
  background: var(--ink); color: #F4F3F2;
  font-size: 10px; font-weight: 500; letter-spacing: 0.05em;
  white-space: nowrap; pointer-events: none;
  opacity: 0; transform: translateY(5px);
  transition: opacity .18s var(--ease-out), transform .18s var(--ease-out);
}
.tl-pill:hover { z-index: 6; }
.tl-pill:hover .tl-hint { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .tl-hint { transition: none; transform: none; }
}

/* ============================================================
   Features — checkerboard bento (from the layout reference):
   2×2 grid on 3 tracks, wide(⅔)+narrow(⅓) then narrow+wide.
   Cards are flat single-surface (no border, no shadow), title
   top-left, hairline/diegetic demo pinned to the bottom. The
   brand coin sits on the grid's T-junction, overlapping three
   cards — decor crossing boundaries, as everywhere in the refs.
   ============================================================ */
/* Alternating section fill (light cool-gray, theme-flippable).
   `--card-flat` is the fill's companion: a flat, borderless card has to read
   AGAINST its section, so it is grey on the plain dotted background and white
   inside a filled section. Setting it here means any flat card (.feat-card,
   .mission-card, .value-card, .showcase-card) inverts automatically wherever
   it is dropped, instead of each class hard-coding a surface and breaking the
   moment the section under it changes. */
:root { --card-flat: var(--surface-3); }
#how, #inside, #heritage, #compare, #inside-scan, #audience, #support {
  background-color: var(--surface-3);
  --card-flat: var(--surface);
}

.feat-grid {
  position: relative;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px;
}
.feat-card {
  background: var(--card-flat);
  border-radius: var(--r-md);
  padding: var(--pad-roomy) var(--pad-roomy) var(--pad-card);
  min-height: 280px;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.feat-card--w2 { grid-column: span 2; }
/* Card titles all sit on the h-3 step of the scale — see .h-3. */
.feat-title {
  font-size: var(--fs-h-3);
  letter-spacing: -0.02em; line-height: 1.22;
}

/* Model pill cloud — rows deliberately clip at the card edges */
.feat-pills { display: flex; flex-direction: column; gap: 10px; margin: auto calc(-1 * var(--pad-roomy)) 6px; }
.feat-pills-row { display: flex; gap: 10px; flex-wrap: nowrap; justify-content: center; }
.feat-pills-row--shift { transform: translateX(-28px); }
.feat-pill {
  flex-shrink: 0;
  padding: 9px 18px; border-radius: 999px;
  background: var(--paper-2); color: var(--text);
  font-size: 13.5px; font-weight: 500; white-space: nowrap;
}
.feat-pill--dark { background: var(--ink); color: #F4F3F2; }

/* Hairline gauge — tick arc runs a blue→cyan→lavender gradient (the SVG
   defs a userSpaceOnUse linearGradient); reading sits bottom-left. */
.feat-gauge { position: relative; margin-top: auto; }
.feat-gauge-svg { display: block; width: 100%; height: auto; }
.feat-gauge-ticks { fill: none; stroke: url(#gaugeGrad); stroke-width: 14; stroke-dasharray: 1.5 6.5; }
.feat-gauge-read {
  position: absolute; left: 2px; bottom: 6px;
  display: flex; flex-direction: column; gap: 3px; align-items: flex-start;
}
.feat-gauge-label { font-size: 10px; letter-spacing: 0.06em; color: var(--text-muted); }
.feat-gauge-val { display: inline-flex; align-items: center; gap: 7px; font-weight: 600; font-size: 16px; letter-spacing: -0.01em; }
.feat-gauge-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--accent-blue); }

/* One-pass connector — blue dot → dotted hairline → ink dot */
.feat-card--center { align-items: center; text-align: center; padding-top: var(--pad-card); padding-bottom: var(--pad-card); }
.feat-title--center { padding: 18px 0; }
.feat-connector-dot { width: 10px; height: 10px; border-radius: 999px; background: var(--text); flex-shrink: 0; }
.feat-connector-dot--green { background: var(--primary-2); }
.feat-connector-line { flex: 1; min-height: 28px; border-left: 1.5px dotted var(--text-muted-2); }

/* Subscription compare + giant thin numeral */
.feat-compare-wrap { margin-top: auto; display: flex; align-items: flex-end; justify-content: space-between; gap: 32px; }
.feat-compare { display: flex; flex-direction: column; gap: 10px; min-width: 0; flex: 1; max-width: 330px; }
.feat-compare-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 9px 16px; border-radius: 999px;
  background: var(--paper-2); color: var(--text-muted);
  font-size: 13.5px; font-weight: 500; white-space: nowrap;
}
.feat-compare-row--ours { background: var(--ink); color: #F4F3F2; }
.feat-compare-price { letter-spacing: 0.08em; }
.feat-compare-price--acid { color: var(--tint-1); }
.feat-big { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; flex-shrink: 0; }
.feat-big-kicker, .feat-big-label { font-size: 10.5px; letter-spacing: 0.05em; color: var(--text-muted); }
.feat-big-num {
  font-weight: 300; font-size: clamp(56px, 5.5vw, 88px);
  letter-spacing: -0.04em; line-height: 0.95; color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* Brand coin on the T-junction of the grid seams — the round-logo SVG
   asset (already a filled disc), sized like the old built coin. */
.feat-coin {
  position: absolute; z-index: 5;
  width: 92px; height: 92px; border-radius: 999px;
  left: calc(66.8% - 34px);
  top: calc(50% - 32px);
  display: block;
  box-shadow: 0 12px 26px -8px rgba(15, 18, 20, 0.28);
}

.bento-bottom-section { padding-top: clamp(72px, 9vw, 120px); }
/* Audience checkerboard (client's placement reference): 2×2 on 3 tracks,
   mirrored against the features grid — narrow+wide, then wide+narrow.
   Rows are flush; the wide/narrow alternation carries the asymmetry. */
.profile-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}
.profile-grid > :nth-child(2),
.profile-grid > :nth-child(3) { grid-column: span 2; }
/* Audience cards are static exhibits (client call) — no hover flip, no
   pointer cursor. Only the tint CTA card below stays interactive. */
.profile-card {
  border-radius: 24px; padding: var(--pad-roomy) var(--pad-card); min-height: 340px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border);
  /* Layout: head sticks to top with consistent gap → graphic sits at the
     same y across all cards → body pushed to the bottom via margin-top:auto. */
  display: flex; flex-direction: column; gap: 16px;
}

.profile-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.profile-head-left { display: flex; align-items: center; gap: 12px; }
.profile-num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; padding: 7px 10px;
  border-radius: 999px;
  background: var(--paper-2); color: var(--text);
  font-size: var(--fs-11); text-transform: none; letter-spacing: 0.04em;
}

.profile-kicker {
  font-size: 12px; letter-spacing: 0.08em; color: var(--text);
}

/* Inert remnant: inner pages' markup still carries .profile-arrow-btn;
   without the hover reveal it simply never shows. Strip it during the
   inner-page sweep. */

/* Graphic zone owns the card's middle (reference: big centered visual
   between the head row and the bottom-left text block). */
.profile-graphic {
  flex: 1; min-height: 120px;
  display: flex; align-items: center; justify-content: center;
  padding: 10px 0;
}
/* multiply hides the illustrations' not-quite-white backdrops on the card */
.profile-graphic img { width: 100%; max-width: 400px; height: auto; object-fit: contain; display: block; mix-blend-mode: multiply; }

.profile-body { display: flex; flex-direction: column; gap: 10px; margin-top: auto; }
.profile-title {
  font-size: var(--fs-h-3);
  letter-spacing: -0.02em; line-height: 1.22;
}
.profile-text {
  margin: 0; font-size: 13px; line-height: 1.58; letter-spacing: -0.01em;
  color: var(--text-muted);
}

/* Writers CTA card — pastel bloom fill (same recipe as the hero panel),
   absorbs the old analyzed-strip stat + CTA. The one interactive card:
   a gentle lift on hover, no ink flip. */
.profile-card--tint {
  background: var(--bloom);
  border-color: transparent;
  transition: transform .35s var(--ease-out), box-shadow .35s var(--ease-out);
}
.profile-card--tint:hover {
  transform: translateY(-3px);
  box-shadow: 0 22px 44px -24px rgba(53, 102, 239, 0.35);
}
.profile-stat { display: flex; flex-direction: column; gap: 4px; padding: 10px 0 0 2px; }
.profile-stat-num {
  font-weight: 600; font-size: clamp(40px, 3.6vw, 52px);
  letter-spacing: -0.04em; line-height: 1; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.profile-stat-label { font-size: 10px; letter-spacing: 0.08em; color: var(--text-muted); }
.profile-cta { align-self: flex-start; margin-top: 6px; }

/* ============================================================
   FAQ
   ============================================================ */

.faq-grid { margin-top: var(--space-lg); display: flex; align-items: flex-start; gap: 16px; }
.faq-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.faq-row {
  border-radius: 18px; background: var(--surface); border: 1px solid var(--line);
  padding: 18px 24px; transition: background .25s, border-color .25s;
}
.faq-row.is-open { background: var(--faq-bg, var(--surface-2)); border-color: var(--faq-bg, var(--surface-2)); }
.faq-row-btn {
  width: 100%; display: flex; justify-content: space-between; align-items: center;
  text-align: left;
}
.faq-q { font-weight: 600; font-size: 15px; letter-spacing: -0.01em; line-height: 1.38; color: var(--text); }
.faq-toggle {
  width: 28px; height: 28px; border-radius: 999px; background: var(--paper-2);
  display: inline-flex; align-items: center; justify-content: center; color: var(--text);
  transition: background .2s, color .2s, transform .35s var(--ease-out);
  flex-shrink: 0; margin-left: 16px;
}
.faq-row.is-open .faq-toggle { transform: rotate(180deg); background: var(--ink); color: #F4F3F2; }
.faq-body { overflow: hidden; height: 0; transition: height .4s var(--ease-out); }
.faq-a { margin: 12px 0 0; color: var(--muted); font-size: 13.5px; line-height: 1.6; max-width: 560px; }

/* ============================================================
   Pricing
   ============================================================ */
.pricing-section { background: var(--surface-3); }

.tabs {
  position: relative; display: inline-flex; padding: 4px;
  border-radius: 999px; background: var(--surface); border: 1px solid var(--line);
}
.tabs-pill {
  position: absolute; top: 4px; left: 0; height: calc(100% - 8px);
  background: var(--text); border-radius: 999px;
  transform: translateX(0); width: 0;
  transition: transform .35s var(--ease-out), width .35s var(--ease-out);
}
.tab {
  position: relative; padding: 8px 14px; border-radius: 999px;
  font-weight: 500; font-size: 13px; color: var(--text);
  transition: color .25s;
}
.tab.tab-active { color: var(--bg); }

.pricing-grid {
  margin-top: var(--space-lg);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px;
  align-items: stretch;
}
/* Per-card tab-switch microanimation. Speed (.7s) matches the site-wide
   .reveal-stagger so the initial scroll-reveal of the prices and the tab
   swap feel identical. Stagger (0/70/140ms) reuses the existing
   .reveal-stagger.in > *:nth-child delays, so cards fade out 1→2→3 and
   then in 1→2→3.

   Two hidden states (asymmetric magnitudes — user-driven decision):
     OUT  → translateY(-6px) : 6px upward (half of IN), feels lighter.
     IN   → translateY(+12px): 12px coming up from below.
   Between OUT-end and IN-start the cards snap (transition: none) from
   -6px to +12px so the IN phase always starts from "below". */
.pricing-grid > .price-card {
  transition: opacity .33s var(--ease-out), transform .33s var(--ease-out);
}
/* Pricing-only stagger override (1/3 of the site-wide .reveal-stagger.in
   nth-child delays) — keeps the 1→2→3 cadence felt but ~3× snappier. */
.pricing-grid > .price-card:nth-child(2) { transition-delay: 25ms; }
.pricing-grid > .price-card:nth-child(3) { transition-delay: 50ms; }
.pricing-grid[data-swap="out"] > .price-card { opacity: 0; transform: translateY(-6px); }
.pricing-grid[data-swap="pre-in"] > .price-card {
  opacity: 0; transform: translateY(12px);
  transition: none;
}
.price-card {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border);
  border-radius: 28px; padding: var(--pad-roomy);
  display: flex; flex-direction: column; gap: 24px;
  transition: transform .35s var(--ease-out), box-shadow .35s;
  position: relative; overflow: hidden;
}
.price-card:hover { transform: translateY(-4px); box-shadow: 0 22px 50px -28px rgba(15,18,20,0.22); }

.price-top { display: flex; flex-direction: column; gap: 10px; }
.price-name-row { display: flex; justify-content: space-between; align-items: center; min-height: 24px; }
.price-name { font-size: 13px; letter-spacing: 0.08em; color: var(--ink); }
.price-popular {
  font-size: 10.5px; letter-spacing: 0.06em; padding: 5px 10px;
  border-radius: 999px; background: var(--primary); color: var(--primary-ink, #FFFFFF);
}

.price-num-row { display: flex; align-items: center; gap: 8px; }
.price-whole { font-weight: 600; font-size: clamp(40px, 5.5vw, 60px); letter-spacing: -0.04em; line-height: 1; }
.price-tail { display: flex; flex-direction: column; }
.price-frac { font-weight: 600; font-size: clamp(18px, 2vw, 24px); letter-spacing: -0.01em; line-height: 1.1; }
.price-mo { font-size: 10.5px; letter-spacing: 0.04em; color: var(--text-muted-2); text-transform: none; }

/* Rate box ($/1,000 words + tagline) */
.price-rate {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--paper-2); border-radius: 12px; padding: 8px 12px;
}
.price-rate-head { display: flex; align-items: center; gap: 8px; }
.price-rate-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--primary-2); flex-shrink: 0; }
.price-rate-text { font-size: 14px; font-weight: 500; letter-spacing: -0.01em; color: var(--text-muted); }
.price-rate-num { color: var(--link); }
.price-rate-desc { font-size: 12px; line-height: 1.5; letter-spacing: -0.01em; color: var(--text-muted-2); }

/* Feature list */
.price-notes { display: flex; flex-direction: column; gap: 20px; flex: 1; }
.price-note { display: flex; gap: 16px; align-items: flex-start; }
.price-check {
  width: 20px; height: 20px; border-radius: 999px; flex-shrink: 0;
  background: var(--primary); color: var(--primary-ink, #FFFFFF);
  display: inline-flex; align-items: center; justify-content: center;
}
.price-check svg { width: 12px; height: 12px; }
.price-note-text { display: flex; flex-direction: column; gap: 2px; }
.price-note-title { font-size: 14px; font-weight: 500; color: var(--text); }
.price-note-sub { font-size: var(--fs-11); letter-spacing: 0.04em; color: var(--text-muted-2); text-transform: none; }

/* CTAs */
.price-cta { margin-top: auto; width: 100%; justify-content: center; }
.price-cta.btn-outline { background: var(--surface-2); }
.price-cta.btn-primary { padding-left: 8px; padding-right: 8px; }

/* Pricing dots — hidden on desktop/tablet, shown only when the grid becomes
   a horizontal snap-scroller on phone (see @media ≤720px). */
.pricing-dots { display: none; }
.pricing-dot {
  appearance: none; background: var(--border); border: 0; padding: 0;
  width: 8px; height: 8px; border-radius: 999px; cursor: pointer;
  transition: background .25s var(--ease-out), width .25s var(--ease-out);
}
.pricing-dot.is-active { background: var(--ink); width: 24px; }

/* ============================================================
   CTA
   ============================================================ */
/* CTA section sits flush against a plain (un-filled) section above it,
   otherwise white-on-white double padding leaves a big empty gap.
   When the preceding sibling IS a gray-fill section (alternating list +
   .pricing-section), restore the standard .section top padding for breathing room. */
.cta-section { padding-top: 0; padding-bottom: var(--space-lg); }
:is(#inside, #heritage, #compare, #inside-scan, #audience, .pricing-section) + .cta-section {
  padding-top: clamp(72px, 9vw, 120px);
}
/* CTA — centered pastel bloom banner in the hero's language: the small
   loupe as a medallion on top, kicker, two-line headline with the blue
   accent word, one primary action and a mono meta line. */
.cta-strip {
  background: var(--bloom);
  color: var(--text); border-radius: 36px;
  padding: clamp(40px, 5vw, 64px) var(--pad-xl);
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 18px;
}
.cta-title { color: var(--text); max-width: 600px; display: flex; flex-direction: column; align-items: center; }
.cta-btn { margin-top: 8px; margin-bottom: 16px; }
.cta-meta { font-size: var(--fs-11); letter-spacing: 0.06em; color: var(--text-muted); }
.cta-loupe {
  width: 120px; height: 120px;
  transform: rotate(-8deg);
  filter: drop-shadow(0 16px 22px rgba(15, 18, 20, 0.16));
  pointer-events: none;
  margin-bottom: 2px;
}

/* cta-title line-rise — gated on .cta-strip.in so it fires on scroll, not page load */
.cta-title .line-rise-inner { animation: none; }
.cta-strip.in .cta-title .line-rise-inner {
  animation: lineRise 1100ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: var(--rise-delay, 0ms);
}

/* ============================================================
   Footer
   ============================================================ */
.footer { background: var(--surface); padding: 64px 0; }
.footer-top { display: flex; gap: 24px; align-items: stretch; }

.footer-brand { width: 417px; flex-shrink: 0; display: flex; flex-direction: column; justify-content: space-between; gap: 32px; }
.footer-logo { display: inline-flex; }
.footer-brand-foot { display: flex; flex-direction: column; gap: 16px; }
.footer-tagline { margin: 0; max-width: 380px; font-size: 14px; line-height: 1.5; color: var(--text-muted); }

.footer-cols { flex: 1; min-width: 0; display: flex; gap: 24px; }
.footer-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.footer-head { font-size: var(--fs-11); letter-spacing: 0.08em; color: var(--text-muted-2); }
.footer-list { display: flex; flex-direction: column; gap: 14px; }
.footer-list li { font-size: 14px; line-height: 1.5; }
.foot-link { display: inline-flex; align-items: center; gap: 8px; color: var(--text-muted); transition: color .2s; }
.foot-link:hover { color: var(--link-hover); }
.footer-badge {
  display: inline-flex; align-items: center;
  padding: 2px 8px; border-radius: 999px;
  background: var(--primary); color: var(--primary-ink, #FFFFFF);
  font-size: 9px; letter-spacing: 0.04em;
}

.footer-offices { display: flex; flex-direction: column; gap: 14px; }
.footer-office { font-size: 14px; line-height: 1.5; color: var(--text-muted); white-space: pre-line; }
.footer-office-divider { height: 1px; width: 100%; background: var(--border); }

.footer-divider { height: 1px; width: 100%; background: var(--border); margin: var(--space-lg) 0; }

.footer-bottom { display: flex; justify-content: space-between; align-items: center; gap: 24px; }
.footer-copy { font-size: 13px; line-height: 1.5; color: var(--text-muted); }
.footer-lang { display: flex; gap: 18px; }
.footer-lang .mono { font-size: 13px; letter-spacing: 0.04em; color: var(--text-muted-2); text-transform: none; }
.footer-lang-active { color: var(--link); }

/* ============================================================
   Form fields (labelled inputs, select, textarea, checkbox)
   ============================================================ */
.form { display: flex; flex-direction: column; gap: 20px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

.field { display: flex; flex-direction: column; gap: 8px; }
.field-label { font-size: 13px; font-weight: 500; color: var(--text); letter-spacing: -0.01em; }
.field-label .field-req { color: var(--success); margin-left: 2px; }
.field-label .field-opt { color: var(--text-muted-2); font-weight: 400; }

.field-input, .field-select, .field-textarea {
  width: 100%;
  font-family: var(--font-sans); font-weight: 500; font-size: 15px; color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  transition: border-color .2s var(--ease-out), box-shadow .2s var(--ease-out), background .2s;
}
.field-input, .field-select { height: 50px; padding: 0 16px; }
.field-textarea { min-height: 148px; padding: 14px 16px; line-height: 1.55; resize: vertical; }
.field-input::placeholder, .field-textarea::placeholder { color: var(--text-muted-2); }
.field-input:focus, .field-select:focus, .field-textarea:focus {
  outline: none;
  border-color: var(--text);
  background: var(--surface);
  box-shadow: 0 0 0 4px var(--primary-soft);
}

/* Select: native chevron removed, custom one drawn on the wrapper */
.field-select-wrap { position: relative; }
.field-select { appearance: none; -webkit-appearance: none; -moz-appearance: none; padding-right: 44px; cursor: pointer; }
.field-select-wrap::after {
  content: ""; position: absolute; right: 19px; top: 50%; width: 8px; height: 8px;
  border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted);
  transform: translateY(-70%) rotate(45deg); pointer-events: none;
}

/* Checkbox */
.field-check { display: flex; gap: 12px; align-items: flex-start; }
.field-check input {
  appearance: none; -webkit-appearance: none;
  width: 20px; height: 20px; flex-shrink: 0; margin: 1px 0 0;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px;
  cursor: pointer; position: relative;
  transition: background .2s, border-color .2s;
}
.field-check input:checked { background: var(--primary); border-color: var(--primary); }
.field-check input:checked::after {
  content: ""; position: absolute; left: 6px; top: 2px; width: 5px; height: 10px;
  border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink); transform: rotate(45deg);
}
.field-check input:focus-visible { outline: none; box-shadow: 0 0 0 4px var(--primary-soft); }
.field-check-label { font-size: 13px; line-height: 1.5; color: var(--text-muted); }
.field-check-label a { color: var(--link); text-decoration: underline; text-underline-offset: 2px; }

/* Success / status banner. The [hidden] override is load-bearing, not belt-and-
   braces: `display: flex` below beats the UA's `[hidden] { display: none }`, so
   the contact form's "Thanks — your message is on its way" banner was painted on
   page load, before anything had been sent. (Same trap as .upload-url-chip.) */
.form-status[hidden] { display: none; }
.form-status {
  display: flex; gap: 12px; align-items: center;
  padding: 14px 18px; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--success) 12%, var(--surface)); border: 1px solid color-mix(in srgb, var(--success) 38%, var(--border));
  color: var(--success); font-size: 14px; font-weight: 500;
}
/* Gap to the content below only when the banner leads other elements
   (e.g. above the contact form). No trailing space when it's the last child. */
.form-status:not(:last-child) { margin-bottom: 24px; }
.form-status-ico { display: inline-flex; flex-shrink: 0; }

/* ============================================================
   Contact page
   ============================================================ */
.contact-hero { padding-top: var(--hero-top); padding-bottom: clamp(48px, 6vw, 80px); }
/* The same pastel-bloom panel as the landing and the checker. Here the panel
   carries BOTH columns: the copy on the left and the message form as the
   right-hand object (client call), the way the checker's scanner sits on it.
   The panel IS the .wrap, so it overrides the wrap's gutter with its own. */
.contact-hero-panel {
  position: relative;
  background: var(--bloom);
  border-radius: 36px;
  padding: clamp(32px, 4.5vw, 56px);
}
.contact-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr); gap: clamp(32px, 4vw, 56px); align-items: start; }

.contact-intro { display: flex; flex-direction: column; gap: 28px; }
.contact-title { display: flex; flex-direction: column; }
.contact-lead { max-width: 440px; margin: 0; }
.contact-anchors { display: flex; flex-wrap: wrap; gap: 10px; }
/* The default chip is --surface-2 on white; on the bloom that grey turns muddy.
   White pills read as objects ON the wash, like the form card beside them. */
.contact-anchors .chip { background: var(--surface); }
.contact-anchors .chip:hover { background: var(--surface); box-shadow: var(--shadow-2); }

.contact-details { display: flex; flex-direction: column; border-top: 1px solid var(--border); margin-top: 4px; }
.contact-detail { display: flex; gap: 16px; align-items: flex-start; padding: 18px 0; border-bottom: 1px solid var(--border); }
/* Ink plate + white glyph — the same icon treatment as the mission stat cards
   and the about value cards. */
.contact-detail-ico {
  width: 42px; height: 42px; border-radius: 12px; flex-shrink: 0;
  background: var(--ink); color: #FFFFFF;
  display: inline-flex; align-items: center; justify-content: center;
}
.contact-detail-body { display: flex; flex-direction: column; gap: 4px; padding-top: 2px; }
.contact-detail-value { font-size: 15px; font-weight: 500; color: var(--text); line-height: 1.45; }
.contact-detail-value a { transition: color .2s; }
.contact-detail-value a:hover { color: var(--link-hover); }

.contact-form-card { padding: clamp(24px, 3vw, 40px); }
.contact-form-head { display: flex; flex-direction: column; gap: 6px; }
.contact-form-title { font-size: var(--fs-h-3); letter-spacing: -0.03em; }
.contact-submit { width: 100%; justify-content: center; }

/* Help cards — flat single-surface, no border or shadow, like .feat-card and
   .value-card. #support is a filled section, so --card-flat resolves to white. */
.contact-help-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.help-card {
  padding: var(--pad-roomy); display: flex; flex-direction: column; gap: 20px;
  background: var(--card-flat); border-radius: var(--r-md);
}
.help-card-ico {
  width: 48px; height: 48px; border-radius: 14px;
  background: var(--ink); color: #FFFFFF;
  display: inline-flex; align-items: center; justify-content: center;
}
.help-card-body { display: flex; flex-direction: column; gap: 10px; flex: 1; }
.help-card-title { font-size: var(--fs-h-3); letter-spacing: -0.025em; line-height: 1.15; }
.help-card-text { font-size: 14.5px; line-height: 1.55; color: var(--text-muted); margin: 0; }
.help-card .btn { align-self: flex-start; }

/* Utility: section that butts directly against the section above it.
   Used by the checker's trust strip, pricing, etc. */
.section-flush-top { padding-top: 0; }

/* Offices banner (globe + the two address PNGs) — a flat panel on the dotted
   background, so it reads against the white cards of the filled section above. */
.contact-banner {
  display: grid; grid-template-columns: 0.85fr 1fr; gap: 48px; align-items: center;
  background: var(--card-flat);
  border-radius: var(--r-2xl); padding: clamp(28px, 4vw, 56px); overflow: hidden;
}
/* A Nano Banana vignette in the audience/detector language, not a 3D object
   (client call). multiply melts the render's near-white backdrop into the panel,
   so no cut-out is needed — which also means the panel's own surface shows
   through it, and the illustration has to be light enough to survive that. */
.contact-banner-media { display: flex; align-items: center; justify-content: center; }
.contact-banner-media img {
  width: 100%; height: auto; display: block;
  object-fit: contain;
  mix-blend-mode: multiply;
}
.contact-banner-body { display: flex; flex-direction: column; gap: 24px; }
.contact-banner-title { font-size: var(--fs-h-2); letter-spacing: -0.03em; line-height: 1.1; }
.contact-banner-text { color: var(--text-muted); max-width: 460px; margin: 0; }
.contact-offices { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 4px; }
.contact-office { display: flex; flex-direction: column; gap: 8px; }

/* ============================================================
   About page
   ============================================================ */

/* Value cards ("What we stand for") — static informational cards */
.about-values-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
/* 4 cards in a 3-track grid leave an orphan — the checker page takes 2×2,
   echoing the landing's checkerboard rhythm. */
.about-values-grid--2up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Flat single-surface card + dark icon plate: the landing's card language.
   Overrides the .card border/shadow these still carry in markup. */
.value-card {
  padding: var(--pad-roomy); display: flex; flex-direction: column; gap: 16px;
  background: var(--card-flat); border: 0; border-radius: var(--r-md); box-shadow: none;
}
.value-card-ico {
  width: 40px; height: 40px; border-radius: 12px;
  background: var(--ink); color: #FFFFFF;
  display: inline-flex; align-items: center; justify-content: center;
}
.value-card-ico svg { width: 20px; height: 20px; }
.value-card-title { font-size: var(--fs-h-3); letter-spacing: -0.02em; line-height: 1.22; }
.value-card-text { font-size: 14.5px; line-height: 1.55; color: var(--text-muted); margin: 0; }

/* Illustrated variant (pricing's "What every plan actually buys you") — a 16:9
   Nano Banana vignette takes the ink icon plate's place. It is a VARIANT, not a
   replacement: about-us and the checker still render the icon cards, so
   .value-card-ico stays exactly as it is.
   16:9 is the client's call and the only place the family isn't 3:2 — the frame
   is set here rather than left to the render, so a re-render at the wrong ratio
   letterboxes instead of resizing the card. multiply melts the render's white
   backdrop into the card, which is --card-flat (grey on the dotted ground here,
   white inside a filled section) — so the artwork must survive being multiplied
   onto a tint, the same condition the contact banner introduced. */
.value-card--media { gap: 20px; }
.value-card-media {
  aspect-ratio: 16 / 9;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.value-card-media img {
  width: 100%; height: 100%; display: block;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/* Timeline — year | content rows separated by dividers */
.timeline { display: flex; flex-direction: column; margin: 0; padding-left: 0; list-style: none; }
.timeline-item {
  display: grid; grid-template-columns: 132px 1fr; gap: 32px;
  padding: var(--pad-card) 0; border-top: 1px solid var(--border);
}
.timeline-item:last-child { border-bottom: 1px solid var(--border); }
.timeline-year { font-size: 14px; color: var(--text-muted); padding-top: 3px; }
.timeline-content { display: flex; flex-direction: column; gap: 6px; }
.timeline-title { font-size: 18px; letter-spacing: -0.02em; line-height: 1.25; }
.timeline-text { font-size: 14.5px; line-height: 1.55; color: var(--text-muted); margin: 0; max-width: 620px; }

/* ============================================================
   Pricing page
   ============================================================ */
/* ============================================================
   Text-page hero — a dark image panel with the page title centred on it.
   Used by the pages that are read rather than operated: pricing, then
   about / contact / legal.

   The nav sits ABOVE the panel (the classic sticky pill), so the panel opens
   at the same --hero-top gap as every other hero, and its padding is
   symmetric — nothing is reserved at the top any more, so the copy sits on
   the panel's true vertical centre. (A version where the nav rode ON the
   image is shelved in the Nav block above.)
   ============================================================ */
.text-hero { padding: var(--hero-top) 0 clamp(48px, 6vw, 80px); }
.text-hero-panel {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-2xl);
  background: var(--ink);
  min-height: clamp(300px, 30vw, 420px);
  display: flex; align-items: center; justify-content: center;
  padding: clamp(56px, 6vw, 80px) var(--pad-xl);
}
/* The photo is the panel's floor, not its content — absolute, so it adds no
   height and the panel is sized by the copy inside it. */
.text-hero-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0.62;
}
/* A scrim under the copy. The image alone cannot guarantee contrast — the title
   has to stay legible whatever the artwork does — and it is measured, not eyeballed:
   `scratchpad/contrast.js` screenshots the panel with the copy hidden, samples the
   composited background inside each text box and reports the WCAG ratio against the
   WORST pixel, not the average. The average always looks fine; the worst pixel is
   what a reader actually hits.

   The radial has to reach the title's TAIL, not just its centre. With the about
   page's ring artwork the second line ran onto the bright iridescent rim, and the
   old falloff had already faded to nothing there — 3.1:1, scraping the large-text
   floor. Widening it symmetrically fixed the words but drowned the ring, so the
   centre sits LEFT of the panel's (42%), tracking the copy: the band behind the
   words goes dark, and the outer arc — well past the 82% release — keeps its gloss.
   Worst-pixel ratios at 1440: 14.1 / 4.9 / 11.4. */
.text-hero-panel::after {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(70% 78% at 42% 54%,
      rgba(9, 11, 14, 0.90) 0%,
      rgba(9, 11, 14, 0.55) 46%,
      rgba(9, 11, 14, 0) 82%),
    linear-gradient(180deg, rgba(9, 11, 14, 0.55) 0%, rgba(9, 11, 14, 0.12) 38%, rgba(9, 11, 14, 0.45) 100%);
  pointer-events: none;
}
.text-hero-inner {
  position: relative; z-index: 1;
  max-width: 820px;
  display: flex; flex-direction: column; align-items: center; gap: 22px;
  text-align: center;
}
.text-hero-title { color: #FFFFFF; display: flex; flex-direction: column; align-items: center; }
.text-hero-title .h-muted { color: #9FB8FF; }
.text-hero-lead { color: rgba(255, 255, 255, 0.72); max-width: 640px; margin: 0; }
/* Eyebrow inverts on the dark panel — the blue-tint chip would vanish. */
.text-hero .eyebrow {
  background: rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.text-hero .eyebrow::before { background: #FFFFFF; }

/* Buttons on the panel: the blue primary already reads on black, but the
   outline variant is an ink border on an ink surface — invisible. It goes
   white here. (.btn-dark must never be used on this panel for the same
   reason: dark on dark.) */
.text-hero-cta { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 6px; }
.text-hero .btn-outline {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.38);
  color: #FFFFFF;
}
.text-hero .btn-outline:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.62);
}
/* The tablet band is the panel's worst case: it is the narrowest the panel gets
   while the copy still runs its full width, so `cover` blows the artwork up and
   pushes it under the words — the headline's tail sat at 4.3:1 there. Anchoring
   the crop left walks the bright side of the image off the right edge instead of
   under the text; on phone the crop is already deep enough to do this on its own. */
@media (max-width: 1100px) {
  .text-hero-img { object-position: 0% 50%; }
}

/* Trust strip — 4 quick promises in one card */
/* Flat surface, no border — the same card language as the landing. (The dark
   variant below is LEGACY: ai-detector and pricing still render it.) */
.trust-strip {
  display: grid; grid-template-columns: repeat(4, 1fr);
  background: var(--surface-3); border: 0;
  border-radius: var(--r-xl); padding: var(--pad-card) 8px;
}
.trust-item {
  display: flex; flex-direction: column; gap: 6px;
  padding: 4px 24px; border-left: 1px solid var(--border);
}
.trust-item:first-child { border-left: 0; }
/* Icon sits on a dark rounded plate — same move as the mission stat cards. */
.trust-item-ico {
  width: 44px; height: 44px; border-radius: 12px;
  background: var(--ink); color: #FFFFFF;
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: clamp(10px, 1.5vw, 16px);
}
/* Glyph is masked in from assets/icons/*.svg — the modifier class picks the
   file. It used to be an inline `style="--ico: url(…)"`, which broke the
   project's no-inline-style rule AND was what this selector keyed off, so the
   selector had to change with it. Needs HTTP serving: file:// blocks the SVG. */
.trust-item-ico--lock-keyhole      { --ico: url(../assets/icons/lock-keyhole.svg); }
.trust-item-ico--clock             { --ico: url(../assets/icons/clock.svg); }
.trust-item-ico--globe             { --ico: url(../assets/icons/globe.svg); }
.trust-item-ico--card-1            { --ico: url(../assets/icons/card-1.svg); }
.trust-item-ico--99-on-benchmark   { --ico: url(../assets/icons/99-on-benchmark.svg); }
.trust-item-ico--re-trained-weekly { --ico: url(../assets/icons/Re-trained-weekly.svg); }
.trust-item-ico--never-stored      { --ico: url(../assets/icons/Never-stored.svg); }
.trust-item-ico--no-card-to-start  { --ico: url(../assets/icons/No-card-to-start.svg); }
.trust-item-ico::after {
  content: "";
  display: block;
  width: 24px; height: 24px;
  background-color: currentColor;
  -webkit-mask-image: var(--ico);
          mask-image: var(--ico);
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
}
.trust-item-title { font-weight: 500; font-size: 15px; letter-spacing: -0.01em; color: var(--text); }
.trust-item-sub { font-size: 12.5px; line-height: 1.45; color: var(--text-muted); }

/* Dark variant — flips bg + colors. Add `.trust-strip-dark` alongside
   `.trust-strip`. Lime icons on a subtle dark container give the same
   visual rhythm as the dark hero panel / .cta-strip. */

/* Plan comparison table */
.compare-wrap {
  background: var(--compare-bg, var(--surface)); border: 1px solid var(--compare-border, var(--border));
  border-radius: var(--r-xl); overflow-x: auto;
}
.compare-table { width: 100%; min-width: 720px; border-collapse: collapse; }
.compare-table th, .compare-table td {
  padding: 16px 20px; text-align: center; font-size: 14.5px;
  border-bottom: 1px solid var(--compare-border, var(--border));
}
.compare-table thead th {
  font-weight: 500; font-size: 13px; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text); background: var(--compare-head-bg, var(--surface-2));
}
.compare-table thead .compare-col-popular { color: var(--link); }
.compare-table tbody th {
  text-align: left; font-weight: 500; color: var(--text);
  width: 38%; background: var(--compare-bg, var(--surface));
}
.compare-table tbody td { color: var(--text-muted); }
.compare-table tbody tr:last-child th,
.compare-table tbody tr:last-child td { border-bottom: 0; }
/* Subtle accent tint on the popular (3rd) column */
.compare-table thead th:nth-child(3),
.compare-table tbody td:nth-child(3) { background: var(--compare-highlight, rgba(53,102,239,0.06)); }
.compare-check {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--success);
}
.compare-dash { color: var(--text-muted-2); }

/* ============================================================
   Plagiarism Checker page — big hero form
   ============================================================ */
.check-hero { padding-top: var(--hero-top); padding-bottom: clamp(48px, 6vw, 80px); }
/* Same pastel-bloom panel as the landing hero — the copy and the scanner both
   sit on the wash, the white form/aside cards float on it. The panel IS the
   .wrap, so it overrides the wrap's gutter padding with its own. */
.check-hero-panel {
  position: relative;
  background: var(--bloom);
  border-radius: 36px;
  padding: clamp(32px, 4.5vw, 56px);
}
/* The AI detector's hero is the same component (client call — "розміщення форми
   як на plagiarism checker"): same bloom panel, same left-aligned head, same
   form + aside grid. Its head used to be centred, which is why the .ai-* names
   still exist — they are the same rule now, merged rather than duplicated.
   (They are kept as separate class names, not renamed to .check-*: .ai-hero-title
   is one arm of the :is() that drives the line-rise delays, and prune-css.js
   deletes a whole rule when ANY class in an :is() list goes dead — it would take
   the checker's, the text hero's and contact's rise delays with it.) */
.check-hero-head,
.ai-hero-head { display: flex; flex-direction: column; gap: var(--head-gap); max-width: 760px; margin-bottom: 40px; }
.check-hero-title,
.ai-hero-title { display: flex; flex-direction: column; }
.check-hero-lead,
.ai-hero-lead { max-width: 600px; margin: 0; }
.check-hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: 24px; align-items: start;
}

/* Main form card */
.check-form { padding: clamp(20px, 2.6vw, 36px); display: flex; flex-direction: column; gap: 22px; }
.check-form-tabs {
  position: relative;
  display: inline-flex; gap: 4px; padding: 4px;
  background: var(--surface-2); border-radius: var(--r-pill);
  width: fit-content;
}
/* Sliding pill behind the active tab. JS sets --tab-pill-x / --tab-pill-w
   from the active .check-tab's offsetLeft / offsetWidth; CSS animates. */
.check-form-tabs::before {
  content: "";
  position: absolute;
  top: 4px; bottom: 4px; left: 0;
  width: var(--tab-pill-w, 0);
  transform: translateX(var(--tab-pill-x, 0));
  background: var(--surface);
  box-shadow: 0 1px 3px rgba(15,18,20,0.08);
  border-radius: var(--r-pill);
  transition: transform .3s var(--ease-out), width .3s var(--ease-out);
  pointer-events: none;
  z-index: 0;
}
.check-tab {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 18px; border-radius: var(--r-pill);
  font-weight: 500; font-size: 14px; color: var(--text-muted);
  background: transparent;
  transition: color .25s var(--ease-out);
}
.check-tab:hover { color: var(--text); }
.check-tab.is-active { color: var(--text); }
.check-tab svg { width: 16px; height: 16px; }

.check-form-pane { display: flex; flex-direction: column; gap: 18px; }
.check-form-pane[hidden] { display: none; }

/* Dashed dropzone */
.check-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
  min-height: 280px; padding: 40px 24px; text-align: center;
  border: 2px dashed var(--border); border-radius: var(--r-lg);
  background: var(--surface-2);
  transition: border-color .25s var(--ease-out), background .25s;
}
.check-dropzone.is-over {
  border-color: var(--primary-2); background: var(--primary-soft);
}
/* 3D chrome upload object (Magnific, RGBA cutout) — the same liquid-chrome
   decor language as the hero quote-marks right above it. Lifts on drag-over
   so the dropzone answers the pointer.
   The file is a 240px WebP (3× the 80px render) — the 480px PNG it started
   as weighed 204KB for an 80px decoration. */
.check-dropzone-art {
  width: 80px; height: 80px;
  object-fit: contain;
  filter: drop-shadow(0 12px 18px rgba(15, 18, 20, 0.22));
  pointer-events: none;
  transition: transform .35s var(--ease-out);
}
.check-dropzone:hover .check-dropzone-art { transform: translateY(-4px); }
.check-dropzone.is-over .check-dropzone-art { transform: translateY(-10px) scale(1.04); }
@media (prefers-reduced-motion: reduce) {
  .check-dropzone-art { transition: none; }
  .check-dropzone:hover .check-dropzone-art,
  .check-dropzone.is-over .check-dropzone-art { transform: none; }
}

.check-dropzone-hint { color: var(--text-muted-2); font-size: 13px; margin-top: -4px; }

/* Textarea pane */
.check-textarea { min-height: 280px; resize: vertical; }
.check-form-meta {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  justify-content: space-between;
}
/* Let the encrypt text fill the remaining row width (wrapping to multi-line
   if needed) so the submit button stays anchored to the right edge instead
   of wrapping below when the text gets long. */
.check-form-meta-left { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.check-form-meta > .btn { flex-shrink: 0; }
.check-wordcount { font-family: var(--font-mono); font-weight: 500; font-size: 12px; color: var(--text-muted); text-transform: none; letter-spacing: 0.02em; }
.check-wordcount strong { color: var(--text); font-weight: 600; }
/* Inline "Encrypted in transit" reassurance sits inside .check-form-meta-left,
   next to the wordcount / supported-formats info — replaces the standalone
   .check-form-foot row that sat below both meta + CTA. */
.check-form-encrypt {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--text-muted); font-size: 12px; line-height: 1.4;
}
.check-form-encrypt svg { width: 12px; height: 12px; color: var(--text-muted-2); flex-shrink: 0; }

/* Top header row of .check-form: tabs left + pane-specific info right on
   desktop; stacks under the tabs on tablet/phone. .check-wordcount belongs
   to the Paste pane, .check-form-formats to Upload — :has() shows whichever
   pane is currently active. */
.check-form-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.check-form-formats {
  display: inline-flex; flex-direction: column; gap: 2px;
  align-items: flex-end; text-align: right;
}
/* Paste active → hide formats; Upload active → hide wordcount. */
.check-form:has(.check-form-pane[data-pane="paste"]:not([hidden])) .check-form-head .check-form-formats { display: none; }
.check-form:has(.check-form-pane[data-pane="upload"]:not([hidden])) .check-form-head .check-wordcount { display: none; }
@media (max-width: 1100px) {
  .check-form-head { flex-direction: column; align-items: stretch; gap: 12px; }
  .check-form-formats { align-items: flex-start; text-align: left; }
}

/* ============================================================
   Check-form flow states — selected-file list, progress bars,
   inline errors, the "analyzing…" stage and the result card
   (free-preview numbers OR locked report). Driven by JS in
   script.js; the report itself lives in the user cabinet, so the
   terminal state here always funnels toward sign-up.
   ============================================================ */

/* Compact the dropzone once at least one file is queued — JS hides
   it entirely and shows the list + an "add more" trigger, but the
   compact rule keeps the drag target usable on the drop-more path. */
.check-form-pane.has-files .check-dropzone { display: none; }
.check-dropzone.is-full { opacity: .55; pointer-events: none; }
.check-form-pane.is-over .check-dropzone { border-color: var(--primary-2); background: var(--primary-soft); }

/* ---- Selected-file list ---- */
.check-filelist { display: flex; flex-direction: column; gap: 10px; }
.check-filelist[hidden] { display: none; }
.check-file-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2);
}
.check-file-row-ico {
  flex-shrink: 0; width: 36px; height: 36px; display: grid; place-items: center;
  border-radius: 9px; background: var(--surface); border: 1px solid var(--border);
  color: var(--text-muted);
}
.check-file-row-ico svg { width: 16px; height: 16px; }
.check-file-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.check-file-row-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.check-file-row-name {
  font-size: 14px; font-weight: 500; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.check-file-row-size {
  font-family: var(--font-mono); font-weight: 500; font-size: 11px;
  color: var(--text-muted-2); white-space: nowrap; flex-shrink: 0;
}
.check-file-row.is-done .check-file-row-size { color: var(--success); }
.check-file-remove {
  flex-shrink: 0; width: 28px; height: 28px; display: grid; place-items: center;
  border: none; border-radius: 8px; background: transparent; color: var(--text-muted-2);
  cursor: pointer; transition: background .2s var(--ease-out), color .2s var(--ease-out);
}
.check-file-remove:hover { background: var(--surface-3); color: var(--text); }
.check-file-remove svg { width: 14px; height: 14px; }

/* ---- Reusable progress bar ---- */
.check-progress {
  position: relative; height: 5px; border-radius: 99px; overflow: hidden;
  background: var(--surface-3);
}
.check-progress-bar {
  position: absolute; inset: 0 auto 0 0; width: 0;
  border-radius: 99px; background: var(--primary-2);
  transition: width .2s var(--ease-out);
}
.check-file-row.is-done .check-progress-bar { background: var(--success); }

/* ---- "Add more files" trigger under the list ---- */
.check-addmore {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 7px;
  padding: 0; border: none; background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 13px; font-weight: 500; color: var(--success);
  transition: color .2s var(--ease-out);
}
.check-addmore:hover { color: var(--ink); }
.check-addmore svg { width: 14px; height: 14px; }
.check-addmore[hidden] { display: none; }

/* ---- Inline error banner ---- */
.check-error {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--alert) 13%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--alert) 42%, var(--border));
  color: var(--text); font-size: 13.5px; line-height: 1.45;
}
.check-error[hidden] { display: none; }
.check-error svg { width: 16px; height: 16px; color: var(--alert); flex-shrink: 0; margin-top: 1px; }
.check-error strong { font-weight: 600; }

/* The injected upload scan button is hidden until files are queued. */
.check-scan[hidden] { display: none; }

/* ---- Analyzing… stage (text scan) ---- */
.check-scanning {
  display: flex; flex-direction: column; gap: 16px; align-items: center;
  text-align: center; padding: 48px 24px;
}
.check-scanning[hidden] { display: none; }
.check-scanning-label { font-size: 15px; font-weight: 500; color: var(--text); }
.check-scanning-sub { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted-2); }
.check-scanning .check-progress { width: min(360px, 80%); height: 6px; }

/* ---- Result card (terminal state) ---- */
.check-result { display: none; }
.check-form[data-stage="scanning"] .check-form-head,
.check-form[data-stage="scanning"] .check-form-pane,
.check-form[data-stage="result"] .check-form-head,
.check-form[data-stage="result"] .check-form-pane { display: none; }
.check-form[data-stage="result"] .check-result {
  display: flex; flex-direction: column; align-items: center; gap: 18px;
  text-align: center; padding: 8px 0 4px;
}
.check-result-badge {
  width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center;
  background: var(--primary-soft); color: var(--success);
}
.check-result-badge.is-lock { background: var(--surface-3); color: var(--text-muted); }
.check-result-badge svg { width: 26px; height: 26px; }
.check-result-title { font-size: clamp(20px, 3vw, 25px); letter-spacing: -0.02em; }
.check-result-lead { color: var(--text-muted); max-width: 48ch; line-height: 1.5; }

.check-figures {
  position: relative; display: flex; gap: 14px; justify-content: center;
  flex-wrap: wrap; margin: 4px 0;
}
.check-figure {
  min-width: 148px; padding: 20px 26px; border-radius: var(--r-md);
  border: 1px solid var(--border); background: var(--surface-2);
  display: flex; flex-direction: column; gap: 6px; align-items: center;
}
.check-figure-num { font-size: 34px; font-weight: 600; letter-spacing: -0.03em; line-height: 1; color: var(--text); }
.check-figure-num.is-good { color: var(--success); }
.check-figure-num.is-warn { color: var(--alert); }
.check-figure-label {
  font-family: var(--font-mono); font-weight: 500; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted);
}
/* Locked: blur the numbers behind a lock chip so the shape of the
   report is visible but the values are gated. */
.check-figures.is-locked .check-figure-num { filter: blur(9px); user-select: none; }
.check-result-lockchip {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 99px;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-2);
  font-family: var(--font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--text);
}
.check-result-lockchip svg { width: 13px; height: 13px; color: var(--text-muted); }

.check-result-actions {
  display: flex; gap: 12px; flex-wrap: wrap; justify-content: center;
  margin-top: 6px;
}
@media (max-width: 560px) {
  .check-result-actions { flex-direction: column; align-items: stretch; width: 100%; }
}

/* Aside "Included with every scan" */
.check-aside { padding: 32px; display: flex; flex-direction: column; gap: 20px; align-self: start; }
.check-aside-title { font-size: 17px; letter-spacing: -0.02em; }
.check-aside-list { display: flex; flex-direction: column; gap: 14px; }
.check-aside-list li { display: flex; align-items: flex-start; gap: 12px; font-size: 14.5px; color: var(--text); line-height: 1.4; }
.check-aside-ico {
  width: 22px; height: 22px; border-radius: 999px; flex-shrink: 0;
  background: var(--primary); color: var(--primary-ink, #FFFFFF);
  display: inline-flex; align-items: center; justify-content: center;
}
.check-aside-ico svg { width: 12px; height: 12px; }
.check-aside-foot { display: flex; align-items: center; gap: 14px; padding-top: 4px; border-top: 1px solid var(--border); padding-top: 18px; }
.check-aside-stars { display: inline-flex; gap: 2px; color: var(--primary-2); }
.check-aside-score { display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; color: var(--text); font-weight: 500; }
.check-aside-score .mono { font-size: 10.5px; letter-spacing: 0.04em; }

/* Showcase slides — placeholder cards for future screenshots */
/* Feature cards left, one abstract image right, both the same height (client
   call). The old per-card "slide" wells were UI placeholders — they read as an
   unfinished page, so they are gone.

   Equal height is the whole trick, and it only works if ONE side owns the
   height: the cards do. The panel is therefore intrinsically height-less — its
   image is absolutely positioned, so it contributes nothing to the row — and
   the grid's default `stretch` then pulls the panel to whatever the card column
   came out at, with object-fit: cover doing the rest. Give the image a normal
   height and the two sides fight over the row instead. */

/* Flat card + dark icon plate — the same card language as .value-card. The icon
   sits inline with the title (as on the mission stat cards) to keep the stack
   short enough that the image beside it is not cropped to a sliver. */

/* ============================================================
   Auth pages (sign in / sign up) — shared
   ============================================================ */

/* Minimal topbar replaces the site nav on auth pages: logo top-left,
   close (X) top-right. position: fixed so it overlays without taking
   vertical space; pointer-events: none on the bar lets clicks pass
   through the empty space between logo and X (children get :auto). */
.auth-topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--pad-card);
  pointer-events: none;
}
.auth-topbar > * { pointer-events: auto; }
.auth-close {
  width: 40px; height: 40px; border-radius: 999px;
  background: var(--surface-2); color: var(--text);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .2s, color .2s, transform .2s var(--ease-out);
}
.auth-close:hover { background: var(--ink); color: #F4F3F2; }
.auth-close svg { width: 14px; height: 14px; }

/* Auth hero — fills the full viewport (topbar is fixed and doesn't push
   content down), content vertically centered.

   The background is the hero's pastel bloom, set adrift (client call). --bloom
   is four radial gradients over a base colour, and animating a multi-radial
   `background-position` repaints the whole surface every frame — so the colours
   are split across the two pseudo-elements instead and only `transform` moves.
   That is compositor-only: no repaint, no layout, and it stays smooth under a
   full-viewport wash.

   Each layer carries two of the bloom's four blobs and drifts on its own slow
   loop (37s / 29s — coprime, so the composite never visibly repeats). They are
   inset -25% so the drift can never walk an edge into frame. Motion is opt-IN:
   the static state below is the finished look, and the keyframes only run under
   prefers-reduced-motion: no-preference. */
.auth-hero {
  position: relative;
  overflow: hidden;
  background-color: #F2F4F8;
  padding-top: clamp(20px, 4vw, 40px);
  padding-bottom: clamp(40px, 6vw, 80px);
  min-height: 100vh;
  display: flex; align-items: center;
}
.auth-hero::before,
.auth-hero::after {
  content: "";
  position: absolute;
  inset: -25%;
  pointer-events: none;
  will-change: transform;
}
/* Layer A — periwinkle bottom-left + lavender bottom-right */
.auth-hero::before {
  background:
    radial-gradient(52% 72% at 18% 76%, #C7D7FA 0%, rgba(199, 215, 250, 0) 70%),
    radial-gradient(42% 58% at 66% 86%, #DFD6F9 0%, rgba(223, 214, 249, 0) 72%);
  transform: translate3d(-1%, 1%, 0) scale(1);
}
/* Layer B — ice top-right + the pale centre wash */
.auth-hero::after {
  background:
    radial-gradient(46% 64% at 82% 18%, #CFEDF4 0%, rgba(207, 237, 244, 0) 70%),
    radial-gradient(70% 90% at 40% 26%, #EDF1F9 0%, rgba(237, 241, 249, 0) 82%);
  transform: translate3d(1%, -1%, 0) scale(1.06);
}
/* Plain `ease-in-out`, deliberately NOT the --ease-in-out token: that curve is
   cubic-bezier(0.65, 0, 0.35, 1), which accelerates and brakes hard. Right for a
   300ms UI transition, wrong for a 37s ambient drift — it would hang at the ends
   and rush the middle, reading as a pulse. The keyword is close to a sine wave. */
@media (prefers-reduced-motion: no-preference) {
  .auth-hero::before { animation: authDriftA 37s ease-in-out infinite alternate; }
  .auth-hero::after  { animation: authDriftB 29s ease-in-out infinite alternate; }
}
/* Amplitude is measured, not guessed. At ±3% travel the composite moved a mean
   of 2.8/255 across 18s — below the threshold of noticing, i.e. it read as a
   static gradient. These numbers put it at a mean ~9 and a peak ~30, which is
   visible as a slow breathing wash without ever becoming a moving background.
   The layers are inset -25%, so a 10% translate (10% of the LAYER = 15% of the
   viewport) plus scale(1.3) still leaves overhang — an edge can never walk in. */
@keyframes authDriftA {
  from { transform: translate3d(-7%, 5%, 0) scale(1); }
  to   { transform: translate3d(9%, -7%, 0) scale(1.3); }
}
@keyframes authDriftB {
  from { transform: translate3d(8%, -6%, 0) scale(1.26); }
  to   { transform: translate3d(-9%, 7%, 0) scale(1); }
}
/* The form sits above the wash. */
.auth-hero > .wrap { position: relative; z-index: 1; width: 100%; }

.auth-form { padding: clamp(28px, 3vw, 40px); display: flex; flex-direction: column; gap: 22px; }
/* Form top-row: logo left, close-X right. Shown only on tablet+phone where
   the fixed .auth-topbar overlay is hidden (rule below in the ≤1100 block). */
.auth-form-topbar {
  display: none; align-items: center; justify-content: space-between; gap: 12px;
}
/* Cancel the mobile-nav .logo margin overrides (margin-left:8px tablet,
   margin-left:auto on phone) — those exist to position the nav logo and
   would otherwise nudge or centre the form logo here. */
.auth-form-topbar .logo { margin: 0; }
.auth-form-head { display: flex; flex-direction: column; gap: 8px; }
.auth-form-title { font-size: 26px; letter-spacing: -0.03em; line-height: 1.2; }
.auth-form-sub { color: var(--text-muted); font-size: 14.5px; line-height: 1.5; margin: 0; }

.auth-pane { display: flex; flex-direction: column; gap: 18px; }
.auth-pane[hidden] { display: none; }

/* Social row — two buttons side-by-side so the sign-up form fits on
   one screen. Stacks back to single column on narrow phones. */
.auth-social { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.auth-social-btn { width: 100%; justify-content: center; }
.auth-social-btn > .auth-social-ico { padding: 0; }
.auth-social-ico { display: inline-flex; align-items: center; }
.auth-social-ico svg { width: 18px; height: 18px; display: block; }

/* "or use email" divider */
.auth-or {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--font-mono); font-weight: 500;
  font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-muted-2);
}
.auth-or::before, .auth-or::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}

/* Field-row variant: label + inline link (e.g. "Password [Forgot?]") */
.auth-field-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.auth-link { color: var(--link); font-size: 13px; font-weight: 500; transition: color .2s; }
.auth-link:hover { text-decoration: underline; text-underline-offset: 2px; }

.auth-submit { width: 100%; justify-content: center; margin-top: 4px; }

.auth-foot {
  font-size: 13.5px; color: var(--text-muted);
  margin: 8px 0 0; text-align: center;
}

/* ============================================================
   Auth — centered form, nothing else
   ============================================================ */
/* There were two variants: a split-screen with a brand panel (a portrait photo
   behind a rotating testimonial, fed by a JS table of 4 quotes + 4 PNGs) and
   this centered one. The client took the centered form and dropped the panel,
   so the split is gone — markup, its 14 CSS classes, the JS block and the
   7.2 MB of portraits — and signin-alt.html with it: once signin.html adopted
   .auth-centered the two files were byte-identical and nothing linked to alt. */
.auth-centered { display: flex; flex-direction: column; align-items: center; gap: 32px; }
.auth-centered .auth-form { width: 100%; max-width: 480px; }

/* Auth form tabs (Sign in / Create account) take the full card width on
   desktop and phone — each tab grabs 50%. Tablet (721-1100) keeps the
   default inline pill since the card is wider relative to the labels. */
@media (min-width: 1101px) {
  #authForm .check-form-tabs { display: flex; width: 100%; }
  #authForm .check-tab { flex: 1; justify-content: center; }
}

/* ============================================================
   AI Detector page — centered hero + full-width form (distinct
   first-screen variant vs the plagiarism checker)
   ============================================================ */
.ai-hero { padding-top: var(--hero-top); padding-bottom: clamp(48px, 6vw, 80px); }
/* The head/title/lead rules live with the checker's — they are literally the
   same component now. See the Plagiarism Checker block above. */

/* The form fills its grid column. It used to span the whole wrap with no aside;
   the width: 100% is what is left of that and is still what makes it fill the
   1.55fr track rather than shrink to its content. */
.ai-form { width: 100%; }

/* Models chip row — shows what AI models we detect, mono kicker + chips */
/* Left-aligned, not centred: it sits under a left-aligned head and an
   asymmetric form+aside grid, so a centred row would read as a stray. */
.ai-models {
  margin-top: 28px;
  display: flex; align-items: center; justify-content: flex-start; flex-wrap: wrap;
  gap: 10px;
}
.ai-models-label {
  font-family: var(--font-mono); font-weight: 500;
  font-size: var(--fs-11); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted-2);
  margin-right: 4px;
}
.ai-model-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border);
  font-size: 13px; font-weight: 500; color: var(--text);
}
.ai-model-chip::before {
  content: ""; width: 6px; height: 6px; border-radius: 999px;
  background: var(--primary);
}

/* Big alternating slide rows for product showcases — replaces tiny
   3-in-a-row cards. Media + detailed text side-by-side. */
.showcase-rows {
  display: flex; flex-direction: column;
  gap: clamp(48px, 6vw, 88px);
}
.showcase-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}
.showcase-row:nth-child(even) .showcase-row-media { order: 2; }
/* Carries a Nano Banana illustration, not a "slide goes here" well (client
   call — the placeholders read as an unfinished page). Same treatment as the
   landing's audience graphics: multiply melts the render's near-white backdrop
   into the card, so no cut-out is needed. */
.showcase-row-media {
  aspect-ratio: 3 / 2;
  background: var(--card-flat);
  border-radius: var(--r-2xl);
  display: flex; align-items: center; justify-content: center;
  padding: var(--pad-card);
  overflow: hidden;
}
.showcase-row-media img {
  width: 100%; height: auto; display: block;
  object-fit: contain;
  mix-blend-mode: multiply;
}
.showcase-row-content { display: flex; flex-direction: column; gap: 16px; }
.showcase-row-num {
  font-family: var(--font-mono); font-weight: 500;
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--link);
}
/* Sits on the h-2 step of the scale — it used to be a fourth bespoke clamp. */
.showcase-row-title {
  font-size: var(--fs-h-2);
  letter-spacing: -0.03em; line-height: 1.18; margin: 0;
}
.showcase-row-text {
  font-size: 15px; line-height: 1.6;
  color: var(--text-muted); margin: 0;
  max-width: 480px;
}
.showcase-row-list {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 4px; padding: 0;
}
.showcase-row-list li {
  display: flex; align-items: flex-start; gap: 12px;
  font-size: 14.5px; line-height: 1.5; color: var(--text);
}
.showcase-row-list li::before {
  content: ""; flex-shrink: 0; margin-top: 7px;
  width: 8px; height: 8px; border-radius: 999px;
  background: var(--primary);
}

/* ============================================================
   Legal pages (privacy, terms, cookie policy, etc.)
   ============================================================ */
.legal-hero {
  padding-top: var(--space-lg);
  padding-bottom: clamp(40px, 5vw, 64px);
}
.legal-hero-inner {
  max-width: 840px;
  display: flex; flex-direction: column; gap: 18px;
}
.legal-hero-lead { max-width: 640px; margin: 0; }
.legal-hero-meta {
  display: flex; flex-wrap: wrap; gap: 16px 32px;
  margin-top: 8px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.legal-hero-meta-item { display: flex; flex-direction: column; gap: 4px; }
.legal-hero-meta-label {
  font-family: var(--font-mono); font-weight: 500;
  font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted-2);
}
.legal-hero-meta-value { font-size: 14px; font-weight: 500; color: var(--text); }

/* Two-column body: TOC sidebar + content area */
.legal-grid {
  display: grid; grid-template-columns: 240px minmax(0, 1fr);
  gap: 64px; align-items: start;
}
.legal-toc {
  position: sticky; top: 100px;
  display: flex; flex-direction: column; gap: 2px;
}
.legal-toc-label {
  font-family: var(--font-mono); font-weight: 500;
  font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted-2);
  margin-bottom: 12px;
}
.legal-toc a {
  display: block;
  padding: 6px 0;
  font-size: 13.5px; line-height: 1.4;
  color: var(--text-muted);
  transition: color .2s, padding-left .2s var(--ease-out);
}
.legal-toc a:hover { color: var(--text); padding-left: 4px; }
.legal-toc a.is-active { color: var(--link); font-weight: 500; }

/* Content typography */
.legal-content { max-width: 720px; }
.legal-section { margin-bottom: 56px; scroll-margin-top: 100px; }
.legal-section:last-child { margin-bottom: 0; }
.legal-section-num {
  font-family: var(--font-mono); font-weight: 500;
  font-size: var(--fs-11); letter-spacing: 0.06em;
  color: var(--success);
  display: block; margin-bottom: 8px;
}
.legal-section h2 {
  font-size: clamp(22px, 2.4vw, 28px);
  letter-spacing: -0.025em; line-height: 1.2;
  margin: 0 0 20px;
}
.legal-section h3 {
  font-size: 17px; letter-spacing: -0.02em; line-height: 1.3;
  margin: 28px 0 10px;
}
.legal-section p {
  font-size: 15px; line-height: 1.7;
  color: var(--text-muted);
  margin: 0 0 16px;
}
.legal-section ul, .legal-section ol {
  margin: 0 0 16px;
  padding: 0;
  display: flex; flex-direction: column; gap: 10px;
  list-style: none;
}
.legal-section li {
  font-size: 15px; line-height: 1.65;
  color: var(--text-muted);
  padding-left: 22px;
  position: relative;
}
.legal-section ul li::before {
  content: "";
  position: absolute; left: 0; top: 10px;
  width: 6px; height: 6px; border-radius: 999px;
  background: var(--primary);
}
.legal-section ol { counter-reset: legal-list; }
.legal-section ol li {
  counter-increment: legal-list;
  padding-left: 28px;
}
.legal-section ol li::before {
  content: counter(legal-list) ".";
  position: absolute; left: 0; top: 0;
  font-family: var(--font-mono); font-weight: 500;
  color: var(--success);
}
.legal-section strong { color: var(--text); font-weight: 600; }
.legal-section a {
  color: var(--link);
  text-decoration: underline; text-underline-offset: 2px;
}

/* ============================================================
   SEO / Learn — editorial long-form block for the landing. Eyebrow +
   H2 head, a large lead statement (mission-title scale), then rows of
   left subhead rail / right prose. A "Show more" button reveals the
   rest. Body typography (h4–h6, lists, callout, terms, .compare-table)
   is built on the same tokens as .legal-section so it stays theme-aware.
   ============================================================ */
.seo { --seo-rail: 280px; --seo-gap: 32px; }
.seo-head { margin-bottom: 20px; }
.seo-head .eyebrow { margin-bottom: var(--head-gap); }
/* Title is an .h-1 like every other section title — this only sets its measure. */
.seo-title { max-width: var(--head-measure); }
.seo-meta {
  font-family: var(--font-mono); font-weight: 500;
  font-size: var(--fs-11); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted-2); margin: 10px 0 0;
}
/* Big lead statement — mission-title scale, indented to align with the prose column */
.seo-statement {
  font-weight: 600; font-size: clamp(22px, 2.8vw, 32px); line-height: 1.3; letter-spacing: -0.025em;
  color: var(--text); max-width: 660px;
  margin: 0 0 var(--space-lg) calc(var(--seo-rail) + var(--seo-gap));
}
/* Scroll-linked word ink (script.js splits into .word + sets data-ink) —
   same three discrete states as .mission-title. */
.seo-statement .word { color: var(--text); opacity: .22; }
.seo-statement .word[data-ink="green"] { color: var(--primary-2); opacity: 1; }
.seo-statement .word[data-ink="done"] { color: var(--text); opacity: 1; }
/* Editorial rows: sticky left subhead rail + right prose column */
.seo-rows { display: flex; flex-direction: column; }
.seo-row {
  display: grid; grid-template-columns: var(--seo-rail) 1fr; gap: var(--seo-gap); align-items: start;
  padding: 30px 0; border-top: 1px solid var(--border);
}
.seo-row-head { position: sticky; top: 96px; }
.seo-kicker {
  display: block; font-family: var(--font-mono); font-weight: 500;
  font-size: var(--fs-11); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--primary-2); margin-bottom: 10px;
}
.seo-row-head h3 { font-size: var(--fs-h-3); line-height: 1.22; letter-spacing: -0.02em; color: var(--text); }
.seo-row .seo-prose { max-width: 660px; margin: 0; }
.seo-more[hidden] { display: none; }
.seo-more-btn { margin: 28px 0 0 calc(var(--seo-rail) + var(--seo-gap)); }
.seo-prose h3 {
  font-size: clamp(19px, 1.9vw, 23px);
  line-height: 1.25; letter-spacing: -0.025em;
  margin: 46px 0 12px;
}
.seo-prose h4 {
  font-size: 17px; line-height: 1.3; letter-spacing: -0.02em;
  margin: 30px 0 8px;
}
.seo-prose h5 {
  font-size: 15px; font-weight: 600; line-height: 1.35; letter-spacing: -0.01em;
  color: var(--text); margin: 24px 0 6px;
}
.seo-prose h6 {
  font-family: var(--font-mono); font-weight: 500;
  font-size: var(--fs-11); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted-2); margin: 22px 0 6px;
}
.seo-prose p {
  font-size: 15.5px; line-height: 1.72; color: var(--text-muted);
  margin: 0 0 16px;
}
.seo-prose ul, .seo-prose ol {
  margin: 0 0 18px; padding: 0;
  display: flex; flex-direction: column; gap: 11px;
  list-style: none;
}
.seo-prose li {
  font-size: 15.5px; line-height: 1.65; color: var(--text-muted);
  padding-left: 26px; position: relative;
}
.seo-prose ul li::before {
  content: ""; position: absolute; left: 2px; top: 9px;
  width: 6px; height: 6px; border-radius: 999px; background: var(--primary);
}
.seo-prose ol { counter-reset: seo-list; }
.seo-prose ol li { counter-increment: seo-list; padding-left: 36px; }
.seo-prose ol li::before {
  content: counter(seo-list); position: absolute; left: 0; top: 0;
  width: 23px; height: 23px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-weight: 500; font-size: 12px;
  color: var(--primary-ink); background: var(--primary);
}
.seo-prose p strong, .seo-prose li strong { color: var(--text); font-weight: 600; }
.seo-prose a {
  color: var(--link); text-decoration: underline; text-underline-offset: 2px;
  transition: color .2s var(--ease-out);
}
.seo-prose a:hover { color: var(--link-hover); }

/* Callout — a highlighted key takeaway, accent rule on the left */
.seo-callout {
  margin: 24px 0 28px; padding: 18px 22px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-left: 3px solid var(--primary); border-radius: var(--r-md);
}
.seo-callout p { margin: 0; color: var(--text); font-size: 15.5px; line-height: 1.62; }
.seo-callout p + p { margin-top: 10px; }

/* Key-terms glossary (definition list) */
.seo-terms { margin: 0 0 18px; padding: 0; border-top: 1px solid var(--border); }
.seo-terms div {
  display: grid; grid-template-columns: 190px 1fr; gap: 6px 24px;
  padding: 15px 0; border-bottom: 1px solid var(--border);
}
.seo-terms dt { font-weight: 600; color: var(--text); font-size: 15px; }
.seo-terms dd { margin: 0; color: var(--text-muted); font-size: 15px; line-height: 1.6; }

/* Shared compare table inside prose: fit the narrow column, stay neutral
   (no "popular" column tint — this is an explanatory, not a ranked, table) */
.seo-prose .compare-wrap { margin: 8px 0 26px; }
.seo-prose .compare-table { min-width: 520px; }
.seo-prose .compare-table th:nth-child(3),

.seo-prose .compare-table td:nth-child(3) { background: transparent; }

@media (max-width: 860px) {
  .seo { --seo-rail: 0px; --seo-gap: 0px; }
  .seo-row { grid-template-columns: 1fr; gap: 12px; padding: 24px 0; }
  .seo-row-head { position: static; }
}
@media (max-width: 720px) {
  .seo-terms div { grid-template-columns: 1fr; gap: 2px; padding: 13px 0; }
}

/* ============================================================
   Cookies banner — bottom-left card on the landing, shown after 5s
   ============================================================ */
.cookies-overlay {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(0, 0, 0, 0.1);
  opacity: 0;
  transition: opacity .45s var(--ease-out);
  pointer-events: none; /* visual dim only; clicks pass through */
}
.cookies-overlay.is-shown { opacity: 1; }

.cookies-banner {
  position: fixed;
  left: 24px; bottom: 24px;
  z-index: 60;
  max-width: 420px;
  padding: var(--pad-card);
  opacity: 0; transform: translateY(20px);
  transition: opacity .45s var(--ease-out), transform .45s var(--ease-out);
  pointer-events: none;
}
.cookies-banner.is-shown { opacity: 1; transform: translateY(0); pointer-events: auto; }
.cookies-banner-title { font-size: 18px; letter-spacing: -0.02em; line-height: 1.25; margin: 0; }
.cookies-banner-text { font-size: 14px; line-height: 1.55; color: var(--text-muted); margin: 12px 0 0; }
.cookies-banner-text a { color: var(--link); text-decoration: underline; text-underline-offset: 2px; }
.cookies-banner-actions { display: flex; gap: 10px; margin-top: 20px; }
.cookies-banner-actions .btn { flex: 1; }

/* ============================================================
   404 — "no match found" error page
   Scan-themed 404 used by 404.html: the middle "0" is a radar-sweep
   orb (reuses the report-ring metaphor), and the missing URL is framed
   as a scan that returned no match. Centered, viewport-filling hero.
   ============================================================ */
.error-section {
  position: relative;
  display: flex;
  align-items: center;
  min-height: calc(100vh - 200px);
  overflow: hidden;
}
.error-inner {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 26px;
}

/* Giant 404 — two display numerals flanking the scan orb (the "0").
   The 4s are solid ink; the 0 is the accented scanner — intentional
   hierarchy. Digits reuse the line-rise mask reveal from the hero. */
.error-code {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.4vw, 18px);
  line-height: 0.9;
  margin-top: 4px;
}
.error-digit {
  font-size: clamp(86px, 22vw, 240px);
  font-weight: 600;
  letter-spacing: -0.05em;
  color: var(--text);
}

/* Scan orb = the "0". A faint ring outlines the zero; a short lime arc
   sweeps it like a radar pointer (= still searching); a soft lime glow
   sits behind; a magnifier marks the empty result. */
.error-orb {
  position: relative;
  flex-shrink: 0;
  width: clamp(84px, 20vw, 220px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}
.error-orb::before {
  content: "";
  position: absolute;
  inset: -16%;
  border-radius: 999px;
  background: radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--primary) 48%, transparent) 0%, transparent 66%);
  filter: blur(10px);
  opacity: 0.9;
  z-index: -1;
}
.error-orb-svg { width: 100%; height: 100%; display: block; }
.error-orb-track { stroke: color-mix(in srgb, var(--text) 16%, transparent); }
.error-orb-sweep {
  stroke: var(--primary-2);
  transform-box: view-box;
  transform-origin: 110px 110px;
  animation: orbSweep 3.6s linear infinite;
}
@keyframes orbSweep { to { transform: rotate(360deg); } }
.error-orb-center {
  position: absolute;
  display: grid;
  place-items: center;
  color: var(--primary-2);
  animation: orbFloat 3s var(--ease-in-out) infinite;
}
.error-orb-center svg { width: clamp(30px, 6.5vw, 60px); height: auto; }
@keyframes orbFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-5px); }
}
@media (prefers-reduced-motion: reduce) {
  .error-orb-sweep, .error-orb-center { animation: none; }
}

.error-title { max-width: 16ch; }
.error-lead { max-width: 540px; margin: 0; }

.error-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 2px;
}

.error-links {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 560px;
  margin-top: 10px;
  padding-top: 28px;
  border-top: 1px solid var(--border);
}
.error-links-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 1100px) {
  :root { --section-head-gap: 44px; } /* tablet */
  /* Tablet nav: burger appears LEFT of logo, nav-links + Sign in hidden,
     primary button shrinks to .btn-xs sizing (and "— free" suffix drops). */
  .nav > button[aria-label="Menu"] { display: inline-flex; }
  .nav-links { display: none; }
  /* Tablet: logo sits right after burger; auto-margin pushes CTA to the far right. */
  .logo { margin-left: 8px; margin-right: auto; }
  .nav-cta .btn-ghost { display: none; }
  .nav-cta-suffix { display: none; }
  .nav-cta a.btn:last-child { height: 36px; font-size: 13px; }
  .nav { padding: 10px 16px; }
  /* Collapsed mission: the copy no longer needs the full width, so instead of
     one tall column with a dead gutter beside it, the head (eyebrow → link)
     and the credibility foot (avatars, "built by", rating) sit side by side,
     with the stat cards running full-width underneath. The foot drops the
     margin-top:auto / padding-top that pinned it to the bottom of the desktop
     column — in a row it has nothing to be pushed away from. */
  .mission-grid { grid-template-columns: minmax(0, 1fr); }
  .mission-left { flex-direction: row; align-items: flex-start; gap: clamp(28px, 4vw, 56px); }
  /* Both sides shrink, but only the head grows — so spare width goes to the
     copy, and on a tight tablet the two give way proportionally instead of the
     foot (a fixed 360px) out-widening the head it is supposed to support. */
  .mission-head { flex: 1 1 auto; min-width: 0; }
  .mission-foot { flex: 0 1 340px; min-width: 0; margin-top: 0; padding-top: 0; }
  /* Feature checkerboard collapses to a single column; wide cards lose the
     2-track span and the seam coin has no junction left to sit on. */
  .feat-grid { grid-template-columns: minmax(0, 1fr); }
  .feat-card--w2 { grid-column: auto; }
  .feat-card { min-height: 240px; }
  .feat-coin { display: none; }
  /* Pricing turns into a horizontal scroll-snap carousel from tablet down —
     three plans side by side stop fitting well before the phone breakpoint,
     and stacking them buries the third. The negative margins break the
     scroller out of .wrap's padding so it runs edge-to-edge; scroll-padding
     puts the snapped card back on the wrap's left gutter. Tablet shows two
     cards with the next peeking; the phone block below drops that to one. */
  .pricing-grid {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    /* overflow-y is forced to `auto` when overflow-x is non-visible; the
       large padding-bottom is the buffer that keeps card shadows unclipped. */
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--pad-x);
    gap: 16px;
    margin-left: calc(-1 * var(--pad-x));
    margin-right: calc(-1 * var(--pad-x));
    padding: 4px var(--pad-x) 64px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .pricing-grid::-webkit-scrollbar { display: none; }
  /* Visible track is (100vw - 2 × pad-x); two cards + one 16px gap + a 48px
     peek of the third divide that up, so the swipe affordance is always on
     screen. */
  .pricing-grid > .price-card {
    flex: 0 0 calc((100vw - 2 * var(--pad-x) - 64px) / 2);
    min-width: 0;
    scroll-snap-align: start;
  }
  .pricing-dots {
    display: flex;
    justify-content: center;
    gap: 10px;
    /* Pull the dots up into the scroller's 64px shadow-buffer so the visible
       card → dots gap reads as ~24px instead of 88px. */
    margin-top: -40px;
  }
  .footer-top { flex-direction: column; gap: 48px; }
  .footer-brand { width: 100%; }
  .section-head { grid-template-columns: minmax(0, 1fr); }
  .contact-help-grid { grid-template-columns: minmax(0, 1fr); }
  .contact-banner { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .contact-banner-media { order: -1; }
  .about-values-grid { grid-template-columns: 1fr 1fr; }
  .trust-strip { grid-template-columns: 1fr 1fr; gap: 8px 0; padding: 20px 8px; }
  .trust-item:nth-child(3) { border-left: 0; }
  .check-hero-grid { grid-template-columns: minmax(0, 1fr); }
  /* Auth: the fixed viewport-corner topbar gives way to the in-form one. The
     form is already centred at every width, so nothing else changes here. */
  .auth-topbar { display: none; }
  .auth-form-topbar { display: flex; }
  .showcase-row { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .showcase-row:nth-child(even) .showcase-row-media { order: 0; }
  .legal-grid { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .legal-toc {
    position: static;
    padding: 20px 24px;
    background: var(--surface-3);
    border-radius: var(--r-xl);
  }
}

/* The 1024 tier — where the desktop composition stops working, not where the
   tablet nav starts (that's 1100). Two client calls land here:

   · Hero keeps copy and check-form side by side down to 1024, and only stacks
     below it. NOTE the specificity trap: the 2-class `.hero--panel .hero-grid`
     desktop rule out-ranks a 1-class `.hero-grid` collapse, so the panel rule
     has to be repeated here at matching specificity or the columns survive.
   · Audience checkerboard: below 1024 the 3 tracks get small enough that the
     1-track cards squeeze to ~260px against ~545px wide ones — that reads as
     an accident, not an asymmetry. Four EQUAL cards, 2×2, instead.

   The ≤720 block takes both to a single column. */
@media (max-width: 1023px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero--panel .hero-grid { grid-template-columns: minmax(0, 1fr); padding: 28px 20px 24px; border-radius: 28px; }
  .hero--panel .hero-right { margin-top: 8px; }
  .hero-right { align-items: stretch; margin-top: 0; }

  /* Contact's copy + message form stack in the same tier as the landing hero and
     the checker — not at 1100. The chrome mark hides here too: it fills the void
     the shorter copy column leaves, and stacked there is no void. */
  .contact-grid { grid-template-columns: minmax(0, 1fr); gap: 40px; }

  .profile-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .profile-grid > :nth-child(n) { grid-column: auto; }

  /* Showcase stacks: image on top, then the cards. Nothing is beside the panel
     to give it a height any more, so it takes an aspect ratio of its own —
     without one, the absolutely-positioned image would collapse it to zero. */

  /* Timeline flattens to a vertical stack: the axis columns, the chrome
     cursor and the hover hints (pointer-only anyway) all go.
     The step pills MUST drop their desktop width here — 31% is a share of
     the *track*, so off the axis it is just 31% of a phone, and the pill
     becomes a tall lozenge with the label wrapped one word per line.
     Full width also keeps the "steps are equal length" read, and the fill
     sweep still runs left→right across each one.
     `.tl-pill` stays relative, NOT static: the fill is an absolute ::before
     with inset:0, so a static pill hands it the *track* as its containing
     block and the fill balloons over the whole section. inset:auto cancels
     the desktop .tl-p1/.tl-p3/.tl-p5 offsets.
     The statement's hard line breaks compose the desktop 3-line block; here
     they fight natural wrapping and strand a word per line, so let it flow. */
  .tl-statement .block { display: inline; }
  .tl-track { height: auto; margin-top: 40px; display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
  .tl-cols, .tl-cursor { display: none; }
  .tl-pill { position: relative; inset: auto; white-space: normal; }
  .tl-pill--step { width: 100%; }
  .tl-pill--micro { margin-left: 28px; }
  .tl-final { position: static; width: 100%; max-width: 320px; margin-top: 10px; }
  .tl-hint { display: none; }
}

/* FAQ: two full-width columns down to 768px, single column below.
   align-items:stretch makes the single column fill the block (base is flex-start). */
@media (max-width: 768px) {
  .faq-grid { flex-direction: column; align-items: stretch; }
}

@media (max-width: 720px) {
  :root {
    --hero-top: 40px;
    --section-head-gap: 32px; /* phone */
    /* Phone-tighter padding tokens — 22/24 → 18, 28 → 20. */
    --pad-snug:  18px;
    --pad-card:  18px;
    --pad-roomy: 20px;
    --pad-xl:    24px;
    --space-lg:  40px;
  }
  /* Mobile nav: logo recenters (auto-margin both sides); the header CTA
     stays a text pill, just compact (icons are retired button-wide).
     The wordmark is wide (~6.2:1), so at its fixed desktop width it ran
     into the CTA below ~375px. Two things keep the row honest at any
     width: it scales with the viewport (capped at the 160px desktop
     size), and — since the burger and the CTA are not compressible — it
     is allowed to shrink past that if the row still runs out of space
     (min-width:0 lets the flex item shrink; max-width:100% carries the
     img down with it). */
  .nav { padding: 10px 12px; gap: 10px; --logo-w: clamp(124px, 38vw, 160px); }
  .logo { margin-left: auto; margin-right: auto; min-width: 0; }
  .nav .logo-svg { max-width: 100%; }
  .nav-cta a.btn:last-child { height: 32px; font-size: 12px; }
  /* the phone nav CTA is tight, so its label gives back some of its padding */
  .nav-cta a.btn:last-child > span { padding: 0 12px; }
  .profile-grid { grid-template-columns: minmax(0, 1fr); }
  .profile-grid > :nth-child(n) { grid-column: auto; }
  /* Mission: no room for head + foot side by side any more, so back to a
     stack; the stat cards stack too and the wide card loses its 2-col span. */
  .mission-left { flex-direction: column; gap: var(--head-gap); }
  .mission-cards { grid-template-columns: minmax(0, 1fr); }
  .mission-card--wide { grid-column: auto; }
  .mission-card { min-height: 190px; }
  .mission-foot { padding-top: 28px; }
  /* The carousel itself is already set up in the ≤1100 block — on a phone
     only the card width changes: one per view, with the next peeking. */
  .pricing-grid > .price-card { flex: 0 0 calc(100vw - 3 * var(--pad-x) - 16px); }
  .footer-cols { flex-direction: column; gap: 32px; }
  .footer-bottom { flex-direction: column; gap: 16px; align-items: flex-start; }
  .hero-title { font-size: 48px; }
  /* Tabs container goes full-width; each tab takes 50% of the row.
     The sliding pill re-measures via window.resize (script.js). */
  .check-form-tabs { display: flex; width: 100%; }
  .check-tab { flex: 1; justify-content: center; }
  /* Profile-card titles get larger on phone — each card has the full row
     to itself in single-column stack, so a bigger headline reads better. */
  .profile-title { font-size: 24px; }
  /* Upload-card on phone: shrink padding, hide file-extensions hint (its
     content overflows together with the Scan CTA in one row), stretch the
     Scan button to fill the remaining width next to attach. In the foot
     the "150 words · free · no card" meta drops onto its own full-width
     line below the chips so all four bits still surface. */
  .upload-card { padding: 14px; }
  .upload-hint { display: none; }
  .upload-controls { gap: 10px; }
  /* Scan CTA hugs its content; the .flex-spacer between attach and scan
     pushes the button to the right edge of the row. */
  .upload-foot { flex-wrap: wrap; row-gap: 10px; column-gap: 8px; }
  .upload-meta { flex-basis: 100%; }
  /* FAQ rows on phone: proportionally shrink chrome so each row reads
     tighter against the narrow viewport. */
  .faq-row { padding: 14px 18px; }
  .faq-toggle { margin-left: 12px; }
  .faq-a { margin-top: 10px; }
  /* Phone: the loupe decor shrinks and hugs the corner so it never covers
     the CTA copy; the panel compacts. */
  .cta-strip { padding: 28px 20px; border-radius: 28px; }
  .cta-loupe { width: 96px; height: 96px; }
  /* Reviews-foot arrows are redundant on phone — the carousel becomes a
     stack/swipe surface and the prev/next button row would just clutter the
  /* .btn-lg → .btn-md sizing on phone (56→48 height) so big CTAs don't
     dominate the small viewport. Ico-circle and font shrink proportionally. */
  .btn-lg { height: 48px; font-size: 15px; }
  .feat-card { padding: var(--pad-card); min-height: 220px; }
  /* Compare pills and the giant numeral can't share a row on phone. */
  .feat-compare-wrap { flex-direction: column; align-items: stretch; gap: 26px; }
  .feat-compare { max-width: none; }
  .feat-big { align-self: flex-end; align-items: flex-end; text-align: right; }
  .form-row { grid-template-columns: minmax(0, 1fr); }
  .contact-offices { grid-template-columns: minmax(0, 1fr); }
  .about-values-grid { grid-template-columns: minmax(0, 1fr); }
  .timeline-item { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .cookies-banner { left: 16px; right: 16px; bottom: 16px; max-width: none; }
  .trust-strip { grid-template-columns: minmax(0, 1fr); padding: 8px 8px; }
  .trust-item { border-left: 0; border-top: 1px solid var(--border); padding: 16px 16px; }
  .trust-item:first-child { border-top: 0; }
  .check-dropzone { min-height: 220px; padding: 28px 16px; }
  .check-form-meta { flex-direction: column; align-items: stretch; }
  .check-form-meta .btn { width: 100%; justify-content: center; }
  .auth-social { grid-template-columns: minmax(0, 1fr); }
}

/* Disabled buttons */
.btn:disabled, .btn[disabled] { opacity: .45; box-shadow: none; pointer-events: none; }
