/* ==========================================================================
   myXpns — marketing site
   --------------------------------------------------------------------------
   The design system is the app's own "Modernist": Archivo throughout, square
   corners everywhere, flat surfaces with hairline rules instead of shadows,
   near-monochrome with a single red accent doing all the work. The palette is
   lifted verbatim from
   ledgr/app/src/main/java/com/myxpns/ui/theme/Color.kt — do not invent colours
   here; if the app's palette moves, move these to match.

   Contrast: #EC3013 is the brand accent but white on it is only 4.20:1, so
   filled buttons use Accent600 #DD2B0F (4.74:1) and small red text uses
   Accent700 #AE1800 (6.41:1). Both are from the app's own accent ramp.
   ========================================================================== */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/archivo-latin-ext.woff2') format('woff2');
  /* Carries the rupee sign, U+20B9. */
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ── tokens ─────────────────────────────────────────────────────────────── */

:root {
  --bg:          #F3F2F2;
  --surface:     #EAE9E9;
  --ink:         #201E1D;
  --ink-soft:    #605D5D;
  --ink-mute:    #7D7979;
  --accent:      #EC3013;   /* fills and rules only */
  --accent-btn:  #DD2B0F;   /* filled button ground — AA with white */
  --accent-text: #AE1800;   /* small red text */
  --on-accent:   #FFFFFF;
  --credit:      #3F7D5C;
  --line:        rgba(32, 30, 29, .16);
  --line-firm:   rgba(32, 30, 29, .34);

  /* The inverted panel. In dark mode it flips to light, the same way the
     app's balance card inverts on its dark home screen. */
  --panel:       #201E1D;
  --panel-ink:   #F3F2F2;
  --panel-soft:  #BAB6B6;
  --panel-line:  rgba(243, 242, 242, .18);
  --panel-accent:#FF8A68;

  --phone-bezel: #201E1D;
  --shell:       76rem;
  --pad:         clamp(1.25rem, 4vw, 3rem);

  /* The sticky bar's height, in one place: the bar itself, the scroll offset
     for in-page links, and the top of the mobile menu sheet all read it. */
  --nav-h:       4.5rem;

  /* Zero on a desktop browser; the notch and home-indicator insets on a phone
     once viewport-fit=cover is in play. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
}

[data-theme="dark"] {
  --bg:          #1C1A19;
  --surface:     #2D2B2B;
  --ink:         #F3F2F2;
  --ink-soft:    #BAB6B6;
  --ink-mute:    #9B9797;
  --accent:      #FF563C;
  --accent-btn:  #FF563C;
  --accent-text: #FF8A68;
  --on-accent:   #201E1D;
  --credit:      #6FBF8C;
  --line:        rgba(243, 242, 242, .16);
  --line-firm:   rgba(243, 242, 242, .34);

  --panel:       #F3F2F2;
  --panel-ink:   #201E1D;
  --panel-soft:  #605D5D;
  --panel-line:  rgba(32, 30, 29, .18);
  --panel-accent:#AE1800;

  --phone-bezel: #45403F;
}

/* ── base ───────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Archivo', 'Segoe UI', system-ui, -apple-system, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  /* Nothing on this page is wider than the viewport by design, so a sideways
     rubber-band is always an accident. */
  overflow-x: hidden;
  overscroll-behavior-x: none;
}

/* Touch targets should feel like an app's: no grey flash on tap, and a press
   state that reads as a press rather than a lingering hover. */
a, button, summary, [role="button"] {
  -webkit-tap-highlight-color: transparent;
}

/* The scroll lock the mobile menu applies. The bar goes position:fixed for the
   duration (see .nav.is-open), which takes it out of flow — the padding puts
   back exactly the height it vacated, so the page behind the sheet does not
   shift up and back as the menu opens and closes. */
html.is-locked, html.is-locked body { overflow: hidden; }
html.is-locked body { padding-top: calc(var(--nav-h) + var(--safe-t)); }

/* Every inline SVG in this page is a stroked line icon on a 24 grid, ported
   from the app's drawable set. One rule dresses all of them. */
svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.i { width: 1.15em; height: 1.15em; flex: none; }
.i--lg { width: 1.7rem; height: 1.7rem; stroke-width: 1.6; }

h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -.028em; line-height: 1.04; }
/* The lower bound of each clamp is set from the narrowest phone we support
   (320px), not from a desktop hunch — a floor that does not fit is what makes a
   page feel cramped rather than large. */
h1 { font-size: clamp(2.35rem, 9vw, 5.4rem); }
h2 { font-size: clamp(1.8rem, 6.2vw, 3.25rem); }
h3 { font-size: 1.0625rem; letter-spacing: -.012em; line-height: 1.3; }
p  { margin: 0; }

a { color: inherit; }
code, pre { font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace; }
code { font-size: .875em; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--ink); color: var(--bg);
  padding: .75rem 1.25rem; font-weight: 600; text-decoration: none;
}
.skip:focus { left: 0; }

