/* =====================================================
   EVOGLYPH - Self-hosted fonts (#97)
   Replaces Google Fonts so browsers do not ping
   fonts.googleapis.com / fonts.gstatic.com on page load.
   See fonts/README.md for source URLs.
   ===================================================== */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/InterVariable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/JetBrainsMono.woff2') format('woff2-variations');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Quicksand';
  src: url('/fonts/Quicksand-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* =====================================================
   EVOGLYPH - Component & token helpers (#165, Epic 3)
   These replace the per-element inline style="…" attributes
   that previously set colors/borders straight from the legacy
   :root tokens. Re-homing them into classes is what lets the
   CSP drop style-src 'unsafe-inline' (Epic 10). Each helper is
   APPEARANCE-PRESERVING: it consumes the SAME legacy token the
   inline declaration referenced, so the rendered result is
   byte-identical. The dark-palette flip (new --color-* tokens)
   is Epic 6, not here.

   Text-color helpers. Used on text nodes and on inline SVG icons
   whose paths use stroke/fill="currentColor" (so `color` cascades
   into the glyph) — exactly what the inline `color: var(--…)` did.
   ===================================================== */
.t-primary {
  color: var(--text-primary);
}
.t-secondary {
  color: var(--text-secondary);
}
.t-tertiary {
  color: var(--text-tertiary);
}
.t-accent {
  color: var(--accent);
}
.t-accent-text {
  color: var(--accent-text);
}

/* Top hairline border used by comparison rows and footer dividers. */
.border-subtle-t {
  border-top: 1px solid var(--border-subtle);
}
/* Matching bottom hairline (e.g. the hero proof-strip band). */
.border-subtle-b {
  border-bottom: 1px solid var(--border-subtle);
}

/* Demo waveform bars: solid fill in the tertiary token. The per-bar
   opacity variants (0.6–1.0) stay as Tailwind opacity-* utilities on
   each bar so the staggered look is preserved exactly. */
.wave-bar-fill {
  background: var(--text-tertiary);
}

/* Hero "See the benchmark →" link — underlined accent text. */
.hero-benchmark-link {
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* =====================================================
   EVOGLYPH - Skip-link (#101)
   Hidden until focused via Tab; lets keyboard users jump
   past the nav directly into the main landmark.
   ===================================================== */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px 16px;
  background: var(--accent);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  border-radius: 0 0 8px 0;
  z-index: 1000;
  transform: translateY(-100%);
  /* Also hide via opacity, not just the off-screen transform: the element
     physically sits just above the page top, and iOS Safari's rubber-band
     overscroll on a fast scroll-to-top renders that region — which flashed the
     link over the header (#495). opacity:0 keeps it invisible there while
     staying keyboard-focusable (unlike visibility/display, which drop it from
     the tab order). */
  opacity: 0;
  transition:
    transform 150ms ease-out,
    opacity 150ms ease-out;
}
.skip-link:focus {
  transform: translateY(0);
  opacity: 1;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* =====================================================
   EVOGLYPH - Design Tokens (dark-flip, Epic 6 / #168)

   The legacy hardcoded-hex token system is RETIRED. These legacy
   names (--bg-*, --text-*, --accent*, --border-*) now ALIAS the
   canonical dark-first OKLCH semantic tokens defined in src/main.css
   (the @theme --color-* layer). Every component below consumes the
   legacy names, so re-pointing the aliases flips the whole site to
   the premium dark palette in one block.

   Dark-mode only (#223): there is no light palette and no theme
   toggle. The aliases below resolve through the single dark --color-*
   token set in src/main.css; `color-scheme: dark` there locks native
   UI to dark as well.

   Shadows are kept subtle: on a dark canvas, depth comes mostly from
   hairline borders (Raycast/Linear style), so the drop-shadows are
   light-touch dark-tinted values rather than the old strong shadows.
   ===================================================== */

:root {
  --bg-primary: var(--color-canvas);
  --bg-secondary: var(--color-surface-1);
  --bg-tertiary: var(--color-surface-2);
  --bg-card: var(--color-surface-1);
  --bg-card-hover: var(--color-surface-2);
  --border-primary: var(--color-border-hairline);
  --border-subtle: var(--color-border-subtle);
  --text-primary: var(--color-text-primary);
  --text-secondary: var(--color-text-secondary);
  --text-tertiary: var(--color-text-muted);
  /* The PRIMARY accent is the MBC gradient (--eg-mbc); --accent is the
     SECONDARY periwinkle (hue 274) solid used only where a gradient can't go
     — tint washes, dots, checks, link underlines. Dark-mode only (#223). White
     label text on the periwinkle fill is AA, so accent-text resolves to
     text-primary (near-white on the dark canvas) for elements that sit on the
     canvas, while buttons that fill with --accent pair it with explicit white
     in the component rules below. */
  --accent: var(--color-accent);
  /* accent-light / accent-muted are TINT SURFACES (icon chips, highlighted
     cards, soft glows), not solid accent fills. Express them as low-alpha
     mixes of the accent into transparent so they read as a faint periwinkle
     wash on the dark canvas (#223, dark-mode only) while keeping a "barely
     there" weight. */
  --accent-light: color-mix(in oklch, var(--color-accent) 16%, transparent);
  --accent-text: var(--color-text-primary);
  --accent-muted: color-mix(in oklch, var(--color-accent) 10%, transparent);
  /* Sky-blue accent (= the MBC gradient's mid stop #6cbeff) used by the
     redesign for numbered-step circles, the cleanup arrow, and the pipeline
     nodes — distinct from the periwinkle icon accent. High-contrast on the
     dark canvas (AA for small text). */
  --accent-blue: #6cbeff;
  /* Deeper, more saturated blue for the founder-pricing badges (#499) — set
     apart from the green value/feature cues. Lifted just enough off a pure
     #0055ff to clear WCAG AA (~5:1 on the card surface) for the small,
     uppercase badge text; #0055ff itself only reaches ~3.4:1. */
  --accent-blue-deep: #3b7bff;
  /* The MBC gradient token (--eg-mbc) + --eg-spectrum are the
     PRIMARY UI accent (#221, MBC #222). They are declared in src/main.css @theme
     so they compile into dist/tailwind.css and resolve on every page; the
     component rules below consume them directly. The brand mark itself is
     now a static PNG (evoglyph-mark.png), not a CSS gradient (#430). */
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.3);
  --shadow-md: 0 4px 14px oklch(0 0 0 / 0.4);
  --shadow-lg: 0 16px 48px oklch(0 0 0 / 0.5);
}

/* =====================================================
   EVOGLYPH - Custom Styles
   ===================================================== */

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

/* NOTE (#215): `scroll-behavior: smooth` was removed. It only affects
   programmatic/anchor jumps (which script.js already handles via
   scrollIntoView), never wheel/trackpad scroll, and a global smooth-scroll can
   hurt perceived scroll performance. In-page anchor smoothness is unchanged. */

body {
  font-family:
    'Inter',
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: var(--bg-primary);
  color: var(--text-primary);
  overflow-x: hidden;
}

/* Backdrop layering (#215): the <body> stays OPAQUE (the canvas above). The
   fixed `.site-backdrop` paints at z-index:0 — OVER the body background but
   UNDER the page content, which is lifted to z-index:1 here so it scrolls over
   the fixed aurora. Keeping the body opaque is deliberate: it preserves the
   contrast-resolution behaviour axe relies on (see src/main.css). The backdrop
   itself is the FIRST body child and is excluded from the lift.

   `position: relative` is only added where an element is statically positioned;
   the section/footer already carry Tailwind's `.relative`, so z-index alone
   takes effect there. The nav already sits at z-50. */
body[data-page='home'] > section,
body[data-page='home'] > footer,
/* developers wraps its sections in <main> (unlike home, whose sections are direct body children) */
body[data-page='developers'] > footer,
body[data-page='developers'] > main > section {
  position: relative;
  z-index: 1;
}

/* =====================================================
   TEXT WRAPPING (Principle 10)
   - balance for short headings (no widows/orphans)
   - pretty for long-form paragraphs
   ===================================================== */
h1,
h2,
h3 {
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

/* =====================================================
   TYPOGRAPHY
   ===================================================== */

.wordmark {
  font-family: 'Quicksand', 'Inter', sans-serif;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
}

/* Static PNG mark used by the app surfaces (login / dashboard /
   admin) and the non-partial docs pages. The nav + footer
   partials now use the animated .eg-mark construct below (#217),
   but these pages are intentionally out of scope, so this rule
   stays to keep their static mark unchanged. */
.evoglyph-logo {
  flex-shrink: 0;
  opacity: 0.85;
  transition: opacity 0.2s ease;
}

.evoglyph-logo:hover,
a:hover .evoglyph-logo {
  opacity: 1;
}

/* =====================================================
   BRAND MARK (nav + footer). Static holographic glyph PNG
   + plain wordmark. The animated hover treatment (#217 /
   #219) was removed pre-launch (#430); a lighter motion may
   return later. The full CSS construct is in git history.
   ===================================================== */
.eg-mark {
  flex-shrink: 0;
  width: 34px;
  height: auto;
  /* Subtle bloom echoing the glyph's own glow. */
  filter: drop-shadow(0 0 4px rgb(255 255 255 / 0.18));
}

.eg-wordmark {
  color: var(--text-primary);
}

/* Header-only: a subtle, bottom-weighted white glow under the
   wordmark. Footer wordmark intentionally untouched (#336). */
#navbar .eg-wordmark {
  text-shadow:
    0 1px 6px rgba(255, 255, 255, 0.42),
    0 3px 16px rgba(255, 255, 255, 0.28);
}

.inline-code {
  font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
  font-size: 0.85em;
  padding: 0.15em 0.45em;
  border-radius: 5px;
  background: var(--accent-muted);
  border: 1px solid var(--border-primary);
  color: var(--accent-text);
}

/* =====================================================
   NAVBAR
   ===================================================== */

#navbar {
  background: transparent;
}

#navbar.scrolled {
  /* Near-opaque solid instead of a translucent glass pane. A blurred-backdrop
     pane is CPU-rendered on Safari/iOS (the macOS audience) — a known perf
     trap (decision L3). 92% surface-1 over the canvas reads as a clean
     elevated bar with no compositing-cost blur pass. */
  background: color-mix(in oklch, var(--color-surface-1) 92%, transparent);
  border-bottom: 1px solid var(--border-subtle);
}

.nav-link {
  color: var(--text-secondary);
  position: relative;
  /* Min 40x40 hit area (Principle 16) without changing visual size.
     The pseudo-element extends the click target. */
}

.nav-link::before {
  content: '';
  position: absolute;
  inset: -10px -6px;
  /* Hit-target overlay only - no background. Adjacent nav-links sit
     in a flex row with gap-8 (32px), so 6px horizontal extension
     never overlaps neighbours. */
}

.nav-link:hover {
  color: var(--text-primary);
}

/* Active-page highlight for the single-source nav (#164). The nav partial
   carries data-nav="features|pricing|benchmark|changelog|docs|home" on its
   orientation links; each page sets data-page="…" on <body>. The matching
   link is promoted to the primary text colour, replacing the per-page inline
   active styles that used to live in the duplicated navs. */
body[data-page='features'] [data-nav='features'],
body[data-page='pricing'] [data-nav='pricing'],
body[data-page='benchmark'] [data-nav='benchmark'],
body[data-page='changelog'] [data-nav='changelog'],
body[data-page='docs'] [data-nav='docs'],
body[data-page='home'] [data-nav='home'] {
  color: var(--text-primary);
}

/* The brand UI accent is the MBC gradient (#221, MBC #222). The nav CTA — like
   all primary CTAs — is a transparent pill with a ~3px MBC gradient BORDER and a
   white label (legible on the dark nav). The gradient lives on a ::before
   pseudo (see the shared .cta-primary/.nav-cta/.pricing-btn-primary rule below)
   so the LABEL is not masked out. Only colour/label state lives here. */
.nav-cta {
  color: oklch(0.99 0 0);
  /* Declared here (not only as a markup utility) so BOTH instances — the
     desktop nav pill and the mobile-menu copy, which carries no `transition`
     utility — get the same interruptible hover/press motion as .cta-primary. */
  transition-property: background-color, box-shadow, transform;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.nav-cta:active {
  transform: scale(0.96);
}

.nav-cta:hover {
  color: oklch(0.99 0 0);
}

/* =====================================================
   HERO
   ===================================================== */

/* NOTE (#215): the in-hero `.grid-overlay` was removed at the owner's request.
   The hero background now comes solely from the fixed `.site-backdrop` aurora
   (src/main.css), with no grid lines. */

/* =====================================================
   CTA BUTTONS
   ===================================================== */

/* ---------- MBC gradient-border CTAs (#221, MBC #222) ----------
   Shared by every primary call-to-action: hero "Download for macOS", the nav
   CTA, the featured-plan pricing button, the closing CTA, and the token-system
   .btn-primary. The button itself is transparent (the dark page/section shows
   through the interior); a ::before pseudo paints the 3px MBC ring.

   Why a pseudo and not `border-image`: the ring is drawn by filling the pseudo
   with the gradient as a `border-box` background, then masking AWAY the
   content-box rectangle (mask-composite: exclude) so only a 3px frame remains.
   Crucially the gradient is on the PSEUDO, never on the element, so the button's
   real text/icon children are NOT clipped to the gradient (a background-clip:text
   approach would erase the white label). pointer-events:none keeps clicks live. */
.cta-primary,
.nav-cta,
.pricing-btn-primary {
  position: relative;
  background: transparent;
  border: 0;
  box-shadow: none;
}

.cta-primary::before,
.nav-cta::before,
.pricing-btn-primary::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px;
  background: var(--eg-mbc) border-box;
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  transition:
    filter 200ms cubic-bezier(0.2, 0, 0, 1),
    opacity 200ms cubic-bezier(0.2, 0, 0, 1);
}

/* Hover: a faint rainbow-tint interior fill + a soft gradient glow, and the ring
   brightens a touch. Subtle — the page still reads through the interior. The
   tint uses a representative spectrum hue so the wash isn't muddy. */
.cta-primary:hover,
.nav-cta:hover,
.pricing-btn-primary:hover {
  background: color-mix(in oklch, var(--eg-spectrum) 12%, transparent);
  box-shadow: 0 8px 28px color-mix(in oklch, var(--eg-spectrum) 28%, transparent);
}

.cta-primary:hover::before,
.nav-cta:hover::before,
.pricing-btn-primary:hover::before {
  filter: brightness(1.12) saturate(1.1);
}

.cta-primary:hover {
  transform: translateY(-1px);
}

/* Keyboard focus: a clear ring that doesn't rely on the (decorative) gradient
   border, so it reads for low-vision users in both themes. */
.cta-primary:focus-visible,
.nav-cta:focus-visible,
.pricing-btn-primary:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* Primary CTA: the brand accent is the rainbow gradient (#221). The button is a
   TRANSPARENT pill with a ~3px rainbow gradient border and a white centred
   label. State (lift, press, glow) lives in the shared rule below; the colour
   is white text on the dark page showing through the transparent interior. */
.cta-primary {
  color: oklch(0.99 0 0);
  transition-property: background-color, box-shadow, transform;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.cta-primary:active {
  transform: scale(0.96);
}

.cta-secondary {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  color: var(--text-secondary);
  transition-property: background-color, border-color, color, transform;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.cta-secondary:hover {
  background: var(--bg-card-hover);
  border-color: var(--text-tertiary);
  color: var(--text-primary);
}

.cta-secondary:active {
  transform: scale(0.96);
}

/* Optical alignment (make-interfaces-feel-better / surfaces): a button that
   pairs a leading download icon with a text label feels balanced when the
   icon side carries ~2px less padding than the text side. Applied to the
   download CTAs (hero + final) which use the .cta-with-icon marker. The
   base px-* utility is dropped from those anchors in favour of this rule. */
.cta-with-icon {
  padding-left: 1.75rem; /* 28px text side */
  padding-right: 1.625rem; /* 26px icon side (= text - 2px) */
}

/* =====================================================
   HERO TERMINAL
   ===================================================== */

/* The terminal/code-sample surfaces are deliberately a darker "device" panel
   that reads the same in both themes (a code window is always dark). They are
   re-expressed off the ink ramp so they sit a notch below the canvas with a
   hairline edge — and the blurred backdrop is removed (decision L3). */
.terminal-header {
  background: oklch(1 0 0 / 0.03);
  border-bottom: 1px solid oklch(1 0 0 / 0.06);
}

/* Recording indicator */
.recording-pulse {
  animation: pulse-rec 1.5s ease-in-out infinite;
}

@keyframes pulse-rec {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.5;
    transform: scale(0.85);
  }
}

/* Pulse dot in badge */
.pulse-dot {
  animation: pulse-badge 2s ease-in-out infinite;
}

@keyframes pulse-badge {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.4;
  }
}

/* =====================================================
   SECTION LABELS
   ===================================================== */

.section-label {
  color: var(--accent-text);
}

/* =====================================================
   FEATURE CARDS
   ===================================================== */

.feature-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
  transition-property: background-color, border-color, transform, box-shadow;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.feature-card:hover {
  background: var(--bg-card-hover);
  border-color: var(--border-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.feature-icon-bg {
  background: var(--accent-light);
  border: 1px solid var(--accent-muted);
}

/* =====================================================
   COMPARISON TABLE
   ===================================================== */

.comparison-header {
  background: var(--bg-secondary);
}

.comparison-row:hover {
  background: var(--bg-card-hover);
}

.comparison-row {
  border-color: var(--border-subtle);
}

/* =====================================================
   PRICING CARDS
   ===================================================== */

.pricing-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
  transition-property: background-color, border-color, transform, box-shadow;
  transition-duration: 400ms;
  /* easeOutQuint — a smooth, settled lift/glow (was a snappier 300ms ease). */
  transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

/* The tile lifts + glows ONLY when its CTA is hovered/focused (#480), never on
   bare tile hover — the affordance must match the actually-clickable element
   (the button), not the whole non-clickable tile. :has() lets the card react to
   its own button's state; it pairs with the CTA fill-in below for one cohesive
   active look triggered by a single element. */
.pricing-card:has(.pricing-cta:hover),
.pricing-card:has(.pricing-cta:focus-visible) {
  transform: translateY(-4px);
  border-color: var(--border-primary);
  box-shadow:
    var(--shadow-lg),
    0 0 60px -30px color-mix(in oklch, var(--accent-blue) 45%, transparent);
}

/* .pricing-btn-primary / .pricing-btn-secondary are retained for thank-you.html
   (the only remaining consumer); the pricing tiles themselves now use the
   interactive .pricing-cta below (#480 dropped the featured tile + badge). */
.pricing-btn-primary {
  color: oklch(0.99 0 0);
  transition-property: background-color, box-shadow, transform;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pricing-btn-primary:active {
  transform: scale(0.96);
}

.pricing-btn-secondary {
  background: var(--bg-secondary);
  border: 1px solid var(--border-primary);
  color: var(--text-secondary);
  transition-property: background-color, border-color, color, transform;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pricing-btn-secondary:hover {
  background: var(--bg-tertiary);
  border-color: var(--text-tertiary);
  color: var(--text-primary);
}

.pricing-btn-secondary:active {
  transform: scale(0.96);
}

/* Pricing CTAs (#480) — one uniform treatment across all three tiles, no
   precedence. BASE: a transparent pill with the MBC gradient OUTLINE (the
   ::before ring, masked) and a white label. ACTIVE (the parent .pricing-card is
   hovered, or the CTA is keyboard-focused): the gradient FILL (::after) fades in
   and the label flips white→dark ink — landing on the look the Monthly tile had.
   Hover is driven at the CARD level so pointing anywhere on a tile lights its
   CTA; :focus-visible mirrors it for keyboard users. Both pseudos sit at
   z-index:-1 (isolation:isolate scopes the stack) so the label stays on top. */
.pricing-cta {
  position: relative;
  isolation: isolate;
  background: transparent;
  border: 0;
  color: oklch(0.99 0 0);
  /* Label color fades white→dark in lockstep with the fill (::after) so the two
     read as one gradual change; ease-in-out (not ease-out) avoids the
     front-loaded "pop". The press (:active) transform stays snappy. */
  transition:
    color 500ms ease-in-out,
    transform 200ms cubic-bezier(0.2, 0, 0, 1);
}

/* BASE — gradient outline ring (same mask trick as .cta-primary). */
.pricing-cta::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  padding: 2px;
  background: var(--eg-mbc) border-box;
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* ACTIVE — gradient fill, painted above the ring (later pseudo) but below the
   label; fades in on the active states below. */
.pricing-cta::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--eg-mbc);
  opacity: 0;
  pointer-events: none;
  /* Gradual 500ms ease-in-out fade — not a front-loaded pop. */
  transition: opacity 500ms ease-in-out;
}

.pricing-cta:hover,
.pricing-cta:focus-visible {
  color: oklch(0.18 0.02 264);
}

.pricing-cta:hover::after,
.pricing-cta:focus-visible::after {
  opacity: 1;
}

.pricing-cta:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.pricing-cta:active {
  transform: scale(0.98);
}

/* Reduced motion: keep the state change but make it instant (no fades). */
@media (prefers-reduced-motion: reduce) {
  .pricing-cta,
  .pricing-cta::after {
    transition: none;
  }
}

/* D4 beta-promo callout: visually distinct from the public pricing cards,
   uses the accent-muted surface so it reads as a labeled secondary offer. */
.pricing-promo-callout {
  background: var(--accent-muted);
  border: 1px solid var(--accent);
  box-shadow: var(--shadow-sm);
}

.pricing-promo-eyebrow {
  color: var(--accent-text);
}

/* =====================================================
   DOWNLOAD SECTION
   ===================================================== */

/* Developer install block (#211): the curl / Homebrew commands beneath the
   primary .dmg CTA. A hairline divider separates it from the button so the
   DMG stays visually dominant; the commands themselves reuse .use-case-example
   (a dark code-sample panel that reads correctly in both themes). */
.dev-install {
  padding-top: 2rem;
  border-top: 1px solid var(--border-primary);
}

/* =====================================================
   FAQ
   ===================================================== */

.faq-item {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  transition: border-color 0.2s ease;
}

.faq-item:hover {
  border-color: var(--text-tertiary);
}

.faq-item.open {
  border-color: var(--accent);
  background: var(--accent-muted);
}

.faq-trigger {
  cursor: pointer;
  background: transparent;
  border: none;
  color: inherit;
}

/* FAQ open/close — animate the panel HEIGHT so it grows/shrinks to its exact
   content height. The grid-template-rows 0fr→1fr trick interpolates to the real
   content height; unlike a max-height transition it never has to guess a ceiling
   and so never snaps at the end (the symptom this replaced). script.js strips
   the markup `.hidden` on init so the panel stays in grid layout and the height
   can transition — collapse is then driven purely by `.faq-item.open`. No-JS
   keeps the panel collapsed (grid 0fr, or `.hidden`). */
.faq-content {
  display: grid;
  grid-template-rows: 0fr;
  /* The markup's `pb-5` is overridden to 0 while collapsed and restored (and
     animated) when open, in lockstep with the row height — so the panel
     collapses fully to 0 (a child with its own padding-bottom can't shrink
     below that padding in a 0fr track and would leave a residual gap).
     Horizontal `px-6` stays on the box. */
  padding-bottom: 0;
  transition:
    grid-template-rows 300ms cubic-bezier(0.33, 1, 0.68, 1),
    padding-bottom 300ms cubic-bezier(0.33, 1, 0.68, 1);
}

.faq-item.open .faq-content {
  grid-template-rows: 1fr;
  padding-bottom: 1.25rem; /* = pb-5 */
}

/* The content child clips its overflow as the row collapses; min-height:0 lets
   the grid track shrink to 0 below the child's intrinsic height. visibility
   keeps collapsed content out of the a11y tree + tab order — it is transitioned
   so the text stays visible through the close animation, then hides at the end. */
.faq-content > * {
  overflow: hidden;
  min-height: 0;
  visibility: hidden;
  transition: visibility 300ms;
  transition-behavior: allow-discrete;
}

.faq-item.open .faq-content > * {
  visibility: visible;
}

.faq-icon {
  transition: transform 0.25s ease;
}

.faq-item.open .faq-icon {
  transform: rotate(180deg);
}

/* =====================================================
   HERO ENTRANCE (load animation — not scroll-driven)
   ===================================================== */

/* The hero fades in on load via a keyframe animation that SETTLES at the
   visible state (forwards). It is independent of any scroll observer, so it
   keeps working after the JS reveal observer was retired (Epic 5, #167).
   Visible-by-default safety: reduced-motion users get the static end state
   below; the `forwards` fill means even a slow start lands at opacity:1. */
.fade-in {
  opacity: 0;
  transform: translateY(20px);
  animation: fadeInUp 0.7s ease forwards;
}

.fade-in-delay-1 {
  animation-delay: 0.1s;
}
.fade-in-delay-2 {
  animation-delay: 0.2s;
}
.fade-in-delay-3 {
  animation-delay: 0.35s;
}
.fade-in-delay-4 {
  animation-delay: 0.5s;
}
.fade-in-delay-5 {
  animation-delay: 0.65s;
}

@keyframes fadeInUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Reduced-motion: skip the hero entrance entirely, show the final state. */
@media (prefers-reduced-motion: reduce) {
  .fade-in,
  [class*='fade-in-delay'] {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  /* FAQ + mobile menu: instant open/close, no height/fade animation. The grid
     row snaps and the child's visibility flips with no transition. */
  .faq-content,
  .faq-content > *,
  #mobile-menu {
    transition: none !important;
    translate: 0 0 !important;
  }
}

/* NOTE on scroll reveals (the `.reveal` system): these now live exclusively in
   src/main.css and are driven by a one-shot IntersectionObserver in script.js —
   it adds `.is-visible` the first time each element enters the viewport, then
   stops observing it (no scroll-timeline). The base `.reveal` state is shown by
   default (no-JS / reduced-motion safe) and only flips to hidden-until-revealed
   once `js-reveal` is set on <html>. The earlier `animation-timeline: view()`
   scroll-driven variant was dropped (#215) because it re-evaluated every reveal
   on every scroll event; the legacy `.reveal.visible` + `.reveal-delay-*` rules
   that once lived here were removed in Epic 5 (#167). */

/* =====================================================
   MOBILE MENU
   ===================================================== */

#mobile-menu {
  /* Surface re-homed from the inline style on the partial (#165). The
     blurred-backdrop pass is REMOVED here (decision L3 — a CPU-rendered
     blur is a Safari/iOS perf trap on the macOS audience). Visually kept
     close: the same 95%-of-bg solid the inline declaration used, just
     without the compositing-cost pass. */
  border-top: 1px solid var(--border-subtle);
  /* Fully opaque so the open menu never shows the bright hero through it at the
     top of the page (#458). */
  background: var(--bg-primary);
  /* Same allow-discrete treatment as .faq-content: script.js toggles `.hidden`
     (display:none), so the old `opacity, transform, max-height` list never
     animated. Now the menu fades/slides 8px through the display flip; engines
     without allow-discrete keep the instant toggle. */
  opacity: 1;
  translate: 0 0;
  transition-property: opacity, translate, display;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
  transition-behavior: allow-discrete;
}

#mobile-menu.hidden {
  opacity: 0;
  translate: 0 -8px;
}

@starting-style {
  #mobile-menu {
    opacity: 0;
    translate: 0 -8px;
  }
}

/* =====================================================
   HERO STATS STRIP
   ===================================================== */

.hero-stat-value {
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* =====================================================
   TABULAR NUMERALS (Principle 9)
   Any element rendering dynamic numbers should use
   tabular-nums so digits don't jitter as values change.
   Apply via .tabular-nums utility OR built into the
   component class itself.
   ===================================================== */
.pricing-card .text-4xl,
.docs-meta time,
table th[scope='row'],
table td {
  font-variant-numeric: tabular-nums;
}

/* Changelog version pills (h2 lines like "## [0.1.0] - 2026-05-11"
   rendered by changelog-render.js from CHANGELOG.md). Tabular
   numerals keep version numbers and dates aligned across releases. */
.docs-body h2 {
  font-variant-numeric: tabular-nums;
}

/* =====================================================
   TESTIMONIALS
   ===================================================== */

.testimonial-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
  transition-property: background-color, border-color, transform, box-shadow;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.testimonial-card:hover {
  background: var(--bg-card-hover);
  border-color: var(--border-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.testimonial-quote {
  color: var(--text-tertiary);
}

.testimonial-card blockquote {
  font-size: 0.95rem;
  line-height: 1.65;
}

/* =====================================================
   FOOTER
   ===================================================== */

.site-footer {
  background: var(--bg-secondary);
  border-color: var(--border-subtle);
}

.footer-link {
  position: relative;
  display: inline-block;
}

.footer-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.2s ease;
}

.footer-link:hover::after {
  transform: scaleX(1);
}

.footer-social {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-primary);
  /* Min 40x40 hit area (surfaces §Minimum Hit Area): the visible tile is
     36px (w-9 h-9). The ::after extender adds 2px per side without changing
     the visual; the row's gap-2 (8px) leaves 4px clear between extended
     targets, so neighbours never overlap. */
  position: relative;
}

.footer-social::after {
  content: '';
  position: absolute;
  inset: -2px;
}

.footer-social:hover {
  background: var(--accent-light);
  border-color: var(--accent);
  transform: translateY(-1px);
}

/* =====================================================
   SMOOTH SCROLL OFFSET
   ===================================================== */

#features,
#pricing,
#download,
#how-it-works,
#use-cases,
#testimonials,
#built-for-mac {
  scroll-margin-top: 80px;
}

/* =====================================================
   BEFORE/AFTER DEMO
   ===================================================== */

.demo-panel {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
}

.demo-before {
  opacity: 0.85;
}

/* Contrast lift (#215): the demo-before's two small muted labels ("Recording"
   and "Raw voice input") are `t-tertiary` (the muted token) at 12px, further
   dimmed by this panel's 0.85 opacity and sitting on a slightly-lit pill. With
   the ambient backdrop now visible behind the semi-transparent panel, that
   combination dips just under WCAG AA (4.5:1 for small text). Promoting just
   these labels to the secondary token clears AA while keeping the panel's
   intentional "raw/dim" look (the 0.85 opacity is preserved). The body text
   below already uses the secondary token, so this only touches the two labels. */
.demo-before .t-tertiary {
  color: var(--text-secondary);
}

/* "Clean output" panel — its outline is now an MBC gradient ring (#221, MBC
   #222), marking it as the on-brand "after" result. The ring is a ::before mask
   (so the panel's animated text content isn't clipped to the gradient); the 1px
   solid border from .demo-panel is dropped in favour of the 1.5px gradient frame.
   The faint periwinkle interior tint is kept so the panel still reads as
   accented. */
.demo-after {
  position: relative;
  background: var(--accent-muted);
  border-color: transparent;
}

.demo-after::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: var(--eg-mbc) border-box;
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

.demo-arrow {
  color: var(--text-tertiary);
  animation: arrowPulse 2s ease-in-out infinite;
}

@keyframes arrowPulse {
  0%,
  100% {
    opacity: 0.5;
    transform: translateX(0);
  }
  50% {
    opacity: 1;
    transform: translateX(4px);
  }
}

@media (min-width: 768px) {
  .demo-arrow {
    animation-name: arrowPulseH;
  }
  @keyframes arrowPulseH {
    0%,
    100% {
      opacity: 0.5;
      transform: translateX(0);
    }
    50% {
      opacity: 1;
      transform: translateX(6px);
    }
  }
}

/* Demo transformation loop: conveys raw speech -> polished text.
   Visible-by-default — the base state is the final, fully-revealed text, so
   browsers without animation support (and reduced-motion users) see the
   finished output. The keyframes start hidden and settle to the base state. */
.demo-after-text {
  clip-path: inset(0 0 0 0);
  opacity: 1;
  animation: demoReveal 7s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}

@keyframes demoReveal {
  /* raw input still "settling" */
  0%,
  12% {
    clip-path: inset(0 100% 0 0);
    opacity: 0.25;
  }
  /* polished text wipes in */
  45% {
    clip-path: inset(0 0 0 0);
    opacity: 1;
  }
  /* hold the clean result, then loop */
  92%,
  100% {
    clip-path: inset(0 0 0 0);
    opacity: 1;
  }
}

.demo-after-badge {
  opacity: 1;
  animation: demoBadge 7s ease-out infinite;
}

@keyframes demoBadge {
  0%,
  30% {
    opacity: 0.35;
    transform: translateY(2px);
  }
  50%,
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.demo-before-text {
  animation: demoBeforeDim 7s ease-in-out infinite;
}

@keyframes demoBeforeDim {
  0%,
  12% {
    opacity: 1;
  }
  /* dip as the cleanup happens, then return */
  40% {
    opacity: 0.55;
  }
  70%,
  100% {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .demo-after-text,
  .demo-after-badge,
  .demo-before-text {
    animation: none;
    clip-path: none;
    opacity: 1;
    transform: none;
  }
}

/* Offscreen pause (Epic 5, #167): a tiny IntersectionObserver in script.js
   adds `.paused` to the looping demo (and the fixed backdrop aurora, #215) when
   it scrolls out of view, so an infinite compositor animation isn't burning
   cycles on a panel nobody is looking at. Re-entering view removes the class
   and the loop resumes. */
.demo-after-text.paused,
.demo-after-badge.paused,
.demo-before-text.paused,
.site-backdrop-aurora.paused {
  animation-play-state: paused;
}

/* When PAUSED, the looping demo must rest at its SETTLED, fully-readable output
   — not whatever keyframe it happened to freeze on. `animation-play-state:
   paused` freezes the CURRENT frame, and at page load that is the 0% frame
   (opacity 0.25, mid-wipe), which is below the fold on a short viewport and so
   never plays forward. Forcing the finished state here keeps the offscreen demo
   readable and makes good on the "content stays visible either way" intent. The
   running animation when the demo is in view is unchanged.

   `!important` is required: a running-but-paused CSS animation still applies its
   current keyframe at a higher precedence than a normal declaration, so without
   it the `demoReveal` 0% frame (opacity 0.25) would keep winning. */
.demo-after-text.paused {
  clip-path: inset(0 0 0 0) !important;
  opacity: 1 !important;
}
.demo-after-badge.paused,
.demo-before-text.paused {
  opacity: 1 !important;
  transform: none !important;
}

/* =====================================================
   BUILT FOR MAC
   ===================================================== */

.mac-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
  transition-property: background-color, transform, box-shadow;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.mac-card:hover {
  background: var(--bg-card-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* =====================================================
   PRIVACY GRID
   ===================================================== */

.privacy-claim-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
  transition-property: background-color, transform, box-shadow;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.privacy-claim-card:hover {
  background: var(--bg-card-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.privacy-verify {
  font-size: 12px;
  color: var(--text-tertiary);
  font-style: italic;
}

/* =====================================================
   RESPONSIVE
   ===================================================== */

@media (max-width: 640px) {
  .wordmark {
    font-size: 1.1rem;
  }

  .terminal-card {
    font-size: 12px;
  }

  .comparison-card table {
    font-size: 12px;
  }

  .hero-stat-value {
    font-size: 1.4rem;
  }

  .use-case-example {
    font-size: 11px;
    padding: 10px 12px;
  }

  .testimonial-card {
    padding: 1.5rem;
  }

  .spec-card {
    padding: 1.5rem;
  }
}

/* =====================================================
   CONSOLIDATED HOMEPAGE SECTIONS (#213)
   Features pillars, the compact how-it-works flow strip, the
   differentiation cards, and the Specs models/pipeline cards. All share the
   established card surface (var(--bg-card) + hairline border + layered
   shadow) and the same hover lift as .feature-card / .step-card, so the new
   consolidated sections read as one system rather than a flutter of grids.
   Transitions name explicit properties (never `transition: all`).
   ===================================================== */

/* Four-pillar row + the differentiation cards: same surface as feature cards. */
.pillar-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
  transition-property: background-color, border-color, transform, box-shadow;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pillar-card:hover {
  background: var(--bg-card-hover);
  border-color: var(--border-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* Pillar + differentiator icon GLYPHS render in the MBC gradient (#222). The
   line icons are inline SVGs with stroke="currentColor" (via .t-accent); this
   CSS `stroke` overrides that presentation attribute and points it at the shared
   <linearGradient id="eg-mbc-icon"> sprite (index.html), so each glyph picks up
   the magenta→blue→cyan sweep. Covers the pillar, differentiator,
   and privacy-claim ("Every claim is verifiable") icon grids (#224). The Specs
   models/pipeline block has no line icons, so it is unaffected.
   CSP-safe: a CSS property, not an inline style. */
.pillar-card .feature-icon-bg svg,
.privacy-claim-card .feature-icon-bg svg {
  stroke: url(#eg-mbc-icon);
}

/* Compact how-it-works flow: a lighter inset surface so the three steps read
   as a single strip, not three more feature cards. */
.flow-step {
  background: color-mix(in oklch, var(--bg-card) 60%, transparent);
  border: 1px solid var(--border-subtle);
  transition-property: background-color, border-color, transform;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.flow-step:hover {
  background: var(--bg-card);
  border-color: var(--border-primary);
  transform: translateY(-2px);
}

/* Oversized step ordinal — echoes the .step-number treatment (muted, tabular,
   non-selectable) but inline at the head of each flow step. */
.flow-step-num {
  flex-shrink: 0;
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
  user-select: none;
}

/* Specs cards: same card surface, no hover lift (these are dense reference
   blocks, not affordances). */
.spec-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-sm);
}

/* Pipeline step badge: small accent-tinted numeral chip aligned to its row. */
.spec-pipeline-num {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 7px;
  background: var(--accent-muted);
  border: 1px solid var(--border-primary);
  color: var(--accent-text);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* =====================================================
   SELECTION
   ===================================================== */

::selection {
  /* Accent-tinted highlight that reads in both themes (was a near-black
     overlay, invisible on the dark canvas). */
  background: color-mix(in oklch, var(--color-accent) 35%, transparent);
  color: var(--text-primary);
}

/* =====================================================
   SCROLLBAR
   ===================================================== */

::-webkit-scrollbar {
  width: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--text-tertiary);
  border-radius: 3px;
  opacity: 0.3;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-secondary);
}

/* =====================================================
   LANDING REDESIGN (#417) — refined direction
   Section restructure + restrained type scale. New component classes used by
   the rebuilt index.html. Color/border/shadow all flow through the @theme
   tokens (src/main.css), so nothing here hardcodes a palette value. Dark-only,
   CSP-safe (class-based, no inline styles), motion gated by reduced-motion.
   ===================================================== */

/* ---------- Type scale (landing-scoped, not global @theme) ----------
   Localized here so other marketing pages' text-display/headline utilities are
   undisturbed. Display clamps 40–54px (build note); section title 32–42px. */
.hero-headline {
  font-family:
    'Inter',
    -apple-system,
    sans-serif;
  font-weight: 600;
  font-size: clamp(2.5rem, 4.8vw, 3.5rem);
  line-height: 1.03;
  letter-spacing: -0.038em;
}
.section-title {
  font-family:
    'Inter',
    -apple-system,
    sans-serif;
  font-weight: 600;
  font-size: clamp(1.875rem, 4vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
}
/* Monospace eyebrow — the "reads 2026" cue. 0.16em tracking per the spec. */
.eyebrow-mono {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
/* Numbers are always mono (credibility cue). */
.num-mono {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Refined gradient accent: MBC clipped to text WITHOUT forcing 900 weight, so
   the hero "fully local" stays at the display weight (600). Distinct from the
   legacy .gradient-text (which forces 900 for the bolder direction). */
.gradient-accent {
  background: var(--eg-mbc);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--eg-spectrum); /* fallback if background-clip:text unsupported */
}

/* ---------- Hero ---------- */
.hero-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.hero-stat {
  padding: 0 1rem;
  border-left: 1px solid var(--border-primary);
  text-align: left;
}
.hero-stat:first-child {
  border-left: 0;
  padding-left: 0;
}
.hero-stat-num {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.5rem, 3vw, 1.875rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text-primary);
}
.hero-stat-label {
  font-size: 0.8125rem;
  color: var(--text-tertiary);
  line-height: 1.3;
}
@media (max-width: 720px) {
  .hero-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.5rem 0;
  }
  .hero-stat:nth-child(3) {
    border-left: 0;
  }
}

/* Moat pills under the CTA row + small emerald-check status pills. */
.moat-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--border-primary);
  background: var(--bg-card);
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.moat-pill .check {
  color: var(--color-emerald);
  font-weight: 700;
}

/* =====================================================
   HERO — 2-column redesign (#439): copy left, product-demo card right.
   ===================================================== */
.hero-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  column-gap: 3.5rem;
  row-gap: 0;
  /* start, not center: the demo (col 2) re-centers itself via align-self; the
     copy (col 1 / row 1) and proof strip (col 1 / row 2) stay top-aligned. */
  align-items: start;
}
.hero-copy {
  grid-column: 1;
  grid-row: 1;
  text-align: left;
}
/* Proof strip (stats + latency note) gets its own grid cell (col 1 / row 2) so
   that on mobile — where the grid collapses to one column — it stacks AFTER the
   demo video in DOM order (copy → video → stats), while on desktop it sits back
   under the copy in the left column (#495). */
.hero-proof {
  grid-column: 1;
  grid-row: 2;
}
.hero-lead {
  font-size: 1.125rem;
  line-height: 1.6;
  max-width: 48ch;
  margin-top: 1.375rem;
}
.hero-cta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.875rem;
  margin-top: 1.875rem;
}

/* Install-via-terminal toggle — a transparent ghost button (distinct from the
   bg-filled .cta-secondary), with a chevron that flips when the panel opens. */
.term-toggle {
  background: transparent;
  border: 1px solid var(--color-border-strong);
  color: var(--text-primary);
  cursor: pointer;
  transition:
    border-color 150ms ease,
    background-color 150ms ease;
}
.term-toggle:hover {
  border-color: color-mix(in oklch, white 32%, transparent);
  background: color-mix(in oklch, white 3%, transparent);
}
.term-toggle:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}
.term-chevron {
  color: var(--text-tertiary);
  transition: transform 200ms cubic-bezier(0.2, 0, 0, 1);
}
.term-toggle[aria-expanded='true'] .term-chevron {
  transform: rotate(180deg);
}

/* Install-via-terminal disclosure. The `hidden` attr collapses it for no-JS (UA
   display:none); script.js strips `hidden` on init so the panel is CSS-collapsed
   via the default below, then the toggle animates height smoothly with the
   grid-template-rows 0fr→1fr technique. (display:none can't transition, which is
   why the open state is a class, not :not([hidden]).) CSP-safe: the toggle flips
   the `.is-open` class — no inline-style writes. */
.term-panel {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: 0;
  transition:
    grid-template-rows 320ms cubic-bezier(0.4, 0, 0.2, 1),
    margin-top 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
.term-panel.is-open {
  grid-template-rows: 1fr;
  margin-top: 1rem; /* gap above the pills; 0 when closed so no residual space */
}
.term-panel-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  min-height: 0; /* let the grid row collapse all the way to 0 */
  overflow: hidden;
  visibility: hidden; /* dropped from tab order + AT while collapsed */
  transition: visibility 0s linear 320ms; /* hide only after the close finishes */
}
.term-panel.is-open .term-panel-inner {
  visibility: visible;
  transition: visibility 0s; /* reveal immediately on open */
}
@media (prefers-reduced-motion: reduce) {
  .term-panel {
    transition: none;
  }
  .term-panel-inner {
    transition: none;
  }
}
.term-cmd {
  display: inline-flex;
  align-items: center;
  gap: 0.875rem;
  text-align: left;
  background: var(--color-surface-2);
  border: 1px solid var(--border-primary);
  border-radius: 10px;
  padding: 0.8rem 1rem;
  cursor: pointer;
  transition:
    border-color 150ms ease,
    background-color 150ms ease;
}
.term-cmd:hover {
  border-color: color-mix(in oklch, var(--accent-blue) 40%, transparent);
  background: var(--color-surface-3);
}
.term-cmd-text {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--text-secondary);
  white-space: nowrap;
}
.term-cmd-state {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.term-cmd-copy {
  color: var(--text-tertiary);
}
.term-cmd-copied {
  display: none;
  align-items: center;
  gap: 0.3rem;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  color: var(--color-emerald);
}
.term-cmd.copied .term-cmd-copy {
  display: none;
}
.term-cmd.copied .term-cmd-copied {
  display: inline-flex;
}

/* Free-trial line. */
.hero-trial {
  display: flex;
  align-items: center;
  gap: 0.5625rem;
  margin-top: 1.25rem;
}
.hero-trial-icon {
  color: var(--color-success);
  flex-shrink: 0;
}
.hero-trial-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.hero-trial-text {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.78rem;
  color: var(--text-tertiary);
}

/* Stat-number unit (the s / % / x / mo after the figure) — smaller, muted. */
.hero-stat-unit {
  font-size: 0.875rem;
  color: var(--text-tertiary);
}
.hero-proof .hero-stats {
  margin-top: 2.125rem;
  padding-top: 1.625rem;
  /* left-aligned hero: stats span the column, divided by left hairlines */
}
.hero-latency-note {
  text-align: left;
  max-width: none;
  margin: 0.875rem 0 0;
  font-size: 0.75rem;
}

/* ---------- Hero product-demo video ---------- */
.hero-demo-wrap {
  position: relative;
  /* Spans both left-column rows (copy + proof) and centers the video against
     their combined height — preserving the desktop look while the proof strip
     lives in its own grid cell for the mobile reorder (#495). */
  grid-column: 2;
  grid-row: 1 / 3;
  align-self: center;
}
.demo-video-frame {
  position: relative;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid var(--color-border-strong);
  box-shadow: 0 40px 80px -34px oklch(0 0 0 / 0.85);
}
/* Hero product-demo video (#492). A bare looping screen recording — the macOS
   window chrome and the 3-step caption strip were removed in review. The frame
   rounds + clips the corners and casts the floating-card shadow; `aspect-ratio`
   reserves the box before the file loads so there is zero layout shift. The
   pause/play toggle is wired in script.js (addEventListener — CSP-safe, no
   inline handler) and honours prefers-reduced-motion (the poster is held). */
.demo-video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1080 / 700;
  object-fit: cover;
  background: var(--color-canvas);
}
.demo-video-toggle {
  position: absolute;
  bottom: 0.75rem;
  right: 0.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  color: var(--text-primary);
  background: color-mix(in oklch, var(--color-surface-1) 72%, transparent);
  border: 1px solid var(--color-border-strong);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  cursor: pointer;
  transition: background 0.15s ease;
}
.demo-video-toggle:hover {
  background: color-mix(in oklch, var(--color-surface-1) 90%, transparent);
}
.demo-video-toggle:focus-visible {
  outline: 2px solid var(--accent-blue);
  outline-offset: 2px;
}
.demo-video-icon {
  display: block;
}
.demo-video-toggle .demo-video-icon--play {
  display: none;
}
.demo-video-toggle.is-paused .demo-video-icon--pause {
  display: none;
}
.demo-video-toggle.is-paused .demo-video-icon--play {
  display: block;
}

/* Hero stack on narrow screens: demo card drops below the copy. */
@media (max-width: 900px) {
  .hero-grid {
    grid-template-columns: 1fr;
    row-gap: 2.5rem;
  }
  /* Collapse to one column and let the three cells flow in DOM order:
     copy → demo video → proof/stats (#495). */
  .hero-copy,
  .hero-proof,
  .hero-demo-wrap {
    grid-column: auto;
    grid-row: auto;
  }
  .hero-demo-wrap {
    align-self: auto;
    max-width: 30rem;
  }
  .hero-proof .hero-stats {
    /* row-gap already separates the stats from the video above; drop the
       desktop top-margin so the spacing doesn't double up. */
    margin-top: 0;
  }
}

/* =====================================================
   CLEANUP — raw → cleaned before/after (#439).
   ===================================================== */
.cleanup-grid {
  display: grid;
  grid-template-columns: 1fr 64px 1fr;
  align-items: stretch;
}
.cleanup-card {
  border: 1px solid var(--border-primary);
  border-radius: 16px;
  background: var(--bg-card);
  padding: 1.75rem;
}
/* Cleaned-output card: soft MBC gradient border (padding-box/border-box mask). */
.cleanup-card--clean {
  border: 1.5px solid transparent;
  border-radius: 16px;
  background:
    linear-gradient(var(--bg-card), var(--bg-card)) padding-box,
    linear-gradient(
        160deg,
        color-mix(in oklch, #ff7bfd 50%, transparent),
        color-mix(in oklch, #6cbeff 50%, transparent),
        color-mix(in oklch, #7fffff 40%, transparent)
      )
      border-box;
  padding: 1.75rem;
}
/* Recording / Cleaned header pills: 26px animated mark on the LEFT of the text,
   roomy padding, matched text size for both (#456). */
.cleanup-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-primary);
  padding: 0.5rem 1rem 0.5rem 0.625rem;
  border-radius: 999px;
  background: var(--color-surface-2);
  border: 1px solid var(--color-border-strong);
}
.cleanup-rec-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #ff5f57;
}
/* Animated evoglyph mark — mirrors the macOS app's menu-bar icon (#16).
   Recording: a white logo outline with a rainbow disc spinning in the center
   hole (~1.98s). Cleaned: the triangle flooded with a rotating conic rainbow,
   center circle cut out (~3.15s). Counterclockwise + linear, like the app. Pure
   CSS (conic-gradient + SVG-mask data URIs) — CSP-safe, no inline styles or JS. */
.eg-mark-anim {
  --eg-rainbow: conic-gradient(
    from 0deg,
    hsl(350 90% 72%),
    hsl(25 90% 70%),
    hsl(50 88% 67%),
    hsl(120 55% 64%),
    hsl(165 62% 65%),
    hsl(195 80% 68%),
    hsl(225 90% 73%),
    hsl(275 85% 74%),
    hsl(320 90% 72%),
    hsl(350 90% 72%)
  );
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
}
.eg-mark-anim > span {
  position: absolute;
  inset: 0;
}
@keyframes eg-mark-spin {
  to {
    transform: rotate(-1turn);
  }
}
@keyframes eg-mark-spin-rec {
  to {
    transform: translate(-50%, -50%) rotate(-1turn);
  }
}
/* Cleaned: fixed triangle-with-hole mask, rotating rainbow inside it. */
.eg-mark-anim--clean {
  overflow: hidden;
  -webkit-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1010 981'><path fill='%23fff' fill-rule='evenodd' d='M764.415 145C839.772 145 888.053 225.188 852.794 291.788L593.186 782.158C555.625 853.107 453.99 853.107 416.429 782.158L156.821 291.788C121.562 225.188 169.842 145 245.199 145H764.415ZM505.063 241C422.22 241 355.063 308.157 355.063 391C355.063 473.843 422.22 541 505.063 541C587.905 541 655.063 473.843 655.063 391C655.063 308.157 587.905 241 505.063 241Z'/></svg>")
    center / contain no-repeat;
  mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1010 981'><path fill='%23fff' fill-rule='evenodd' d='M764.415 145C839.772 145 888.053 225.188 852.794 291.788L593.186 782.158C555.625 853.107 453.99 853.107 416.429 782.158L156.821 291.788C121.562 225.188 169.842 145 245.199 145H764.415ZM505.063 241C422.22 241 355.063 308.157 355.063 391C355.063 473.843 422.22 541 505.063 541C587.905 541 655.063 473.843 655.063 391C655.063 308.157 587.905 241 505.063 241Z'/></svg>")
    center / contain no-repeat;
}
.eg-mark-rotor {
  inset: -50%;
  background: var(--eg-rainbow);
  animation: eg-mark-spin 3.15s linear infinite;
}
/* Recording: the white-FILLED macOS menu-bar mark + a rainbow disc spinning in
   the center hole. The disc sits BEHIND the white mark, so the mark's circular
   hole frames it to a centered rotating circle. Selectors are scoped to
   --rec so they outrank `.eg-mark-anim > span { inset:0 }` (else the disc
   snaps to the top-left corner). */
.eg-mark-anim--rec .eg-mark-core {
  inset: auto;
  left: 50%;
  top: 40.1%;
  width: 34%;
  height: 34%;
  border-radius: 50%;
  background: var(--eg-rainbow);
  transform: translate(-50%, -50%);
  animation: eg-mark-spin-rec 1.98s linear infinite;
}
.eg-mark-anim--rec .eg-mark-logo {
  background: #fff;
  -webkit-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1010 981'><path fill='%23fff' fill-rule='evenodd' d='M764.415 145C839.772 145 888.053 225.188 852.794 291.788L593.186 782.158C555.625 853.107 453.99 853.107 416.429 782.158L156.821 291.788C121.562 225.188 169.842 145 245.199 145H764.415ZM505.063 241C422.22 241 355.063 308.157 355.063 391C355.063 473.843 422.22 541 505.063 541C587.905 541 655.063 473.843 655.063 391C655.063 308.157 587.905 241 505.063 241Z'/></svg>")
    center / contain no-repeat;
  mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1010 981'><path fill='%23fff' fill-rule='evenodd' d='M764.415 145C839.772 145 888.053 225.188 852.794 291.788L593.186 782.158C555.625 853.107 453.99 853.107 416.429 782.158L156.821 291.788C121.562 225.188 169.842 145 245.199 145H764.415ZM505.063 241C422.22 241 355.063 308.157 355.063 391C355.063 473.843 422.22 541 505.063 541C587.905 541 655.063 473.843 655.063 391C655.063 308.157 587.905 241 505.063 241Z'/></svg>")
    center / contain no-repeat;
}
@media (prefers-reduced-motion: reduce) {
  .eg-mark-rotor,
  .eg-mark-anim--rec .eg-mark-core {
    animation: none;
  }
}
.cleanup-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.656rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-top: 1.125rem;
}
.cleanup-raw {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.9rem;
  line-height: 1.7;
  color: var(--text-secondary);
  margin: 0.875rem 0 0;
}
.cleanup-clean {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--text-primary);
  margin: 0.875rem 0 0;
}
.cleanup-arrow-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
}
.cleanup-arrow-line {
  width: 1px;
  flex: 1;
}
.cleanup-arrow-line--top {
  background: linear-gradient(var(--bg-card), var(--color-border-strong));
}
.cleanup-arrow-line--bottom {
  background: linear-gradient(var(--color-border-strong), var(--bg-card));
}
.cleanup-arrow-circle {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid color-mix(in oklch, var(--accent-blue) 40%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface-1);
  color: var(--accent-blue);
  flex-shrink: 0;
}
.cleanup-llm-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-secondary);
  padding: 0.6875rem 1rem;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-1);
}
.cleanup-llm-pill svg {
  color: var(--eg-spectrum);
  flex-shrink: 0;
}
.cleanup-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
.cleanup-stat-card {
  border: 1px solid var(--border-primary);
  border-radius: 14px;
  background: var(--bg-card);
  padding: 1.625rem;
  text-align: center;
}
.cleanup-stat-num {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 1.875rem;
  font-weight: 500;
  line-height: 1;
  color: var(--text-primary);
}
.cleanup-stat-unit {
  font-size: 0.9375rem;
  color: var(--text-tertiary);
}
.cleanup-stat-desc {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--text-tertiary);
  margin-top: 0.75rem;
}
@media (max-width: 820px) {
  .cleanup-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
  .cleanup-arrow-col {
    flex-direction: row;
    padding: 0.25rem 0;
  }
  .cleanup-arrow-line {
    display: none;
  }
  .cleanup-stats {
    grid-template-columns: 1fr;
  }
}

