/* Doppel marketing surface — Home, Download, Privacy architecture.
   Separate from styles.css, which stays untouched for the legal/verification
   pages (privacy.html, terms.html, support.html). No framework, no build step.

   Palette derives from the app's :root (src/renderer/styles.css) so app
   screenshots sit natively on the page. --web-bg is one step darker than the
   app's --bg so embedded UI reads as a raised object. */

:root {
  --web-bg: #151824;
  --web-surface: #1e2230;   /* == app --bg */
  --web-raised: #272c3d;    /* == app --bg-raised */
  --web-border: #383f54;    /* == app --border. Hairlines/dividers (decorative). */
  --web-border-strong: #6a748c; /* Interactive boundaries (form fields): >=3:1 on --web-bg for WCAG 1.4.11. */
  --web-text: #e8eaf0;      /* == app --text */
  --web-dim: #aab1c4;       /* == app --text-dim */
  --web-accent: #3eafd1;    /* == app --accent. The one accent. */
  --web-verify: #3aa85a;    /* == app --accent-ready. Status only, never selection. */

  /* Type. PLACEHOLDER STACKS — spec §4 calls for self-hosted Newsreader +
     Inter. Swap --font-display / --font-sans once the woff2 files land in
     site/fonts/ and @font-face blocks are added below. Self-hosting is
     required: a Google Fonts request would contradict the page's own claim. */
  --font-display: Georgia, 'Times New Roman', serif;
  --font-sans: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Consolas, monospace;

  --fs-hero: 56px;
  --fs-1: 40px;
  --fs-2: 28px;
  --fs-3: 20px;
  --fs-body: 16px;
  --lh-tight: 1.2;
  --lh-body: 1.6;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;  /* extends the app's 4-based scale on its own 1.5x ratio: 32 -> 48 -> 72 */
  --space-8: 72px;

  --radius: 14px;
  --radius-ctl: 8px;
  --max: 1080px;
  --max-prose: 660px;
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--web-bg);
  color: var(--web-text);
  font: var(--fs-body)/var(--lh-body) var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

/* ---------- shared primitives ---------- */

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--space-5); }
.prose { max-width: var(--max-prose); }

a { color: var(--web-accent); }

/* Content links carry a non-color cue (WCAG 1.4.1). Nav, buttons, and footer
   links are distinguished by position/shape and are excepted. */
main a:not(.btn) { text-decoration: underline; text-underline-offset: 2px; }

:focus-visible {
  outline: 2px solid var(--web-accent);
  outline-offset: 2px;
  border-radius: 2px;
}

.eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;   /* presentational only; DOM text stays natural case */
  color: var(--web-dim);
  margin: 0 0 var(--space-3);
}

h1, h2, h3 {
  font-family: var(--font-display);
  line-height: var(--lh-tight);
  font-weight: 700;
  margin: 0 0 var(--space-4);
}

h1 { font-size: var(--fs-1); }
h2 { font-size: var(--fs-2); }
h3 { font-size: var(--fs-3); font-weight: 600; }

p { margin: 0 0 var(--space-4); }
.dim { color: var(--web-dim); }
.lead { font-size: var(--fs-3); color: var(--web-dim); }

/* ---------- header ---------- */

.site-header {
  border-bottom: 1px solid var(--web-border);
  position: sticky;
  top: 0;
  background: color-mix(in srgb, var(--web-bg) 88%, transparent);
  backdrop-filter: blur(8px);
  z-index: 10;
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: 64px;
}

.brand {
  font-family: var(--font-display);
  font-size: var(--fs-3);
  font-weight: 700;
  color: var(--web-text);
  text-decoration: none;
  margin-right: auto;
}

/* Nav is a <details> disclosure: an accessible, JS-free hamburger on mobile,
   an inline row on desktop. On desktop the author `display:flex` on .site-nav
   beats the UA "details:not([open]) > * { display:none }" rule by cascade
   ORIGIN, so the links always show and the toggle is hidden. On mobile we set
   no display on .site-nav, letting the UA hide it when closed and reveal it
   when [open]. This replaced an earlier rule that simply hid every link on
   mobile, leaving only the Download button reachable. */