.shell {
  width: 100%; max-width: var(--shell); margin-inline: auto;
  padding-left: calc(var(--pad) + var(--safe-l));
  padding-right: calc(var(--pad) + var(--safe-r));
}
.shell--narrow { max-width: 48rem; }

/* ── shared bits ────────────────────────────────────────────────────────── */

.kicker {
  font-size: .75rem; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--accent-text);
  margin-bottom: 1.1rem;
}

.kicker--tight { margin-bottom: .6rem; }

.lead { font-size: clamp(1.0625rem, 1.5vw, 1.2rem); color: var(--ink-soft); max-width: 34em; }

.sec-head { max-width: 44rem; margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.sec-head--center { margin-inline: auto; text-align: center; }
.sec-head__lede { margin-top: 1.1rem; color: var(--ink-soft); font-size: 1.0625rem; max-width: 36em; }
.sec-head--center .sec-head__lede { margin-inline: auto; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  padding: .8rem 1.25rem;
  min-height: 2.75rem;                 /* 44px — the smallest comfortable tap */
  font: inherit; font-weight: 600; letter-spacing: -.01em;
  text-decoration: none; border: 1px solid transparent; cursor: pointer;
  white-space: nowrap;                 /* a wrapped label is what broke the bar */
  transition: background .16s ease, color .16s ease, border-color .16s ease, transform .16s ease;
}
.btn--lg { padding: 1.05rem 1.75rem; font-size: 1.0625rem; min-height: 3.25rem; }
.btn--accent { background: var(--accent-btn); color: var(--on-accent); }
.btn--accent:hover { background: var(--ink); color: var(--bg); }
.btn--ghost { border-color: var(--line-firm); color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.btn:active { transform: scale(.985); }
.btn__arrow { width: 1.1em; height: 1.1em; transition: transform .2s ease; }
.btn:hover .btn__arrow { transform: translateX(3px); }

.link { color: var(--accent-text); text-underline-offset: 3px; }

/* Store badges. Both platforms are unreleased, so these say so on the line
   where a shipped app would say "Download on the" — and they lead to the
   early-access form rather than pretending to be store links. */
.stores { display: flex; flex-wrap: wrap; gap: .6rem; margin: 0 0 1.9rem; }
.stores--center { justify-content: center; margin: 2rem 0 0; }

.store {
  display: inline-flex; align-items: center; gap: .7rem;
  padding: .55rem 1rem .6rem .85rem;
  background: var(--ink); color: var(--bg);
  border: 1px solid var(--ink);
  text-decoration: none;
  transition: background .16s ease, color .16s ease;
}
.store:hover { background: transparent; color: var(--ink); }
/* These two are filled brand marks, not the stroked icon set the rest of the
   page uses, so they opt out of the global svg rule. */
.store__logo { width: 1.65rem; height: 1.65rem; flex: none; fill: currentColor; stroke: none; }
.store__txt { display: grid; gap: .1rem; }
.store__txt small {
  font-size: .625rem; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; opacity: .78; line-height: 1;
}
.store__txt strong { font-size: 1.0625rem; font-weight: 700; letter-spacing: -.025em; line-height: 1.1; }

.neg { color: var(--accent-text); font-weight: 600; }

/* ── nav ────────────────────────────────────────────────────────────────── */

.nav {
  position: sticky; top: 0; z-index: 40;
  padding-top: var(--safe-t);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.nav.is-stuck { border-bottom-color: var(--line); }
/* While the sheet is open the document is scroll-locked with overflow:hidden,
   which takes away the root's scrollport — and a sticky element without one
   falls back to its static position, i.e. off the top of a scrolled page. Fixed
   for the duration keeps the bar, and its close button, where they belong. */
.nav.is-open {
  position: fixed; top: 0; left: 0; right: 0;
  background: var(--bg);
}
.nav__inner { display: flex; align-items: center; gap: 1.5rem; min-height: var(--nav-h); }

.nav__brand { display: inline-flex; align-items: center; gap: .55rem; text-decoration: none; }
.nav__mark { width: 2.1rem; height: auto; }
.nav__word { font-weight: 700; font-size: 1.2rem; letter-spacing: -.03em; }
.nav__word span { color: var(--accent); }

.nav__links { display: flex; gap: 1.5rem; margin-left: auto; font-size: .9375rem; }
.nav__links a { color: var(--ink-soft); text-decoration: none; transition: color .15s ease; }
.nav__links a:hover { color: var(--ink); }

/* On a wide screen .nav__links already carries the margin-left:auto that pushes
   everything after the brand to the right, so these need no margin of their own.
   Below 900px the links are gone and the actions take that job over. */
.nav__actions { display: flex; align-items: center; gap: .6rem; }
.toggle {
  display: inline-flex; align-items: center; gap: .45rem;
  background: none; border: 1px solid var(--line); color: var(--ink-soft);
  padding: .5rem .7rem; font: inherit; font-size: .8125rem; font-weight: 500;
  cursor: pointer; transition: border-color .15s ease, color .15s ease;
}
.toggle:hover { border-color: var(--line-firm); color: var(--ink); }
.toggle__icon { display: block; width: 1rem; height: 1rem; }
.toggle svg { width: 1rem; height: 1rem; }
.toggle__moon { display: none; }
[data-theme="dark"] .toggle__sun { display: none; }
[data-theme="dark"] .toggle__moon { display: block; }

/* ── mobile menu ────────────────────────────────────────────────────────── */

/* The burger only exists below the width at which .nav__links disappears; the
   media queries at the foot of this file turn it on. */
.burger {
  display: none;
  width: 2.75rem; height: 2.75rem; flex: none;
  align-items: center; justify-content: center;
  padding: 0; background: none; border: 1px solid var(--line); color: var(--ink);
  cursor: pointer;
}
.burger__box { display: block; width: 1.15rem; height: .8rem; position: relative; }
.burger__box span {
  position: absolute; left: 0; right: 0; height: 2px; background: currentColor;
  transition: transform .22s ease, opacity .16s ease;
}
.burger__box span:nth-child(1) { top: 0; }
.burger__box span:nth-child(2) { top: 50%; margin-top: -1px; }
.burger__box span:nth-child(3) { bottom: 0; }
.nav.is-open .burger__box span:nth-child(1) { transform: translateY(.35rem) rotate(45deg); }
.nav.is-open .burger__box span:nth-child(2) { opacity: 0; }
.nav.is-open .burger__box span:nth-child(3) { transform: translateY(-.35rem) rotate(-45deg); }

/* A full-height sheet rather than a dropdown: on a phone the links should be
   the only thing on screen while the menu is open. It sits under the bar in the
   stack so the brand and the close button stay visible over it. */
.menu {
  position: fixed;
  top: calc(var(--nav-h) + var(--safe-t));
  left: 0; right: 0; bottom: 0;
  z-index: 39;
  display: flex; flex-direction: column; gap: .5rem;
  padding: 1rem calc(var(--pad) + var(--safe-l))
           calc(2rem + var(--safe-b)) calc(var(--pad) + var(--safe-r));
  background: var(--bg);
  overflow-y: auto; overscroll-behavior: contain;
  visibility: hidden; opacity: 0; transform: translateY(-.5rem);
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
}
.menu.is-open { visibility: visible; opacity: 1; transform: none; }

.menu__links { display: flex; flex-direction: column; }
.menu__links a {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.05rem 0; min-height: 3.25rem;
  font-size: 1.25rem; font-weight: 600; letter-spacing: -.02em;
  text-decoration: none; color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.menu__links a .i { color: var(--ink-mute); }
.menu__links a:active { color: var(--accent-text); }
.menu__cta { margin-top: 1.5rem; padding: 1.05rem 1.5rem; font-size: 1.0625rem; min-height: 3.25rem; }
.menu__note {
  margin-top: .9rem; text-align: center;
  font-size: .8125rem; color: var(--ink-mute);
}

/* ── hero ───────────────────────────────────────────────────────────────── */

.hero { padding: clamp(3.5rem, 8vw, 7rem) 0 clamp(4rem, 9vw, 8rem); }
.hero__grid {
  display: grid; gap: clamp(3rem, 6vw, 5rem);
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  align-items: center;
}
.hero__title { margin-bottom: 1.6rem; }
.hero__cta { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2.25rem; }

.hero__proof {
  display: flex; flex-wrap: wrap; gap: .5rem 1.75rem;
  list-style: none; margin: 2.5rem 0 0; padding: 1.5rem 0 0;
  border-top: 1px solid var(--line);
  font-size: .875rem; font-weight: 500; color: var(--ink-soft);
}
.hero__proof li { display: flex; align-items: center; gap: .5rem; }
.hero__proof li::before { content: ''; width: 5px; height: 5px; background: var(--accent); flex: none; }

/* ── hero demo: one SMS becoming one ledger row ─────────────────────────── */

.demo { margin: 0; display: grid; gap: 0; }
.demo__cap {
  display: flex; align-items: center; gap: .5rem;
  font-size: .75rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-mute); margin-bottom: .9rem;
}
.demo__pulse { width: 7px; height: 7px; background: var(--accent); flex: none; animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }

.sms, .row { background: var(--surface); border: 1px solid var(--line); padding: 1rem 1.1rem; }

.sms__head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .55rem; }
.sms__from { font-size: .8125rem; font-weight: 700; letter-spacing: .06em; }
.sms__time { font-size: .75rem; color: var(--ink-mute); }
.sms__body { font-size: .9375rem; line-height: 1.65; color: var(--ink-soft); }

.demo mark {
  background: none; color: inherit; position: relative;
  padding: 0 .08em; transition: color .3s ease, font-weight .3s ease;
}
.demo mark::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform .38s cubic-bezier(.2, .7, .3, 1);
}
.demo mark.lit { color: var(--ink); font-weight: 700; }
.demo mark.lit::after { transform: scaleX(1); }
.demo mark[data-token="ignored"].struck { color: var(--ink-mute); text-decoration: line-through; }
.demo mark[data-token="ignored"].struck::after { background: var(--ink-mute); transform: scaleX(1); }

.sms__note, .demo__done {
  display: flex; align-items: flex-start; gap: .5rem;
  font-size: .8125rem; line-height: 1.5; color: var(--ink-mute);
  margin-top: .8rem; opacity: 0; transform: translateY(3px);
  transition: opacity .35s ease, transform .35s ease;
}
.sms__note .i, .demo__done .i { margin-top: .18em; }
.sms__note.on, .demo__done.on { opacity: 1; transform: none; }
.demo__done { color: var(--credit); font-weight: 500; padding: 0 .1rem; }

.demo__link { height: 2.25rem; display: flex; justify-content: center; }
.demo__link span { width: 1px; background: var(--line-firm); position: relative; }
.demo__link span::after {
  content: ''; position: absolute; left: -3px; bottom: 0;
  border-left: 3.5px solid transparent; border-right: 3.5px solid transparent;
  border-top: 5px solid var(--line-firm);
}

.row { display: flex; align-items: center; gap: .85rem; border-left: 3px solid var(--line); transition: border-color .35s ease; }
.row.lit { border-left-color: var(--accent); }
.row__badge {
  width: 2.4rem; height: 2.4rem; flex: none;
  display: grid; place-items: center;
  background: var(--bg); border: 1px solid var(--line);
  font-size: .8125rem; font-weight: 700;
}
.row__main { min-width: 0; flex: 1; }
.row__title { font-weight: 700; letter-spacing: -.01em; }
.row__meta { display: flex; flex-wrap: wrap; gap: .3rem .5rem; font-size: .8125rem; color: var(--ink-mute); }
.row__meta span:not(:last-child)::after { content: ' ·'; }
.row__amt { font-weight: 700; font-size: 1.0625rem; white-space: nowrap; }

.demo [data-field] { transition: opacity .4s ease, transform .4s ease; }
.js .demo [data-field] { opacity: .14; transform: translateY(3px); }
.js .demo [data-field].on { opacity: 1; transform: none; }

/* ── privacy band ───────────────────────────────────────────────────────── */

.band {
  background: var(--panel); color: var(--panel-ink);
  padding: clamp(4rem, 9vw, 7.5rem) 0;
}
.band .kicker { color: var(--panel-accent); }
.band__claim { max-width: 18ch; margin-bottom: clamp(2.5rem, 5vw, 3.75rem); }

.band__grid {
  display: grid; gap: clamp(2rem, 4vw, 3.5rem);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  padding-bottom: clamp(3rem, 6vw, 5rem);
  border-bottom: 1px solid var(--panel-line);
}
.band__lede { display: grid; gap: 1.1rem; font-size: 1.0625rem; color: var(--panel-soft); max-width: 38em; }
.band__lede code { color: var(--panel-ink); }
.band .link { color: var(--panel-accent); }

/* What the app uses, in plain words — the same boxed look the band always had,
   without asking anyone to read code. */
.asks { border: 1px solid var(--panel-line); }
.asks__cap {
  font-size: .6875rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--panel-soft); padding: .75rem 1.1rem; border-bottom: 1px solid var(--panel-line);
}
.asks ul { list-style: none; margin: 0; padding: 0; }
.asks li { display: grid; gap: .2rem; padding: .9rem 1.1rem; }
.asks li + li { border-top: 1px solid var(--panel-line); }
.asks strong { font-weight: 600; color: var(--panel-ink); }
.asks span { font-size: .9375rem; color: var(--panel-soft); }