/* =====================================================
   HOW — two-key-press 3-step timeline (#439).
   ===================================================== */
.how-steps {
  position: relative;
  margin-top: 4rem;
}
.how-rail {
  position: absolute;
  top: 23px;
  left: 16%;
  right: 16%;
  height: 1px;
  background: linear-gradient(
    90deg,
    color-mix(in oklch, var(--accent-blue) 5%, transparent),
    color-mix(in oklch, var(--accent-blue) 35%, transparent),
    color-mix(in oklch, var(--accent-blue) 35%, transparent),
    color-mix(in oklch, var(--accent-blue) 5%, transparent)
  );
}
.how-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}
.how-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.how-circle {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--color-surface-1);
  border: 1px solid color-mix(in oklch, var(--accent-blue) 40%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--accent-blue);
}
.how-circle--final {
  border: 1.5px solid transparent;
  background:
    linear-gradient(var(--color-surface-1), var(--color-surface-1)) padding-box,
    var(--eg-mbc) border-box;
  color: #7fffff;
}
.how-step-title {
  font-size: 1.3125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 1.375rem 0 0.5rem;
  color: var(--text-primary);
}
.how-step-desc {
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 30ch;
  margin: 0;
}
.how-keycap {
  margin-top: 1rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.75rem;
  font-weight: 500;
  color: color-mix(in oklch, var(--color-text-primary) 70%, var(--color-text-secondary));
  padding: 0.5rem 0.8125rem;
  border-radius: 8px;
  border: 1px solid var(--border-primary);
  background: var(--color-surface-2);
}