.nav-wrap { position: relative; }

.nav-toggle {                       /* the hamburger; hidden on desktop */
  display: none;
  list-style: none;
  cursor: pointer;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--web-border-strong);
  border-radius: var(--radius-ctl);
  color: var(--web-text);
  font: 600 14px/1 var(--font-sans);
}
.nav-toggle::-webkit-details-marker { display: none; }
.nav-bars, .nav-bars::before, .nav-bars::after {
  display: block; width: 18px; height: 2px; background: currentColor; border-radius: 2px;
}
.nav-bars { position: relative; }
.nav-bars::before, .nav-bars::after { content: ''; position: absolute; left: 0; }
.nav-bars::before { top: -6px; }
.nav-bars::after { top: 6px; }

.site-nav { align-items: center; gap: var(--space-5); }

.site-nav a {
  color: var(--web-dim);
  text-decoration: none;
  font-size: 14px;
  padding: var(--space-1) 0;   /* lifts the desktop hit area to ~30px (WCAG 2.5.8 24px floor) */
}

.site-nav a:hover,
.site-nav a[aria-current='page'] { color: var(--web-text); }

@media (min-width: 721px) {
  .site-nav { display: flex; }      /* author beats UA hide → always visible */
  .nav-toggle { display: none; }
}

@media (max-width: 720px) {
  .nav-toggle { display: inline-flex; }
  .site-nav {                        /* dropdown panel; hidden until [open] */
    display: none;                   /* explicit — do not rely on UA details hide */
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    z-index: 20;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-1);
    min-width: 220px;
    padding: var(--space-3);
    background: var(--web-surface);
    border: 1px solid var(--web-border-strong);
    border-radius: var(--radius);
    box-shadow: 0 16px 40px -16px rgba(0, 0, 0, 0.7);
  }
  .nav-wrap[open] .site-nav { display: flex; }
  .site-nav a {                      /* full-width, 44px touch rows */
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--space-3);
    font-size: 16px;
    border-radius: var(--radius-ctl);
  }
  .site-nav a.btn { justify-content: center; margin-top: var(--space-2); }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-ctl);
  padding: 11px 18px;
  font: 600 14px/1 var(--font-sans);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.22s var(--spring), box-shadow 0.22s ease, background 0.22s ease;
}

.btn-primary {
  background: var(--web-accent);
  color: #0d1117;
}

.btn-primary:hover {
  transform: scale(1.05);
  box-shadow: 0 0 0 1px var(--web-accent), 0 6px 24px -6px var(--web-accent);
}

.btn-primary:active { transform: scale(0.95); }

.btn-secondary {
  background: transparent;
  border-color: var(--web-border);
  color: var(--web-text);
}

.btn-secondary:hover { background: var(--web-raised); }

.btn-lg { padding: 15px 26px; font-size: 16px; }

/* ---------- sections ---------- */

/* Interior narrative sections read lighter; the two conversion moments — the
   hero (weighted by the Mirror) and the closing CTA — carry more, so the eye is
   paced toward the download instead of meeting nine equal-weight blocks.
   Section dividers were removed: 96px of whitespace (proximity) separates
   sections already, and the old 1px line sat at 1.69:1 — below perceptibility. */
section { padding: var(--space-7) 0; }
.section-cta { padding: var(--space-8) 0; background: var(--web-surface); }

.hero { padding-top: var(--space-7); position: relative; overflow: hidden; }

/* The one permitted glow — spends the boldness budget behind the demo only. */
.hero::before {
  content: '';
  position: absolute;
  top: -180px;
  left: 50%;
  width: 900px;
  height: 620px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center,
    color-mix(in srgb, var(--web-accent) 16%, transparent) 0%,
    transparent 68%);
  pointer-events: none;
  z-index: 0;
}

.hero .wrap { position: relative; z-index: 1; }

.hero h1 {
  font-size: var(--fs-hero);
  max-width: 16ch;
  margin-bottom: var(--space-5);
}

@media (max-width: 720px) {
  .hero h1 { font-size: var(--fs-1); }
  :root { --fs-1: 32px; --fs-2: 24px; }
}