.pillars {
  list-style: none; margin: clamp(3rem, 6vw, 4.5rem) 0 0; padding: 0;
  display: grid; gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.pillars li { display: grid; gap: .7rem; align-content: start; }
.pillars .i--lg { color: var(--panel-accent); }
.pillars p { font-size: .9375rem; color: var(--panel-soft); }
.pillars code { color: var(--panel-ink); }

/* ── tour ───────────────────────────────────────────────────────────────── */

.tour { padding: clamp(4rem, 9vw, 7rem) 0; border-bottom: 1px solid var(--line); }

.phone { width: 100%; max-width: 340px; margin-inline: auto; }
.phone__bezel { background: var(--phone-bezel); padding: 9px; }
.phone__screen { position: relative; background: #F3F2F2; }
.js .phone__screen { aspect-ratio: 1080 / 2400; overflow: hidden; }
.phone__screen img { display: block; width: 100%; height: auto; }
.js .phone__screen img {
  position: absolute; inset: 0; height: 100%;
  object-fit: cover; object-position: top center;
  opacity: 0; transition: opacity .3s ease;
}
.js .phone__screen img.is-active { opacity: 1; }

.tour__dots { display: flex; gap: .4rem; justify-content: center; list-style: none; margin: .75rem 0 0; padding: 0; }
.tour__dots:empty { display: none; }
/* The bar people see is 4px tall; the button around it is 32px, so it can be
   hit with a thumb. background-clip keeps the paint on the content box. */
.tour__dots button {
  display: block; width: 1.6rem; height: 2rem;
  padding: 14px 0; border: 0; cursor: pointer;
  background: var(--line-firm); background-clip: content-box;
  transition: background-color .2s ease;
}
.tour__dots button:hover { background-color: var(--ink-mute); }
.tour__dots li.is-on button { background-color: var(--accent); }

.tour__steps { list-style: none; margin: 0; padding: 0; }
.step { display: grid; gap: .85rem; align-content: center; padding: 2.5rem 0; }
.step__n {
  font-size: .75rem; font-weight: 700; letter-spacing: .14em; color: var(--ink-mute);
  border-top: 1px solid var(--line-firm); padding-top: .6rem; width: 2.6rem;
  transition: color .3s ease, border-color .3s ease;
}
.step h3 { font-size: clamp(1.35rem, 2.4vw, 1.75rem); }
.step p { color: var(--ink-soft); max-width: 34em; }
.js .step { opacity: .38; transition: opacity .35s ease; }
.js .step.is-on { opacity: 1; }
.js .step.is-on .step__n { color: var(--accent-text); border-color: var(--accent); }

/* ── capture flow ───────────────────────────────────────────────────────── */

.capture { padding: clamp(4rem, 9vw, 7rem) 0; border-bottom: 1px solid var(--line); }

.flow { max-width: 46rem; margin-inline: auto; }
.flow__sources { display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }

.node { border: 1px solid var(--line-firm); padding: 1.15rem 1.25rem; background: var(--bg); }
.node strong { display: block; font-size: 1.0625rem; letter-spacing: -.015em; margin-bottom: .45rem; }
.node p { font-size: .9375rem; color: var(--ink-soft); }
.node__tag {
  display: inline-block; font-size: .6875rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-mute);
  margin-bottom: .6rem;
}
.node__tag--hard { color: var(--accent-text); }
.node--gate { background: var(--surface); border-color: var(--ink); border-width: 2px; }
.node--out { border-color: var(--ink); border-left-width: 3px; }

.flow__join, .flow__arrow { height: 2.5rem; position: relative; }
.flow__join::before, .flow__arrow::before {
  content: ''; position: absolute; left: 50%; top: 0; bottom: 6px;
  width: 1px; background: var(--line-firm);
}
.flow__join::after, .flow__arrow::after {
  content: ''; position: absolute; left: 50%; bottom: 0; translate: -50% 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 6px solid var(--line-firm);
}

.reject { list-style: none; margin: .35rem 0 0; padding: 0; display: grid; gap: .5rem; }
.reject li {
  display: flex; align-items: flex-start; gap: .6rem;
  font-size: .9375rem; color: var(--ink-soft);
}
.reject li::before {
  content: '×'; color: var(--accent-text); font-weight: 700;
  line-height: 1.4; flex: none;
}

.parse { display: grid; gap: 1px; background: var(--line-firm); border: 1px solid var(--line-firm); margin-top: .35rem; }
.parse > div { background: var(--bg); padding: .85rem 1rem; display: grid; gap: .3rem; }
.parse span { font-weight: 600; font-size: .9375rem; }
.parse em { font-style: normal; font-size: .875rem; color: var(--ink-soft); }
.parse__yes span::before { content: '✓ '; color: var(--credit); }
.parse__no span::before { content: '× '; color: var(--accent-text); }

/* ── features ───────────────────────────────────────────────────────────── */

.features { padding: clamp(4rem, 9vw, 7rem) 0; border-bottom: 1px solid var(--line); }
.grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px; background: var(--line);
  border: 1px solid var(--line);
}
.grid li { background: var(--bg); padding: 1.6rem 1.4rem; display: grid; gap: .55rem; align-content: start; }
.grid p { font-size: .9375rem; color: var(--ink-soft); }