/* =====================================================
   WHY — four reason cards (2x2). Reuses .pillar-card + .feature-icon-bg
   (the site's gradient feature-icon treatment), laid out horizontally (#439).
   ===================================================== */
.why-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}
.why-card {
  display: flex;
  gap: 1.25rem;
}
@media (max-width: 820px) {
  .how-grid {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
  .how-rail {
    display: none;
  }
  .why-grid {
    grid-template-columns: 1fr;
  }
}

/* =====================================================
   WHERE — verified-apps grid with real app logos (#439).
   ===================================================== */
.where-grid {
  display: grid;
  grid-template-columns: repeat(4, max-content);
  gap: 2.25rem 4rem;
  justify-content: center;
}
.where-cat {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: 1.25rem;
}
.where-apps {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.where-app {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: color-mix(in oklch, var(--color-text-primary) 62%, var(--color-text-secondary));
}
.where-tile {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--color-surface-2);
  border: 1px solid var(--border-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.where-tile img {
  width: 20px;
  height: 20px;
  object-fit: contain;
}
.where-note {
  margin-top: 2.5rem;
  padding-top: 1.625rem;
  border-top: 1px solid var(--border-subtle);
}
.where-note-inner {
  max-width: 66%;
  margin: 0 auto;
}
.where-note-row {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}
.where-note-row + .where-note-row {
  margin-top: 0.875rem;
}
.where-note-row p {
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--text-secondary);
  margin: 0;
}
.where-note-icon {
  flex-shrink: 0;
  margin-top: 1px;
}
.where-note-icon--ok {
  color: var(--color-success);
}
.where-note-icon--muted {
  color: var(--text-tertiary);
}
@media (max-width: 820px) {
  .where-grid {
    grid-template-columns: repeat(2, max-content);
    gap: 2rem 3rem;
    justify-content: center;
  }
  .where-note-inner {
    max-width: 100%;
  }
}

/* =====================================================
   COMPARE — 4-col grid, evoglyph column highlighted (#439).
   ===================================================== */
/* Cap the table width and center it so it doesn't sprawl across the full
   max-w-7xl container on wide screens (#467). */
.compare-wrap {
  max-width: 960px;
  margin-inline: auto;
}
.compare-grid {
  position: relative;
  display: grid;
  /* Fixed label column sized to fit the longest label with a little breathing
     room; the three comparison columns split the remaining width.
     --compare-label-w is the single source of truth shared with
     .compare-highlight's calc() below, so the track and the overlay can never
     drift (#467, widened #469). */
  --compare-label-w: 16rem;
  grid-template-columns: var(--compare-label-w) 1fr 1fr 1fr;
  font-size: 0.875rem;
}
/* Cells stretch to fill their row track and center their own content, so each
   row's top border lines up across every column even when a label wraps on
   mobile (#458). display:grid keeps the inline label+sub flow (unlike flex). */
.compare-cell,
.compare-head {
  display: grid;
  align-content: center;
}
/* The highlight card behind column 2 (evoglyph): starts after the fixed label
   column and spans exactly one comparison column. Derived from the same
   --compare-label-w as the track (inherited from .compare-grid) so the overlay
   tracks the columns at any table width — no hardcoded percentages (#467). */
.compare-highlight {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--compare-label-w);
  width: calc((100% - var(--compare-label-w)) / 3);
  border: 1px solid color-mix(in oklch, var(--accent-blue) 28%, transparent);
  border-radius: 14px;
  background: linear-gradient(
    180deg,
    color-mix(in oklch, var(--accent-blue) 10%, transparent),
    color-mix(in oklch, var(--accent-blue) 4%, transparent)
  );
  box-shadow: 0 0 50px -26px color-mix(in oklch, var(--accent-blue) 60%, transparent);
  z-index: 0;
  pointer-events: none;
}
.compare-head {
  padding: 1.125rem 1rem;
  text-align: center;
  /* Center each head's grid item horizontally too — the .compare-eg-name badge
     is a flex grid item that would otherwise stretch and pack its logo+wordmark
     at flex-start (left). text-align alone can't position a grid item (#464). */
  justify-items: center;
  font-weight: 600;
  color: var(--text-secondary);
}
.compare-cell {
  padding: 1rem;
  text-align: center;
  color: var(--text-secondary);
  border-top: 1px solid var(--border-subtle);
}
.compare-cell--label {
  text-align: left;
  color: color-mix(in oklch, var(--color-text-primary) 62%, var(--color-text-secondary));
}
/* evoglyph column sits above the highlight overlay. */
.compare-cell--eg {
  position: relative;
  z-index: 1;
}
.compare-eg-name {
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  font-weight: 700;
  color: var(--text-primary);
}
.compare-eg-name img {
  display: block;
}
.compare-sub {
  font-size: 0.75rem;
  color: var(--text-tertiary);
}
.compare-yes {
  color: var(--color-success);
  font-size: 0.875rem;
}
.compare-no {
  color: var(--text-tertiary);
  font-size: 0.875rem;
}
.compare-muted {
  font-size: 0.75rem;
  color: var(--text-secondary);
}
.compare-num {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-secondary);
}
.compare-num--eg {
  color: var(--text-primary);
}
.compare-built {
  font-size: 0.75rem;
  color: color-mix(in oklch, var(--color-text-primary) 62%, var(--color-text-secondary));
}
/* Deal footnote under the grid (#520 r6/r7): explains the asterisk on the
   struck evoglyph prices. Small muted caption carrying the copy pill;
   centered, with clear separation from the table's bottom edge. */