.hero-sub {
  color: var(--web-dim);
  font-size: var(--fs-3);
  margin-bottom: var(--space-6);
}

.hero-cta {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-top: var(--space-6);
}

.hero-cta .version { color: var(--web-dim); font-size: 13px; }

/* ---------- the Mirror demo ---------- */

.mirror {
  background: var(--web-surface);
  border: 1px solid var(--web-border);
  border-radius: var(--radius);
  overflow: hidden;
  max-width: 860px;
  box-shadow: 0 24px 60px -24px rgba(0, 0, 0, 0.7);
}

.mirror-chrome {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 10px var(--space-4);
  border-bottom: 1px solid var(--web-border);
  background: var(--web-raised);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--web-dim);
}

.mirror-chrome .tag {
  margin-left: auto;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 600;
  border: 1px solid var(--web-border);
  border-radius: 999px;
  padding: 2px 10px;
}

.mirror-panes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 220px;
}

@media (max-width: 720px) {
  .mirror-panes { grid-template-columns: 1fr; }
  .mirror-panes .pane + .pane { border-left: 0; border-top: 1px solid var(--web-border); }
}

.pane { padding: var(--space-5); }
.pane + .pane { border-left: 1px solid var(--web-border); }
.pane-label { font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--web-dim); margin-bottom: var(--space-3); }

#mirror-input {
  width: 100%;
  min-height: 140px;
  resize: vertical;
  background: transparent;
  border: 0;
  color: var(--web-text);
  font: var(--fs-body)/var(--lh-body) var(--font-sans);
  padding: 0;
}

/* Keep a visible focus indicator (WCAG 2.4.7). The textarea is borderless by
   design, so on focus we ring the whole input rather than remove the outline. */
#mirror-input:focus-visible {
  outline: 2px solid var(--web-accent);
  outline-offset: 4px;
  border-radius: 4px;
}
#mirror-input::placeholder { color: var(--web-dim); opacity: 0.85; }

#mirror-output { min-height: 140px; white-space: pre-wrap; }
#mirror-output:empty::before { content: attr(data-empty); color: var(--web-dim); opacity: 0.7; }

.caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  background: var(--web-accent);
  vertical-align: text-bottom;
  animation: blink 1s steps(2) infinite;
}

@keyframes blink { 50% { opacity: 0; } }

/* The ledger — the proof beat. */
.ledger {
  border-top: 1px solid var(--web-border);
  background: var(--web-bg);
  padding: var(--space-4) var(--space-5);
  font: 13px/1.8 var(--font-mono);
  color: var(--web-dim);
}

.ledger-row { display: flex; align-items: baseline; gap: var(--space-2); }
.ledger-row .fill { flex: 1; border-bottom: 1px dotted var(--web-border); transform: translateY(-4px); }
.ledger-row .count { color: var(--web-text); font-variant-numeric: tabular-nums; }

.ledger-row .check {
  color: var(--web-verify);
  opacity: 0;
  transition: opacity 0.4s ease;
}

.ledger-row .check.is-shown { opacity: 1; }

/* ---------- proof sections ---------- */

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: center;
}

@media (max-width: 860px) { .split { grid-template-columns: 1fr; gap: var(--space-6); } }

/* Screenshot placeholders. Dimensions are set on the element so swapping in
   a real AVIF causes zero layout shift. */
.shot {
  display: block;
  width: 100%;
  height: auto;
  background: var(--web-surface);
  border: 1px solid var(--web-border);
  border-radius: var(--radius);
}

/* Stands in for a screenshot not yet captured. Styled as an intentional frame
   rather than dev scaffolding, since the site may go live before the captures
   exist. Swap instructions are in an HTML comment beside each instance. */
.shot-placeholder {
  display: grid;
  place-content: center;
  gap: var(--space-2);
  text-align: center;
  background: var(--web-surface);
  border: 1px solid var(--web-border);
  border-radius: var(--radius);
  color: var(--web-dim);
  padding: var(--space-6);
  font: 14px/1.6 var(--font-sans);
}