/* ── night ──────────────────────────────────────────────────────────────── */

.night { padding: clamp(4rem, 9vw, 7rem) 0; border-bottom: 1px solid var(--line); }
.night__row { display: flex; justify-content: center; gap: clamp(1rem, 3vw, 2.5rem); flex-wrap: wrap; }
.phone--sm { max-width: 240px; }

/* ── faq ────────────────────────────────────────────────────────────────── */

.faq { padding: clamp(4rem, 9vw, 7rem) 0; border-bottom: 1px solid var(--line); }
.faq details { border-top: 1px solid var(--line); }
.faq details:last-of-type { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: center; gap: 1rem;
  padding: 1.25rem 0; cursor: pointer; list-style: none;
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ''; margin-left: auto; flex: none;
  width: .65rem; height: .65rem;
  border-right: 2px solid var(--ink-mute); border-bottom: 2px solid var(--ink-mute);
  rotate: 45deg; translate: 0 -25%;
  transition: rotate .2s ease, border-color .2s ease;
}
.faq details[open] summary::after { rotate: -135deg; translate: 0 15%; border-color: var(--accent); }
.faq summary:hover { color: var(--accent-text); }
.faq__body { padding: 0 0 1.4rem; display: grid; gap: .9rem; color: var(--ink-soft); max-width: 42em; }