.compare-footnote {
  margin-top: 1.75rem;
  font-size: 0.75rem;
  text-align: center;
  color: var(--text-tertiary);
}
.compare-note {
  display: flex;
  align-items: flex-start;
  gap: 0.6875rem;
  margin-top: 1.75rem;
  padding: 1.125rem 1.25rem;
  border-radius: 12px;
  border: 1px solid var(--border-primary);
  background: var(--bg-card);
}
.compare-note-icon {
  flex-shrink: 0;
  margin-top: 1px;
  color: var(--eg-spectrum);
}
.compare-note p {
  font-size: 0.84rem;
  line-height: 1.6;
  color: var(--text-secondary);
  margin: 0;
}
/* Mobile: let the grid scroll horizontally rather than crush 4 columns. */
@media (max-width: 720px) {
  .compare-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .compare-grid {
    min-width: 540px;
  }
}

/* =====================================================
   PRICING — 3 tiers, mock layout (#439).
   ===================================================== */
.pricing-tier {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-secondary);
}
.pricing-price {
  display: flex;
  align-items: baseline;
  gap: 0.375rem;
  margin: 1.125rem 0 0.375rem;
}
.pricing-amount {
  font-size: 2.75rem;
  line-height: 1;
  font-weight: 500;
  color: var(--text-primary);
}
.pricing-per {
  font-size: 0.875rem;
  color: var(--text-tertiary);
}
.pricing-desc {
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--text-tertiary);
  margin-bottom: 1.5rem;
}
.pricing-save {
  color: var(--color-success);
}
.pricing-features {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.pricing-feature {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: 0.84rem;
  color: var(--text-secondary);
}
.pricing-check {
  flex-shrink: 0;
  color: var(--color-success);
}

/* BETA50 promotion presentation (#497 → #520). Struck standard price + per-card
   deep-blue code badge on the cards, plus one static "how to redeem" pill above
   the grid. Fully static markup — the promo code is applied by the buyer at
   Stripe checkout; ending the promo is a copy-only edit, no flag, no counter.
   The struck price is aria-hidden; the live price is announced. */
.pricing-price {
  flex-wrap: wrap;
}
/* Shared struck-original-price treatment (#520 r6): the deal is displayed as
   [struck standard] discounted everywhere a price appears numerically —
   tiles (.pricing-was), hero sub-lead + hero stat, final CTA, comparison
   column (.price-was, size inherits from context). The struck span is always
   aria-hidden so screen readers hear only the real price. */
.pricing-was,
.price-was {
  color: var(--text-tertiary);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
/* Tile price row keeps its larger struck size + baseline alignment. */
.pricing-was {
  align-self: baseline;
  font-size: 1.375rem;
  font-weight: 500;
}
/* Inside the big hero stat number, the struck original scales down the same
   way the tiles scale theirs (~half the live price). */
.hero-stat-num .price-was {
  font-size: 0.55em;
  font-weight: 500;
}
/* Bright discounted price in the prose lines (hero sub-lead, final CTA,
   #520 r7): the live amount pops near-white from the gray body text while
   the struck original stays muted. Same token the headings use. */
.price-now {
  color: var(--text-primary);
}
/* r8: in the hero the bright amounts are links into #pricing (same
   destination as the nav "Pricing" link). Underline conventions mirror
   .hero-benchmark-link; hover mirrors the site's opacity pattern; keyboard
   focus keeps the UA focus ring like the other inline text links. */
.price-link {
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: opacity 0.2s;
}
.price-link:hover {
  opacity: 0.8;
}
.pricing-beta-badge {
  /* Small-caps white "50% off with" + the copy pill on one row, reading as a
     sentence ("50% OFF WITH [CODE: BETA50]" — mirrors the hero/footer
     language); the pill wraps under the text on narrow cards. r7: the r4/r6
     wide-gap experiments are reverted — the connector word "with" is what
     the design wanted, with natural word-like spacing around the pill. The
     pill resets the badge's uppercase/tracking internally, then re-applies
     the same small-caps treatment to its own CODE: label. */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.4rem;
  flex-basis: 100%;
  margin-top: 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-primary);
}
.pricing-promo {
  /* Plain standalone line under the section header (the old border-pill
     treatment moved onto the .promo-pill component itself). */
  max-width: min(100%, 38rem);
  margin: 0 auto 2.25rem;
  font-size: 0.875rem;
  text-align: center;
  color: var(--text-secondary);
}

/* =====================================================
   BETA50 COPY PILL (#520) — the one branded promo-code component.
   A pill-shaped <button> used inline wherever the code is named:
   CODE: in the small uppercase sans (white — same treatment as the tiles'
   "50% off" label) + BETA50 in JetBrains Mono in the #500 deep blue + a
   Lucide copy glyph. Click copies the code (see script.js
   [data-copy-code] module); .is-copied swaps the glyph to a check via
   display toggles only — no transitions, so the state change is
   reduced-motion safe by construction. The opaque ink-850 fill +
   hairline border read identically on the canvas and on cards. */
.promo-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.65rem 0.2rem 0.6rem;
  border: 1px solid var(--border-primary);
  border-radius: 999px;
  background: var(--bg-tertiary);
  cursor: pointer;
  vertical-align: baseline;
  white-space: nowrap; /* the pill never breaks internally */
  /* Neutralise inherited context (uppercase badge, hero tracking, …). */
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: normal;
  text-transform: none;
}
.promo-pill:hover {
  border-color: var(--color-border-strong);
  background: var(--bg-card-hover);
}
.promo-pill-label {
  /* Same small-caps sans treatment as the tiles' "50% off" label. Source
     text stays lowercase ("code:") and is uppercased here — the same
     mechanism the badge uses — overriding the pill's text-transform reset. */
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-primary);
}
.promo-pill-code {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 600;
  letter-spacing: 0.02em;
  /* ~4.9:1 on the pill's ink-850 fill — passes WCAG AA for the 13px text
     (same #500 blue the tiles already clear at ~5:1 on ink-900 cards). */
  color: var(--accent-blue-deep);
}
.promo-pill-icon {
  flex-shrink: 0;
  color: var(--text-tertiary);
}
/* Copy ↔ check swap: both glyphs are in the DOM; the class shows one. */
.promo-pill .promo-pill-icon-check {
  display: none;
}
.promo-pill.is-copied .promo-pill-icon-copy {
  display: none;
}
.promo-pill.is-copied .promo-pill-icon-check {
  display: inline-block;
  color: var(--color-success);
}
/* Visually-hidden per-pill live region ("Copied" announcement). Self-contained
   rather than Tailwind's sr-only so the pill works on every page styles.css
   reaches. */