.shot-placeholder .dims {
  color: var(--web-text);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* A captioned screenshot. `.shot` above already handles the image itself
   (block, full-width, height:auto, framed); this only supplies the wrapper,
   because a bare <figure> carries a UA default `margin: 1em 40px` that would
   inset the image ~80px narrower than the surrounding prose — very visible in
   the download page's step list, and worse the narrower the viewport. */
figure.shot-figure {
  margin: var(--space-5) 0;
}

figure.shot-figure figcaption {
  margin-top: var(--space-2);
  color: var(--web-dim);
  font: 14px/1.6 var(--font-sans);
}

/* The two-outcome check on the download page's Publisher card. A real <ul> so
   assistive tech announces "list, 2 items" — the fork between "ours" and "not
   ours" is the point, and a <br>-split paragraph hides it. Scoped by class:
   web.css is shared by five pages and there is no generic prose `ul` rule to
   inherit from, so an unscoped selector would be both unstyled and a blast
   radius. The ✓/✗ glyphs are aria-hidden in the markup — each is redundant
   with the sentence that follows it. */
ul.verify-list {
  margin: var(--space-3) 0 0;
  padding-left: var(--space-4);
  list-style: none;
}

ul.verify-list li + li {
  margin-top: var(--space-2);
}

ul.verify-list li > span[aria-hidden] {
  display: inline-block;
  width: var(--space-4);
  margin-left: calc(var(--space-4) * -1);
}

/* ---------- data ledger table ---------- */

.data-ledger {
  width: 100%;
  border-collapse: collapse;
  font: 14px/1.6 var(--font-mono);
  margin: var(--space-5) 0;
}

.data-ledger th,
.data-ledger td {
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--web-border);
  vertical-align: top;
}

.data-ledger th {
  color: var(--web-dim);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.data-ledger td code { color: var(--web-text); }

/* ---------- numbered steps (/download) ---------- */

.steps { list-style: none; counter-reset: step; padding: 0; margin: 0; }

.steps > li {
  counter-increment: step;
  position: relative;
  padding-left: 56px;
  margin-bottom: var(--space-7);
}

.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -2px;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid var(--web-border);
  background: var(--web-surface);
  font: 700 15px/1 var(--font-mono);
  color: var(--web-accent);
}

.card {
  background: var(--web-surface);
  border: 1px solid var(--web-border);
  border-radius: var(--radius);
  padding: var(--space-5);
}

.checksum {
  font: 13px/1.7 var(--font-mono);
  color: var(--web-dim);
  word-break: break-all;
}

.checksum strong { color: var(--web-text); font-weight: 600; }

/* ---------- signup form (/beta) ---------- */

.signup {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin: var(--space-5) 0 var(--space-3);
}

.signup input[type='email'] {
  flex: 1 1 260px;
  min-width: 0;
  min-height: 44px;               /* touch target */
  background: var(--web-bg);
  border: 1px solid var(--web-border-strong);  /* >=3:1 boundary (WCAG 1.4.11) */
  border-radius: var(--radius-ctl);
  color: var(--web-text);
  font: var(--fs-body)/1 var(--font-sans);
  padding: 12px 14px;
}

.signup input[type='email']::placeholder { color: var(--web-dim); opacity: 0.7; }
.signup input[type='email']:focus { outline: 2px solid var(--web-accent); outline-offset: 1px; }

.signup button { border: 0; }
.signup button[disabled] { opacity: 0.5; cursor: default; }

/* Lives inside .signup (a flex row); force it onto its own line. */
.signup-status {
  flex: 1 0 100%;
  font-size: 14px;
  color: var(--web-dim);
  min-height: 1.4em;
  margin: 0;
}
.signup-status.is-ok { color: var(--web-verify); }
.signup-status.is-warn { color: var(--web-text); }

/* ---------- download key gate (/download) ---------- */

/* .signup sets `display: flex` (author origin), which beats the UA
   `[hidden] { display: none }` rule by cascade ORIGIN — same shape of bug as
   the nav-wrap note above. download.js sets `form.hidden = true` /
   `panel.hidden = false` after issuance, so the attribute must win here or
   the form stays visible next to the key panel. Explicit compound selectors
   (class + attribute) outrank the single-class `.signup`/`.key-panel` rules
   on specificity alone — no !important needed, consistent with the rest of
   this file. */