/* ── closing ────────────────────────────────────────────────────────────── */

.end { padding: clamp(4.5rem, 10vw, 8rem) 0; text-align: center; }
.end h2 { margin-bottom: 1.35rem; }
.end > .shell > p { color: var(--ink-soft); max-width: 34em; margin-inline: auto; font-size: 1.0625rem; }
.end .btn { margin-top: 2.25rem; }

.foot { border-top: 1px solid var(--line); padding: 3rem 0 3.5rem; }
.foot__inner { display: grid; gap: .4rem; justify-items: start; margin-top: 2rem; }
.foot__note { font-size: .875rem; color: var(--ink-mute); }
.foot__note--dim { font-size: .8125rem; }

/* The brand plate, carried over from the banner artwork in brand/. */
.plate {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: clamp(1.5rem, 5vw, 4rem);
  border-top: 3px solid var(--accent);
  padding-top: 2rem;
}
.plate__brand { display: inline-flex; align-items: center; gap: .8rem; text-decoration: none; }
.plate__brand img { width: clamp(3rem, 6vw, 4.25rem); height: auto; }
.plate__word {
  font-size: clamp(2rem, 5vw, 3rem); font-weight: 700; letter-spacing: -.04em; line-height: 1;
}
.plate__word span { color: var(--accent); }
.plate__say {
  border-left: 1px solid var(--line-firm);
  padding-left: clamp(1.25rem, 3vw, 2.25rem);
  max-width: 30rem;
}
.plate__say .kicker { margin-bottom: .5rem; }
.plate__say p:last-child { font-size: clamp(1.0625rem, 1.6vw, 1.25rem); color: var(--ink-soft); }