.promo-pill-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* =====================================================
   PRIVACY under-the-hood — models + pipeline panel (#439).
   ===================================================== */
.hood {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  border: 1px solid var(--border-primary);
  border-radius: 18px;
  background: var(--bg-card);
  overflow: hidden;
  margin-top: 1.5rem;
}
.hood-panel {
  padding: 2.125rem 2.25rem;
}
.hood-panel--models {
  border-right: 1px solid var(--border-subtle);
}
.hood-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.hood-rows {
  display: flex;
  flex-direction: column;
  margin-top: 1.5rem;
}
.hood-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--border-subtle);
}
.hood-row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}
.hood-row-title {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-primary);
}
.hood-row-sub {
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-tertiary);
  margin-top: 0.25rem;
}
.hood-badge {
  flex-shrink: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-secondary);
  padding: 0.375rem 0.6875rem;
  border-radius: 7px;
  border: 1px solid var(--border-primary);
  background: var(--color-surface-2);
  white-space: nowrap;
}
.hood-badge--local {
  color: var(--color-success);
  border-color: color-mix(in oklch, var(--color-success) 28%, transparent);
  background: color-mix(in oklch, var(--color-success) 8%, transparent);
}
.hood-pipe {
  position: relative;
  margin-top: 1.5rem;
}
.hood-pipe-rail {
  position: absolute;
  left: 13px;
  top: 14px;
  bottom: 14px;
  width: 1px;
  background: linear-gradient(
    180deg,
    color-mix(in oklch, var(--accent-blue) 40%, transparent),
    color-mix(in oklch, #7fffff 40%, transparent)
  );
}
.hood-pipe-steps {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1.125rem;
}
.hood-pipe-step {
  display: flex;
  align-items: center;
  gap: 0.875rem;
}
.hood-pipe-num {
  flex-shrink: 0;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: var(--color-surface-1);
  border: 1px solid color-mix(in oklch, var(--accent-blue) 40%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  font-weight: 500;
  color: var(--accent-blue);
}
.hood-pipe-num--final {
  border: 1.5px solid transparent;
  background:
    linear-gradient(var(--color-surface-1), var(--color-surface-1)) padding-box,
    var(--eg-mbc) border-box;
  color: #7fffff;
}
.hood-pipe-label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-secondary);
}
.hood-pipe-note {
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-tertiary);
  margin-top: 1.375rem;
  padding-top: 1.125rem;
  border-top: 1px solid var(--border-subtle);
}
@media (max-width: 820px) {
  .hood {
    grid-template-columns: 1fr;
  }
  .hood-panel--models {
    border-right: 0;
    border-bottom: 1px solid var(--border-subtle);
  }
}