.keygate[hidden], .key-panel[hidden] { display: none; }

.keygate { flex-direction: column; align-items: stretch; gap: var(--space-3); }
.keygate-field label { display: block; font-weight: 600; margin-bottom: 6px; }
.keygate-help { font-size: 14px; margin: 6px 0 0; }

.key-panel {
  border: 1px solid var(--web-border);
  border-radius: 12px;
  background: var(--web-raised);
  padding: 20px;
  margin-top: 16px;
}
.key-panel-title { font-weight: 700; margin: 0 0 8px; }
.key-code {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 15px;
  word-break: break-all;
  user-select: all;
  background: var(--web-bg);
  border: 1px solid var(--web-border);
  border-radius: 8px;
  padding: 12px;
  margin: 0 0 12px;
}
.key-email {
  color: var(--web-dim);
  margin: 0 0 var(--space-3);
  word-break: break-all;
}
.key-panel button + button { margin-left: var(--space-2); }

/* ---------- changelog (/beta) ---------- */

.changelog { list-style: none; padding: 0; margin: var(--space-5) 0 0; }

.changelog > li {
  padding: var(--space-5) 0;
  border-top: 1px solid var(--web-border);
}

.changelog .ver {
  font: 700 13px/1 var(--font-mono);
  color: var(--web-accent);
  display: inline-block;
  margin-bottom: var(--space-3);
}

.changelog h3 { margin-bottom: var(--space-2); }
.changelog p { margin: 0; color: var(--web-dim); }

/* ---------- FAQ ---------- */

.faq { margin: var(--space-5) 0 0; }

.faq details {
  border-top: 1px solid var(--web-border);
  padding: var(--space-4) 0;
}

.faq details:last-of-type { border-bottom: 1px solid var(--web-border); }

.faq summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--fs-3);
  font-weight: 600;
  line-height: var(--lh-tight);
  list-style: none;
  display: flex;
  gap: var(--space-4);
  align-items: baseline;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: '+';
  margin-left: auto;
  color: var(--web-accent);
  font-family: var(--font-mono);
  font-size: 20px;
  line-height: 1;
  flex: none;
}

.faq details[open] summary::after { content: '\2013'; }

.faq details > *:not(summary) { margin-top: var(--space-3); color: var(--web-dim); }
.faq details > p:last-child { margin-bottom: 0; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--web-border);
  padding: var(--space-6) 0 var(--space-7);
  color: var(--web-dim);
  font-size: 13px;
}

.site-footer .wrap { display: flex; gap: var(--space-5); flex-wrap: wrap; align-items: center; }
.site-footer nav { display: flex; gap: var(--space-4); margin-left: auto; flex-wrap: wrap; }
.site-footer a { color: var(--web-dim); text-decoration: none; }
.site-footer a:hover { color: var(--web-text); }

/* ---------- scroll reveal ----------
   Progressive enhancement, deliberately. Content is VISIBLE by default; the
   hidden state is scoped to .js-reveal, which mirror.js adds to <html> only
   after confirming an IntersectionObserver actually delivers callbacks.

   Do not move the hidden state out of .js-reveal. A plain `.reveal {opacity:0}`
   strands every section invisible whenever JS is blocked, fails to parse, or —
   as observed in a snapshot renderer — IO exists but never fires. The animation
   is decoration; the content is not. */

.js-reveal .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.js-reveal .reveal.is-in { opacity: 1; transform: none; }

/* ---------- accessibility utilities ---------- */