/* ── privacy policy (privacy/index.html) ────────────────────────────────── */

/* Built from the landing page's own parts — the hero type, the inverted band,
   flow nodes, the hairline grid — so the policy reads as the same product
   rather than a legal document bolted onto it. */

.policy-hero { padding: clamp(2.5rem, 7vw, 5.5rem) 0 clamp(3rem, 7vw, 5rem); }
.policy-hero h1 { font-size: clamp(2.35rem, 8vw, 4.75rem); max-width: 13ch; margin-bottom: 1.6rem; }

.policy-meta {
  list-style: none; margin: clamp(2rem, 5vw, 3rem) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
}
.policy-meta li { background: var(--bg); padding: 1rem 1.2rem; display: grid; gap: .3rem; align-content: start; }
.policy-meta small {
  font-size: .6875rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-mute);
}
.policy-meta strong { font-weight: 600; letter-spacing: -.01em; }

.policy { padding: clamp(4rem, 9vw, 7rem) 0; border-bottom: 1px solid var(--line); }
.policy__layout {
  display: grid; grid-template-columns: 14rem minmax(0, 1fr);
  gap: clamp(3rem, 6vw, 6rem); align-items: start;
}

/* Contents: a sticky rail on a wide screen; main.js marks the section in view. */
.toc { position: sticky; top: calc(var(--nav-h) + 2rem); }
.toc ol { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--line); }
.toc a {
  display: flex; gap: .7rem; margin-left: -1px;
  padding: .45rem 0 .45rem 1rem; border-left: 2px solid transparent;
  font-size: .9063rem; line-height: 1.35; color: var(--ink-soft); text-decoration: none;
  transition: color .15s ease, border-color .15s ease;
}
.toc a span { flex: none; min-width: 1.35rem; padding-top: .12em; font-size: .6875rem; font-weight: 700; letter-spacing: .08em; color: var(--ink-mute); }
.toc a:hover { color: var(--ink); }
.toc a.is-on { color: var(--ink); font-weight: 600; border-left-color: var(--accent); }
.toc a.is-on span { color: var(--accent-text); }

.clauses { max-width: 48rem; min-width: 0; }
.clause { padding-bottom: clamp(3rem, 6vw, 4.5rem); }
.clause + .clause { padding-top: clamp(3rem, 6vw, 4.5rem); border-top: 1px solid var(--line); }
.clause__n {
  display: block; width: 2.6rem; padding-top: .6rem;
  border-top: 2px solid var(--accent);
  font-size: .75rem; font-weight: 700; letter-spacing: .14em; color: var(--accent-text);
}
.clause h2 { font-size: clamp(1.7rem, 5vw, 2.6rem); margin: 1rem 0 1.2rem; }
.clause > p { color: var(--ink-soft); font-size: 1.0625rem; max-width: 38em; }
.clause > * + p { margin-top: 1rem; }
.clause strong { color: var(--ink); font-weight: 600; }
.clause code { overflow-wrap: anywhere; }