/* #439: privacy cards use smaller type than the why-cards (mock: 16px title,
   13.5px body), so scope these overrides to .privacy-claim-card only. */
.privacy-claim-card h3 {
  font-size: 1rem;
}
.privacy-claim-card p {
  font-size: 0.84rem;
}

/* =====================================================
   FAQ — single bordered container w/ divider rows (#439). Overrides the older
   separate-card .faq-item look; keeps the grid-height open/close animation.
   ===================================================== */
.faq-list {
  border: 1px solid var(--border-primary);
  border-radius: 16px;
  overflow: hidden;
  background: var(--bg-card);
}
.faq-list .faq-item {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--border-subtle);
  border-radius: 0;
}
.faq-list .faq-item:last-child {
  border-bottom: 0;
}
.faq-list .faq-item:hover {
  border-color: var(--border-subtle);
}
.faq-list .faq-item.open {
  background: transparent;
  border-color: var(--border-subtle);
}
.faq-list .faq-trigger span {
  font-size: 0.9375rem;
}
.faq-list .faq-content p {
  font-size: 0.875rem;
}

/* =====================================================
   FINAL CTA — card-less centered section + bottom glow (#439).
   ===================================================== */
.cta-title {
  font-family:
    'Inter',
    -apple-system,
    sans-serif;
  font-weight: 600;
  font-size: clamp(2.125rem, 5vw, 3.25rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
  color: var(--text-primary);
}
.cta-glow {
  position: absolute;
  bottom: -180px;
  left: 50%;
  transform: translateX(-50%);
  width: 820px;
  max-width: 100%;
  height: 460px;
  pointer-events: none;
  background: radial-gradient(
    ellipse 55% 60% at 50% 100%,
    color-mix(in oklch, var(--accent-blue) 16%, transparent),
    color-mix(in oklch, #ff7bfd 9%, transparent) 45%,
    transparent 72%
  );
}
/* The final CTA reuses the hero free-trial component (#484). The hero instance
   is left-aligned inside the left-aligned hero column; here the section is
   centered, so center the flex row to match. */
#get-started .hero-trial {
  justify-content: center;
}
/* #439: CTA 'See pricing' reads as a clean transparent ghost w/ bright label
   (mock); the open FAQ caret takes the accent; carets are 16px (mock). */
#get-started .cta-secondary {
  background: transparent;
  color: var(--text-primary);
}
.faq-list .faq-icon {
  width: 16px;
  height: 16px;
}
.faq-list .faq-item.open .faq-icon {
  color: var(--accent);
}