/* Skip-to-content: first focusable element, off-screen until focused (508 2.4.1). */
.skip-link {
  position: absolute;
  left: var(--space-2);
  top: -60px;
  z-index: 30;
  background: var(--web-accent);
  color: #0d1117;
  padding: 10px 16px;
  border-radius: var(--radius-ctl);
  font: 600 14px/1 var(--font-sans);
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus { top: var(--space-2); }

/* Visually hidden but available to screen readers. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* Comfortable touch targets on every button (WCAG 2.5.5 / mobile). */
.btn { min-height: 44px; }

/* Any wide element (tables) scrolls inside its own box — the page body never
   scrolls sideways on small screens. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---------- section head (centered eyebrow + heading + lead) ---------- */

.section-head { max-width: var(--max-prose); margin: 0 auto var(--space-7); text-align: center; }
.section-head .eyebrow { margin-bottom: var(--space-3); }
.section-head h2 { margin-bottom: var(--space-4); }
.section-head .lead { margin: 0; }
.center { text-align: center; }

/* ---------- the Problem (plain list, large) ---------- */

.problem-list { max-width: var(--max-prose); margin: 0 auto; padding: 0; list-style: none; }
.problem-list li {
  font-size: var(--fs-3);
  color: var(--web-text);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--web-border);
}
.problem-list li:last-child { border-bottom: 0; }
.problem-kicker { max-width: var(--max-prose); margin: var(--space-6) auto 0; font-family: var(--font-display); font-size: var(--fs-2); line-height: var(--lh-tight); text-align: center; }

/* ---------- Meet Doppel (big statement) ---------- */

.statement { max-width: 20ch; margin: 0 auto; font-family: var(--font-display); font-size: var(--fs-1); line-height: var(--lh-tight); text-align: center; }
.statement span { color: var(--web-dim); }

/* ---------- How it works (3 steps) ---------- */

.how { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
@media (max-width: 760px) { .how { grid-template-columns: 1fr; gap: var(--space-5); } }
.how-step { }
.how-step .num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; margin-bottom: var(--space-4);
  border-radius: 999px; border: 1px solid var(--web-border-strong);
  font: 700 15px/1 var(--font-mono); color: var(--web-accent);
}
.how-step h3 { margin-bottom: var(--space-3); }
.how-step p { color: var(--web-dim); margin: 0; }

/* ---------- What it does (feature cards) ---------- */

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}
@media (max-width: 900px) { .feature-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .feature-grid { grid-template-columns: 1fr; } }

.feature-card {
  background: var(--web-surface);
  border: 1px solid var(--web-border);
  border-radius: var(--radius);
  padding: var(--space-5);
  transition: transform 0.22s var(--spring), border-color 0.22s ease;
}
.feature-card:hover { transform: translateY(-3px); border-color: var(--web-border-strong); }
/* Card titles inherit the default h3 (display serif, --fs-3/600) so Features,
   How, and Trust share ONE heading treatment — was sans 16/700 here, serif
   20/600 in How, i.e. one level rendered two ways. */
.feature-card h3 { margin-bottom: var(--space-2); }
.feature-card p { color: var(--web-dim); font-size: 14px; margin: 0; }

/* ---------- Why Doppel (comparison) ---------- */

.compare { width: 100%; border-collapse: collapse; margin: 0 auto; max-width: 820px; }
.compare th, .compare td { padding: var(--space-4); text-align: left; border-bottom: 1px solid var(--web-border); vertical-align: top; }
.compare thead th { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--web-dim); }
.compare thead th:last-child { color: var(--web-accent); }
.compare tbody th { font-weight: 400; color: var(--web-dim); }
.compare tbody td { color: var(--web-text); font-weight: 600; }
.compare tbody td::before { content: '✓ '; color: var(--web-verify); }

/* ---------- Trust points ---------- */

.trust-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); max-width: 900px; margin: 0 auto; }
@media (max-width: 760px) { .trust-grid { grid-template-columns: 1fr; } }
.trust-point h3 { margin-bottom: var(--space-2); }  /* inherits the unified card-title treatment (see .feature-card h3) */
.trust-point p { color: var(--web-dim); font-size: 14px; margin: 0; }

/* ---------- reduced motion ----------
   Mirrors the app convention (§8): null the transform, keep the element
   visible and functional. Never leave content stranded at opacity 0. */

@media (prefers-reduced-motion: reduce) {
  .btn { transition: background 0.15s ease; }
  .btn-primary:hover,
  .btn-primary:active { transform: none; }
  .feature-card { transition: border-color 0.15s ease; }
  .feature-card:hover { transform: none; }
  .skip-link { transition: none; }
  .caret { animation: none; }
  .js-reveal .reveal { opacity: 1; transform: none; transition: none; }
  .ledger-row .check { transition: none; }
  .hero::before { display: none; }
}