.clause .grid { margin-top: 1.75rem; }
.clause .grid .i--lg { color: var(--accent-text); margin-bottom: .35rem; }
.grid--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--trio { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid__wide { grid-column: 1 / -1; }

.ways { counter-reset: way; }
.ways li { counter-increment: way; }
.ways li::before {
  content: counter(way, decimal-leading-zero);
  font-size: .75rem; font-weight: 700; letter-spacing: .14em; color: var(--ink-mute);
}

.stack { display: grid; gap: 1rem; margin: 1.75rem 0; }
.stack + p { margin-top: 0; }
.stack .parse { margin-top: 0; }
.node--gate .node__tag { margin-bottom: .8rem; }
/* .node strong is the card's title block; emphasis inside its text stays inline. */
.node p strong { display: inline; margin: 0; font-size: inherit; }
.node--status { margin-top: .25rem; background: var(--surface); border-left: 3px solid var(--accent); }

.accept { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
/* Positioned rather than flexed: a flex item would tear inline <code> out of
   the sentence and stand it in a column of its own. */
.accept li { position: relative; padding-left: 1.4rem; font-size: .9375rem; color: var(--ink-soft); }
.accept li::before { content: '✓'; position: absolute; left: 0; top: 0; color: var(--credit); font-weight: 700; }

.callout {
  margin-top: 1.75rem; padding: 1.1rem 1.25rem;
  background: var(--panel); color: var(--panel-ink) !important;
  font-weight: 600; letter-spacing: -.01em;
  border-left: 3px solid var(--accent);
}

.clause__aside { margin-top: 1.75rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.clause__aside .reject { margin-top: 0; }

.clause__big {
  font-size: clamp(1.35rem, 3.6vw, 1.85rem) !important; font-weight: 700;
  letter-spacing: -.022em; line-height: 1.2; color: var(--ink) !important;
}

.clause--contact { padding-bottom: 0; }
.contact { margin-top: 1.5rem !important; font-size: clamp(1.2rem, 4.6vw, 2rem) !important; font-weight: 700; letter-spacing: -.02em; overflow-wrap: anywhere; }

@media (max-width: 1024px) {
  .policy__layout { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }

  /* The rail becomes a strip of chips that scrolls sideways inside itself. */
  .toc { position: static; }
  .toc ol {
    display: flex; gap: .5rem; border-left: 0;
    margin-left: calc(-1 * (var(--pad) + var(--safe-l)));
    margin-right: calc(-1 * (var(--pad) + var(--safe-r)));
    padding: 0 calc(var(--pad) + var(--safe-r)) .25rem calc(var(--pad) + var(--safe-l));
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  }
  .toc ol::-webkit-scrollbar { display: none; }
  .toc a {
    margin: 0; padding: .55rem .85rem; min-height: 2.75rem; align-items: center;
    white-space: nowrap; border: 1px solid var(--line);
  }
  .toc a span { padding-top: 0; }
  .toc a.is-on { border-color: var(--ink); }
}

@media (max-width: 900px) {
  .grid--trio { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 620px) {
  .policy-meta, .grid--pair { grid-template-columns: minmax(0, 1fr); }
}

@media print {
  .toc { display: none; }
  .policy__layout { grid-template-columns: minmax(0, 1fr); }
}

/* ── phone action dock ──────────────────────────────────────────────────── */

/* Hidden outright above the phone breakpoint, so it never enters the tab order
   on a desktop. Below it, visibility (not display) does the hiding, which keeps
   it out of the tab order while it is down but still lets it animate. */
.dock { display: none; }

@media (max-width: 620px) {
  .dock {
    display: block;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 38;
    padding: .7rem calc(var(--pad) + var(--safe-l))
             calc(.7rem + var(--safe-b)) calc(var(--pad) + var(--safe-r));
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: saturate(140%) blur(12px);
    -webkit-backdrop-filter: saturate(140%) blur(12px);
    border-top: 1px solid var(--line);
    visibility: hidden; opacity: 0; transform: translateY(100%);
    transition: opacity .25s ease, transform .25s ease, visibility .25s;
  }
  .dock.is-up { visibility: visible; opacity: 1; transform: none; }
  .dock .btn { width: 100%; }

  /* The dock floats over the page, so the last thing on it needs room to clear. */
  .foot { padding-bottom: calc(6rem + var(--safe-b)); }

  /* Two fixed bars at once is one too many. */
  .nav.is-open ~ .dock, .dock.is-hidden { visibility: hidden; opacity: 0; transform: translateY(100%); }
}

/* ── scroll reveal ──────────────────────────────────────────────────────── */

.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s ease, transform .6s ease; }
.js .reveal.is-in { opacity: 1; transform: none; }

/* ── layout: sticky tour, wide ──────────────────────────────────────────── */

@media (min-width: 901px) {
  .tour__layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 360px);
    gap: clamp(3rem, 6vw, 6rem);
    align-items: start;
  }
  .tour__stage { grid-column: 2; grid-row: 1; position: sticky; top: 7rem; }
  .tour__steps { grid-column: 1; grid-row: 1; }
  .step { min-height: 58vh; }
  .step:first-child { padding-top: 0; }
  .step:last-child { padding-bottom: 0; }
}

/* ── layout: narrow ─────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .nav__links { display: none; }
  /* With the links hidden, this is what holds the theme and menu buttons
     against the right edge. */
  .nav__actions { margin-left: auto; }
  .burger { display: inline-flex; }
  .hero__grid { grid-template-columns: minmax(0, 1fr); }
  .hero__demo { max-width: 30rem; }
  .band__grid { grid-template-columns: minmax(0, 1fr); }
  .pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* The tour, restaged.
     Pinning a 178px phone to the top of a phone screen gave an illegible
     screenshot and a column of text fighting it for the same 400px. Below this
     width the phone sits still at a size you can actually read and the eight
     steps become a swipeable deck underneath it — the dots are its pagination,
     and swiping changes the screen above. */
  .tour__stage { position: static; padding: 0; background: none; }
  .phone { max-width: min(62vw, 260px); }
  .step { min-height: auto; padding: 1.75rem 0 0; }
  .js .step { opacity: 1; }

  .js .tour__steps {
    display: flex; align-items: start; gap: 1rem;
    margin-left: calc(-1 * (var(--pad) + var(--safe-l)));
    margin-right: calc(-1 * (var(--pad) + var(--safe-r)));
    padding-left: calc(var(--pad) + var(--safe-l));
    padding-right: calc(var(--pad) + var(--safe-r));
    padding-bottom: .5rem;
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-left: calc(var(--pad) + var(--safe-l));
    scrollbar-width: none;
    /* The height is set from the card on show; see fit() in main.js. */
    transition: height .25s ease;
  }
  .js .tour__steps::-webkit-scrollbar { display: none; }
  /* Short of full width on purpose: the sliver of the next card is what tells
     someone there is something to swipe to. */
  .js .tour__steps .step { flex: 0 0 88%; scroll-snap-align: start; }
  /* The trailing 12% is what lets the eighth card reach the left edge. Without
     it the container runs out of scroll before the last snap point, and
     mandatory snapping bounces back to the seventh — the last screen would be
     unreachable. */
  .js .tour__steps::after { content: ''; flex: 0 0 12%; }
}