/* #439: footer status badge uses mono type (matches the mock). */
.footer-status {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  font-weight: 500;
}

/* #439: offset in-page anchor jumps for the fixed nav (the smooth-scroll JS
   uses scrollIntoView, which honours scroll-padding) so a nav link like
   Speed -> #cleanup lands below the bar, not hidden under it. */
html {
  scroll-padding-top: 5rem;
}

/* ---------- Menu-bar dictation HUD (replaces the old speed bar + sound wave) ----------
   A dark "device" panel echoing the app's menu-bar HUD. min-height reserves
   space so the animated content does not shift layout (CLS guard). */
.hud {
  position: relative;
  background: oklch(0.13 0.014 264);
  border: 1px solid var(--color-border-strong, var(--border-primary));
  border-radius: 16px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.hud-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  background: oklch(1 0 0 / 0.03);
  border-bottom: 1px solid oklch(1 0 0 / 0.06);
}
.hud-status {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.hud-rec {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-emerald);
  flex-shrink: 0;
}
.hud-body {
  padding: 1.25rem 1.25rem 1.5rem;
}
/* Waveform: reuses the .wave-bar scaleY keyframe (defined above). Bars take the
   MBC gradient so the HUD reads as the brand's "listening" state. */
.hud-wave {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 40px;
}
.hud-wave .wave-bar {
  flex: 1;
  max-width: 5px;
  height: 100%;
  border-radius: 3px;
  background: var(--eg-mbc);
  transform-origin: center;
}
.hud-recognized {
  margin-top: 1rem;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--text-primary);
}
.hud-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.85rem;
  padding: 0.2rem 0.55rem;
  border-radius: 7px;
  border: 1px solid var(--border-primary);
  background: oklch(1 0 0 / 0.03);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.75rem;
  color: var(--text-secondary);
}