@media (max-width: 620px) {
  :root { --nav-h: 3.5rem; }

  .flow__sources { grid-template-columns: minmax(0, 1fr); }
  .pillars { grid-template-columns: minmax(0, 1fr); }
  .grid { grid-template-columns: minmax(0, 1fr); }

  /* The bar carries the brand, the theme and the menu, and nothing else: the
     early-access button lives in the sheet and in the dock at the foot. */
  .nav__cta { display: none; }
  .nav__inner { gap: .75rem; }
  .toggle {
    width: 2.75rem; height: 2.75rem; padding: 0;
    justify-content: center; gap: 0;
  }
  /* The button keeps an aria-label, so the visible word is free to go. */
  .toggle__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

  .hero { padding-top: clamp(1.75rem, 6vw, 3rem); }

  /* Buttons and badges go full width so their edges line up with the text
     above them instead of ending wherever their labels happen to stop. */
  .hero__cta { display: grid; grid-template-columns: minmax(0, 1fr); gap: .6rem; margin-top: 1.9rem; }
  .stores { display: grid; grid-template-columns: minmax(0, 1fr); gap: .5rem; }
  .stores--center { max-width: 22rem; margin-inline: auto; }
  .store { justify-content: center; }

  .hero__proof { display: grid; grid-template-columns: minmax(0, 1fr); gap: .55rem; margin-top: 2rem; }

  /* Three phones shrunk into one row were 150px wide each. A snap rail shows
     them at a size worth showing — and brings back the third. */
  .night__row {
    justify-content: flex-start; flex-wrap: nowrap;
    gap: 1rem;
    margin-left: calc(-1 * (var(--pad) + var(--safe-l)));
    margin-right: calc(-1 * (var(--pad) + var(--safe-r)));
    padding-left: calc(var(--pad) + var(--safe-l));
    padding-right: calc(var(--pad) + var(--safe-r));
    padding-bottom: .5rem;
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
  .night__row::-webkit-scrollbar { display: none; }
  .night__row .phone--sm { flex: none; width: 62vw; max-width: 240px; scroll-snap-align: center; }

  .faq summary { padding: 1.1rem 0; min-height: 3.25rem; }
  .faq summary:hover { color: inherit; }
  .faq summary:active { color: var(--accent-text); }

  .plate__say { border-left: 0; padding-left: 0; }
  .end .btn { width: 100%; }
}

/* ── motion ─────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .js .step { opacity: 1; }
  .js .demo [data-field] { opacity: 1; transform: none; }
  .demo mark::after { transform: scaleX(1); }
  .sms__note, .demo__done { opacity: 1; transform: none; }
}

@media print {
  .nav, .tour__dots, .skip { display: none; }
  .js .phone__screen img { position: static; opacity: 1; }
}