/* ---------- Cleanup story: speed callout + coverage chips + disclaimer ---------- */
.speed-callout {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.speed-num {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: clamp(2.5rem, 6vw, 3.5rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  background: var(--eg-mbc);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--eg-spectrum);
}
.coverage-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--border-primary);
  background: var(--bg-card);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.75rem;
  color: var(--text-secondary);
}
.latency-note {
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--text-tertiary);
}

/* ---------- 16-app chip strip (replaces the heavy SVG app grid) ---------- */
.app-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.75rem;
  border-radius: 8px;
  border: 1px solid var(--border-primary);
  background: var(--bg-card);
  font-size: 0.8125rem;
  color: var(--text-secondary);
  transition:
    border-color 150ms ease,
    color 150ms ease;
}
.app-chip:hover {
  border-color: var(--border-subtle);
  color: var(--text-primary);
}

/* ---------- "verify:" line — monospace, emerald (privacy grid) ---------- */
.verify-line {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--color-emerald);
}

/* ---------- Social proof: example ribbon + initials avatar ---------- */
.example-ribbon {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  border: 1px dashed var(--accent);
  background: var(--accent-muted);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.avatar-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--eg-mbc);
  color: oklch(0.18 0.02 264);
  font-weight: 700;
  font-size: 0.8125rem;
  flex-shrink: 0;
}
.star-rating {
  color: var(--color-emerald);
  letter-spacing: 0.1em;
}

/* ---------- Comparison: CSS grid (not a table), highlighted evoglyph column ----------
   Desktop: 5 columns (feature label + evoglyph + 3 competitors). The evoglyph
   column is tinted and its header wears the MBC gradient-ring. Mobile (<720px):
   collapses to label + evoglyph + ONE competitor chosen by the .cmp-switcher;
   script.js sets .cmp--wispr / --super / --open and the inactive competitor
   cells are hidden. No latency row (it left for its own callout in §cleanup). */
.cmp {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(4, minmax(0, 1fr));
  border: 1px solid var(--border-primary);
  border-radius: 16px;
  overflow: hidden;
  background: var(--bg-card);
}
.cmp-cell {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.9rem 1rem;
  border-top: 1px solid var(--border-subtle);
  font-size: 0.9rem;
  min-width: 0;
}
.cmp-head {
  border-top: 0;
  font-weight: 600;
  color: var(--text-primary);
  justify-content: center;
}
.cmp-row-label {
  color: var(--text-secondary);
  justify-content: flex-start;
}
.cmp-value {
  justify-content: center;
  text-align: center;
  color: var(--text-secondary);
}
/* evoglyph column tint + gradient-ring header chip. */
.cmp-eg {
  background: var(--accent-muted);
  color: var(--text-primary);
}
.cmp-eg.cmp-head {
  position: relative;
}
.cmp-eg.cmp-head::before {
  content: '';
  position: absolute;
  inset: 0.5rem 0.4rem;
  border-radius: 999px;
  padding: 1.5px;
  background: var(--eg-mbc) border-box;
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
.cmp-yes {
  color: var(--color-emerald);
  font-weight: 700;
}
.cmp-no {
  color: var(--text-tertiary);
}
.cmp-switcher {
  display: none;
}
@media (max-width: 720px) {
  .cmp {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  }
  .cmp-switcher {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
  }
  .cmp-switch-btn {
    padding: 0.4rem 0.85rem;
    border-radius: 999px;
    border: 1px solid var(--border-primary);
    background: var(--bg-card);
    color: var(--text-secondary);
    font-size: 0.8125rem;
    transition:
      border-color 150ms ease,
      color 150ms ease,
      background-color 150ms ease;
  }
  .cmp-switch-btn[aria-pressed='true'] {
    border-color: var(--accent);
    background: var(--accent-muted);
    color: var(--text-primary);
  }
  /* Hide all competitor cells, then reveal the active one. */
  .cmp-c-wispr,
  .cmp-c-super,
  .cmp-c-open {
    display: none;
  }
  .cmp--wispr .cmp-c-wispr,
  .cmp--super .cmp-c-super,
  .cmp--open .cmp-c-open {
    display: flex;
  }
}

/* Reduced-motion: freeze the HUD waveform + decorative pulses at a static
   frame (build note: "paused under reduced-motion, show a static frame"). */
@media (prefers-reduced-motion: reduce) {
  .wave-bar,
  .recording-pulse,
  .cursor-blink,
  .pulse-dot {
    animation: none !important;
    transform: none !important;
  }
}

/* ---------- Nav: scroll tint (#417) + gradient Download (#439) ----------
   The bar is transparent over the canvas with a single hairline underline; on
   scroll a faint 6% white tint fades in (no blur — decision L3). The Download
   uses the shared MBC gradient-ring treatment (see the .cta-primary group
   above) to match the Jun-28 mock — the #417 solid-pill override is gone. */
#navbar {
  border-bottom: 1px solid var(--color-border-subtle);
  transition: background-color 300ms ease;
}
#navbar.scrolled {
  background: color-mix(in oklch, oklch(1 0 0) 6%, var(--color-canvas));
  border-bottom-color: var(--color-border-hairline);
}
/* Mobile menu toggle: the visible icon is 24px; extend the tap target to
   44x44 via a transparent ::after (surfaces §Minimum Hit Area), mirroring the
   .footer-social pattern. The toggle sits alone at the bar's right edge, so the
   extended target never overlaps a neighbour. */
#mobile-menu-toggle {
  position: relative;
}
#mobile-menu-toggle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}
/* #439: nav Download uses the shared MBC gradient-ring treatment (transparent
   pill + ring + white label, from the .cta-primary group above) to match the
   Jun-28 mock. The #417 solid-neutral-pill override was removed. */
.nav-cta:active {
  transform: scale(0.96);
}
.nav-cta:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* =====================================================
   ACCOUNT / AUTH SURFACE (account.html)

   Restores the auth-* component classes that previously lived in login.css
   (deleted in #415 along with the dead mock login/dashboard pages). account.html
   — the real account/sign-in page — still consumes them, so the page rendered
   borderless + nearly invisible without these rules (#503). Consolidated here
   rather than in a separate login.css: account.html already loads styles.css,
   and the build's content-hash rewrite keeps this single <link> in sync. A
   standalone login.css left a stale, 404-ing hashed href behind.

   Dark-mode only (#223); every value reads a shared semantic token.
   ===================================================== */

/* Soft accent-tinted radial wash behind the card. */
.auth-glow {
  background:
    radial-gradient(ellipse 60% 50% at 50% 0%, var(--accent-muted) 0%, transparent 60%),
    radial-gradient(ellipse 40% 40% at 80% 80%, var(--accent-muted) 0%, transparent 60%);
}

.auth-card {
  background: var(--bg-card);
  border: 1px solid var(--border-primary);
  box-shadow: var(--shadow-lg);
  transition-property: box-shadow, border-color, background-color;
  transition-duration: 0.2s;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

/* Email field + the license-key display box. The resting border meets WCAG
   1.4.11 non-text contrast (≈4.6:1 against both the field fill and the card
   behind it). The design system's hairline border (~2.5:1) does NOT clear the
   3:1 bar, which — combined with Tailwind Preflight's border-0 reset — left the
   field invisible on the dark canvas (#503). */
.auth-input {
  background: var(--bg-tertiary);
  border: 1px solid color-mix(in oklch, var(--color-text-primary) 22%, transparent);
  color: var(--text-primary);
  transition-property: background-color, border-color, box-shadow, color;
  transition-duration: 0.2s;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.auth-input::placeholder {
  color: var(--text-tertiary);
}

.auth-input:focus {
  border-color: var(--accent);
  background: var(--bg-card-hover);
}

/* Keyboard focus indicator — same outline convention as the rest of the site. */
.auth-input:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.auth-link-btn {
  color: var(--text-secondary);
  cursor: pointer;
  transition-property: color, transform;
  transition-duration: 0.15s;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.auth-link-btn:hover {
  color: var(--accent-text);
}

.auth-link-btn:active {
  transform: scale(0.96);
}
