/* ==========================================================================
   Minturn Money — marketing site
   --------------------------------------------------------------------------
   The palette, the two type families and the primitives come from the design
   boards in docs/design/ by way of docs/assets/tuck-docs.css. What is added
   here is everything a marketing page needs that documentation does not:
   a hero, alternating section grounds, product mockups, pricing, an
   accordion.

   Font paths are relative to this file. Keep them that way — dist/ is served
   from its own root and from file:// alike.
   ========================================================================== */

/* ------------------------------------------------------------------ fonts */

/* Display. The chamfered M was drawn to match the logo apex, which is why the
   wordmark is set in it rather than in the body face. */
@font-face {
  font-family: 'Minturn Slab';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/minturn-slab/MinturnSlab-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Minturn Slab';
  font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/minturn-slab/MinturnSlab-SemiBold.woff2') format('woff2');
}

/* Body. Self-hosted so the page makes no third-party request and renders the
   same on every platform — a system stack would shift the whole layout
   between macOS and Windows. Latin subset only. */
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/inter/Inter-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/inter/Inter-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/inter/Inter-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

/* ----------------------------------------------------------------- tokens */

/* Three of these tokens each used to do two jobs, and a token doing two jobs
   settles on a value that serves neither. The page read as one flat sheet
   because of it — `--paper` against `--panel` measured 1.04:1, so the
   "alternating" section grounds did not visibly alternate, and the icon tiles
   at 1.08:1 were very nearly invisible. The splits:

     --band  vs --panel      a section's full-width ground, vs a recess inside
                             a card. The first sits on --paper and must be seen
                             across a whole screen; the second sits on --surface
                             and must stay quiet. One value cannot do both.
     --tint  vs --spruce-lo  marketing chrome (step numbers, feature icons,
                             avatars) vs anything depicting the app. Only --tint
                             is free to move: --spruce-lo is a fidelity claim,
                             so it keeps the app's pale mint. Never restyle an
                             app-representing surface to suit the marketing page.
     --alpenglow-tx          the warm accent is 4.03:1 on paper — fine as a
                             graphic fill, fails AA as 0.7rem eyebrow text.
                             The -tx variant is the one text may use.

   Every ratio in the comments below is measured, not estimated. */
:root {
  --paper:     #F4F6F4;
  --surface:   #FFFFFF;
  --panel:     #E8EFEA;   /* recess inside a card — 1.17:1 on --surface */
  --band:      #DBE6DF;   /* section ground        — 1.18:1 on --paper   */
  --tx:        #16211C;
  /* Darkened from #5C6B63. Deepening --band cost the old value its AA margin
     against it (4.39:1); this clears on every ground the site actually uses —
     5.90 on --paper, 5.00 on --band, 4.64 on --tint. */
  --tx-mut:    #556259;
  --line:      #CFDBD3;   /* 1.31:1 on --paper, 1.15:1 on --band         */
  --spruce:    #0F6B4E;
  --spruce-lo: #E4F0EA;   /* app fidelity — do not tune for the marketing page */
  --tint:      #C8E0D2;   /* marketing chrome      — 1.29:1 on --paper   */
  /* Foreground for anything filled with --spruce. Light-mode spruce is dark
     enough to carry white; dark-mode spruce (#40C08F) is not, and white on it
     measures 2.29:1. Three rules used to hand-roll this for .btn-primary alone,
     which is why .skip and .tier-flag were left failing. */
  --on-spruce: #FFFFFF;
  --alpenglow: #C25A32;   /* fills and graphics only */
  --alpenglow-tx: #9E4522;/* text — 5.81:1 on --paper, 4.93:1 on --band  */
  --topo:      rgba(15, 107, 78, 0.16);

  /* Always-dark bands (privacy, closing CTA). Fixed in both themes: these
     sections are dark *by design*, not dark because the theme is. */
  --ink:       #0C1310;
  --ink-2:     #14201B;
  --on-ink:    #ECF3EE;
  --on-ink-mut:#9DB3A7;

  --f-disp: 'Minturn Slab', Georgia, 'Times New Roman', serif;
  --f-body: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;

  --r-sm: 6px;
  --r:    10px;
  --r-lg: 16px;
  /* Lifted from .05/.04. At the old opacities a card did not sit above the
     page so much as lie flat on it, which added to the washed-out read. */
  --shadow-sm: 0 1px 2px rgba(12, 19, 16, .07), 0 2px 8px rgba(12, 19, 16, .06);
  --shadow:    0 2px 6px rgba(12, 19, 16, .09), 0 12px 32px rgba(12, 19, 16, .11);
  --shadow-lg: 0 6px 16px rgba(12, 19, 16, .11), 0 28px 64px rgba(12, 19, 16, .17);

  --nav-h: 64px;
  --pad:   24px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --paper:     #0E1512;
    --surface:   #151E1A;
    --panel:     #1E2A24;
    --band:      #1B2621;
    --tx:        #E8EFEA;
    --tx-mut:    #93A69C;
    --line:      #26332C;
    --spruce:    #40C08F;
    --spruce-lo: #14261F;
    --tint:      #193A2C;
    --on-spruce: #06120D;
    --alpenglow: #E8845A;
    --alpenglow-tx: #E8845A;  /* 6.9:1 on --paper here; no darker variant needed */
    --topo:      rgba(64, 192, 143, 0.16);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.3);
    --shadow:    0 2px 6px rgba(0,0,0,.35), 0 12px 32px rgba(0,0,0,.30);
    --shadow-lg: 0 4px 12px rgba(0,0,0,.4), 0 28px 64px rgba(0,0,0,.42);
  }
}
:root[data-theme='dark'] {
  --paper:     #0E1512;
  --surface:   #151E1A;
  --panel:     #1E2A24;
  --band:      #1B2621;
  --tx:        #E8EFEA;
  --tx-mut:    #93A69C;
  --line:      #26332C;
  --spruce:    #40C08F;
  --spruce-lo: #14261F;
  --tint:      #193A2C;
  --on-spruce: #06120D;
  --alpenglow: #E8845A;
  --alpenglow-tx: #E8845A;  /* 6.9:1 on --paper here; no darker variant needed */
  --topo:      rgba(64, 192, 143, 0.16);
  --shadow-sm: 0 1px 2px rgba(0,0,0,.3);
  --shadow:    0 2px 6px rgba(0,0,0,.35), 0 12px 32px rgba(0,0,0,.30);
  --shadow-lg: 0 4px 12px rgba(0,0,0,.4), 0 28px 64px rgba(0,0,0,.42);
}

/* ------------------------------------------------------------------- base */

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

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--nav-h) + 16px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--tx);
  font-family: var(--f-body);
  font-size: 17px;
  line-height: 1.65;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;          /* belt and braces; nothing should overflow */
}

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

a { color: var(--spruce); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-color: color-mix(in oklab, var(--spruce) 50%, transparent); }

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--spruce); color: var(--on-spruce); padding: 12px 18px;
  border-radius: 0 0 var(--r-sm) 0; font-weight: 600;
}
.skip:focus { left: 0; }

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 var(--pad); }
.wrap-narrow { max-width: 780px; margin: 0 auto; padding: 0 var(--pad); }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------------- typography */

h1, h2, h3, h4 {
  font-family: var(--f-disp);
  font-weight: 400;
  letter-spacing: -0.018em;
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: clamp(2.6rem, 6.2vw, 4.4rem); }
h2 { font-size: clamp(2rem, 4.2vw, 3rem); line-height: 1.12; }
h3 { font-size: clamp(1.25rem, 2vw, 1.5rem); line-height: 1.25; }
h4 { font-size: 1.08rem; font-weight: 600; line-height: 1.35; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: clamp(1.06rem, 1.5vw, 1.22rem);
  line-height: 1.6;
  color: var(--tx-mut);
  max-width: 58ch;
}
.lede strong { color: var(--tx); font-weight: 600; }

/* The site's one warm note. --alpenglow had only ever meant "over budget" —
   it appears in bar segments, negative figures and .callout.warn — so the whole
   page spoke in a single hue. Promoting it here gives the green something to
   play against, and the eyebrow is the right carrier: high frequency, low
   weight, and always page chrome. The rule that keeps the semantics clean is
   that the warm accent stays OUT of anything depicting the app, where it still
   means overspent and nothing else. */
.eyebrow {
  font-family: var(--f-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--alpenglow-tx);
  margin: 0 0 14px;
  font-weight: 600;
}

.dim { color: var(--tx-mut); }
.amt { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font: inherit; font-weight: 600; font-size: 0.97rem;
  padding: 13px 22px;
  border-radius: var(--r);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 140ms ease, background-color 140ms ease,
              border-color 140ms ease, box-shadow 140ms ease;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary {
  background: var(--spruce);
  color: var(--on-spruce);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover {
  background: color-mix(in oklab, var(--spruce) 88%, #000);
  box-shadow: var(--shadow);
}

.btn-ghost {
  background: var(--surface);
  color: var(--tx);
  border-color: var(--line);
}
.btn-ghost:hover { border-color: color-mix(in oklab, var(--spruce) 45%, var(--line)); }

/* Sits on a photograph, so it cannot inherit a themed foreground — #fff and a
   blur are the only things that hold contrast over an unknown pixel. */
/* Now that the ridge is actually lit rather than crushed to black, this button
   has real detail behind it instead of flat ink, so the fill and border both
   come up to hold the label off the photograph. */
.btn-on-ink {
  background: rgba(255,255,255,.20);
  color: #fff;
  border-color: rgba(255,255,255,.62);
  text-shadow: 0 1px 3px rgba(12,19,16,.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.btn-on-ink:hover { background: rgba(255,255,255,.30); border-color: rgba(255,255,255,.8); }

.btn-lg { padding: 16px 28px; font-size: 1.03rem; }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

.textlink {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 600; text-decoration: none; font-size: 0.97rem;
}
.textlink .arw { transition: transform 160ms ease; }
.textlink:hover .arw { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .btn, .btn:hover, .textlink .arw, .textlink:hover .arw { transition: none; transform: none; }
}

/* -------------------------------------------------------------------- nav */

.nav {
  position: sticky; top: 0; z-index: 100;
  height: var(--nav-h);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 180ms ease, background-color 180ms ease;
}
.nav.scrolled { border-bottom-color: var(--line); }
.nav .wrap { display: flex; align-items: center; gap: 22px; height: 100%; }

.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--tx); }
.brand .mark { width: 30px; height: 30px; color: var(--spruce); flex: none; }
.brand .word {
  font-family: var(--f-disp); font-size: 1.24rem; font-weight: 600;
  letter-spacing: -0.02em; line-height: 1;
  white-space: nowrap;      /* "Minturn / Money" over two lines is not the logo */
}
.brand .word .m2 { color: var(--tx-mut); font-weight: 400; }

.nav-links { display: none; align-items: center; gap: 4px; margin-left: 6px; }
.nav-links a {
  color: var(--tx-mut); text-decoration: none; font-size: 0.94rem; font-weight: 500;
  padding: 8px 12px; border-radius: var(--r-sm);
  transition: color 140ms ease, background-color 140ms ease;
}
.nav-links a:hover { color: var(--tx); background: var(--panel); }
.nav-links a[aria-current='page'] { color: var(--spruce); }

.nav-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.icon-btn {
  width: 38px; height: 38px; display: grid; place-items: center;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-sm);
  color: var(--tx-mut); cursor: pointer; padding: 0;
}
.icon-btn:hover { background: var(--panel); color: var(--tx); }
.icon-btn svg { width: 18px; height: 18px; }

.nav-toggle { display: grid; }

/* Narrow phones: the wordmark must not wrap, so everything else gives ground
   first — the CTA loses padding and the theme toggle steps aside (it is still
   reachable, and the OS preference is honoured regardless). */
@media (max-width: 460px) {
  :root { --pad: 18px; }
  .brand .mark { width: 26px; height: 26px; }
  .brand .word { font-size: 1.08rem; }
  .nav .wrap { gap: 10px; }
  .nav-right { gap: 2px; }
  .nav-right .btn { padding: 10px 13px; font-size: 0.88rem; }
  .nav-right .js-theme { display: none; }   /* relocated into the drawer */
}
.drawer-theme { width: 100%; margin-top: 10px; }
.drawer-theme svg { width: 17px; height: 17px; }
@media (min-width: 461px) { .drawer-theme { display: none; } }

@media (min-width: 900px) {
  .nav-links { display: flex; }
  .nav-toggle { display: none; }
}

/* Mobile drawer */
.drawer {
  position: fixed; inset: var(--nav-h) 0 0; z-index: 99;
  background: var(--paper);
  padding: 18px var(--pad) 40px;
  overflow-y: auto;
  display: none;
}
.drawer.open { display: block; }
.drawer a {
  display: block; padding: 15px 4px; font-size: 1.14rem; font-weight: 500;
  color: var(--tx); text-decoration: none; border-bottom: 1px solid var(--line);
}
.drawer .btn { width: 100%; margin-top: 18px; }
@media (min-width: 900px) { .drawer, .drawer.open { display: none; } }

/* ----------------------------------------------------------------- topo */

/* The recurring texture. Contour lines, drawn once as an SVG data layer and
   reused; it is decorative and always aria-hidden. */
.topo-field {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none;
  color: var(--topo);
  mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
}
.topo-field svg { position: absolute; inset: 0; width: 100%; height: 100%; }

/* --------------------------------------------------------------- sections */

section { position: relative; }

.band       { padding: clamp(64px, 9vw, 112px) 0; }
.band-tight { padding: clamp(44px, 6vw, 72px) 0; }
.band-alt   { background: var(--band); }
.band-line  { border-top: 1px solid var(--line); }

.band-ink {
  background: var(--ink);
  color: var(--on-ink);
  --tx: var(--on-ink);
  --tx-mut: var(--on-ink-mut);
  --line: rgba(255,255,255,.14);
  --surface: rgba(255,255,255,.05);
  --panel: rgba(255,255,255,.07);
  --band: rgba(255,255,255,.07);
  --tint: rgba(255,255,255,.10);
  /* The warm accent has to be re-lit here: #9E4522 is chosen for contrast on
     paper and disappears against ink. */
  --alpenglow-tx: #EE9F7B;
}
.band-ink .eyebrow { color: var(--alpenglow-tx); }
/* :not(.btn) matters. This selector is 0-1-1 and .btn-primary is 0-1-0, so
   without it the rule repainted the closing CTA button's label in pale green on
   its own dark-green fill — 2.11:1, the worst contrast on the site, on the most
   important button. A button carries its own foreground; only prose links here. */
.band-ink a:not(.btn) { color: color-mix(in oklab, var(--spruce) 65%, #fff); }

.section-head { max-width: 62ch; margin-bottom: clamp(32px, 4vw, 52px); }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head h2 + .lede { margin-top: 16px; }

/* ------------------------------------------------------------------- hero */

.hero { position: relative; overflow: hidden; padding: clamp(48px, 7vw, 84px) 0 clamp(56px, 7vw, 92px); }
.hero .wrap { position: relative; z-index: 1; }

.hero-grid { display: grid; gap: clamp(38px, 5vw, 56px); align-items: center; }
@media (min-width: 980px) {
  .hero-grid { grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr); gap: 56px; }
}

.hero h1 { margin-bottom: 20px; }
.hero h1 em {
  font-style: normal;
  color: var(--spruce);
}
.hero .lede { margin-bottom: 28px; font-size: clamp(1.08rem, 1.6vw, 1.26rem); }
.hero .btn-row { margin-bottom: 18px; }

.hero-note {
  font-size: 0.88rem; color: var(--tx-mut);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.hero-note svg { width: 15px; height: 15px; color: var(--spruce); flex: none; }

/* -------------------------------------------------------- trust / marquee */

.trust { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.trust-grid {
  display: grid; gap: 1px;
  grid-template-columns: 1fr;
  background: var(--line);
}
@media (min-width: 720px) { .trust-grid { grid-template-columns: repeat(3, 1fr); } }
.trust-cell {
  background: var(--paper);
  padding: 24px 26px;
  display: flex; gap: 14px; align-items: flex-start;
}
.trust-cell svg { width: 22px; height: 22px; color: var(--spruce); flex: none; margin-top: 2px; }
.trust-cell h3 {
  margin: 0 0 3px; font-family: var(--f-body); font-size: 0.97rem;
  font-weight: 600; letter-spacing: 0; line-height: 1.4;
}
.trust-cell p { margin: 0; font-size: 0.88rem; color: var(--tx-mut); line-height: 1.5; }

/* ------------------------------------------------------------- step cards */

.steps { display: grid; gap: 20px; counter-reset: step; }
@media (min-width: 860px) { .steps { grid-template-columns: repeat(3, 1fr); gap: 24px; } }

.step {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 28px 26px 26px;
}
.step::before {
  counter-increment: step;
  content: counter(step);
  font-family: var(--f-disp); font-size: 0.9rem; font-weight: 600;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--tint); color: var(--spruce);
  margin-bottom: 16px;
}
.step h3 { margin-bottom: 8px; font-size: 1.28rem; }
.step p { color: var(--tx-mut); font-size: 0.95rem; margin: 0; }

/* ----------------------------------------------------------- feature grid */

.fgrid { display: grid; gap: 22px; }
@media (min-width: 640px) { .fgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .fgrid.four { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1040px) { .fgrid.three { grid-template-columns: repeat(3, 1fr); } }

.fcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 26px 24px;
  transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}
.fcard:hover {
  transform: translateY(-3px);
  border-color: color-mix(in oklab, var(--spruce) 40%, var(--line));
  box-shadow: var(--shadow);
}
.fcard .ico {
  width: 42px; height: 42px; border-radius: var(--r);
  background: var(--tint); color: var(--spruce);
  display: grid; place-items: center; margin-bottom: 18px;
}
.fcard .ico svg { width: 21px; height: 21px; }
.fcard h3 { font-size: 1.2rem; margin-bottom: 8px; }
.fcard p { color: var(--tx-mut); font-size: 0.94rem; margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .fcard, .fcard:hover { transition: none; transform: none; }
}

/* ------------------------------------------------------------ feature row */

.frow { display: grid; gap: clamp(32px, 5vw, 60px); align-items: center; }
@media (min-width: 940px) {
  .frow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .frow.flip .frow-media { order: -1; }
}
.frow + .frow { margin-top: clamp(56px, 8vw, 104px); }

.frow-copy h2 { margin-bottom: 16px; }
.frow-copy .lede { margin-bottom: 22px; }

.ticks { list-style: none; padding: 0; margin: 0 0 24px; display: grid; gap: 11px; }
.ticks li { display: flex; gap: 11px; align-items: flex-start; font-size: 0.97rem; }
.ticks svg { width: 19px; height: 19px; color: var(--spruce); flex: none; margin-top: 3px; }

/* --------------------------------------------------------- product mockups
   Real DOM, not screenshots: crisp at any DPI, correct in both themes, and
   incapable of going stale relative to the design system. */

.mock {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  font-size: 14px;
}
.mock-hd {
  display: flex; align-items: center; gap: 9px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
.mock-hd .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); flex: none; }
.mock-hd .t {
  font-family: var(--f-disp); font-size: 0.92rem; font-weight: 600;
  margin-left: 4px; letter-spacing: -0.01em;
}
.mock-hd .sp { margin-left: auto; font-size: 0.72rem; color: var(--tx-mut); font-family: var(--f-mono); }
.mock-bd { padding: 18px 16px; display: grid; gap: 14px; }

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.7rem; font-weight: 600;
  padding: 3px 9px; border-radius: 999px;
  background: var(--spruce-lo); color: var(--spruce);
}
.pill.warn {
  background: color-mix(in oklab, var(--alpenglow) 15%, transparent);
  color: var(--alpenglow-tx);
}

/* Transaction list */
.txn { display: flex; align-items: center; gap: 11px; padding: 9px 0; border-top: 1px solid var(--line); }
.txn:first-child { border-top: 0; }
.txn .ic { width: 28px; height: 28px; border-radius: 8px; background: var(--panel); display: grid; place-items: center; font-size: 14px; flex: none; }
.txn .nm { font-size: 0.9rem; font-weight: 500; }
.txn .mt { font-size: 0.74rem; color: var(--tx-mut); }
.txn .vl { margin-left: auto; font-size: 0.9rem; font-variant-numeric: tabular-nums; font-weight: 600; }
.txn .vl.in { color: var(--spruce); }

/* Summary tiles */
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.tile { background: var(--panel); border-radius: var(--r); padding: 12px 13px; }
.tile .k { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--tx-mut); font-family: var(--f-mono); }
.tile .v { font-family: var(--f-disp); font-size: 1.24rem; font-weight: 600; margin-top: 3px; font-variant-numeric: tabular-nums; }
.tile .v.pos { color: var(--spruce); }
.tile .v.neg { color: var(--alpenglow-tx); }

/* Donut + bars used on the insights mockup */
.mini-bars { display: flex; align-items: flex-end; gap: 6px; height: 78px; }
.mini-bars i {
  flex: 1; border-radius: 3px 3px 0 0; background: var(--spruce);
  opacity: .35; display: block;
}
.mini-bars i.on { opacity: 1; }

/* ----------------------------------------------------------- bar explainer */

.legend { display: grid; gap: 12px; margin-top: 22px; }
@media (min-width: 620px) { .legend { grid-template-columns: repeat(2, 1fr); } }
.legend-item { display: flex; gap: 11px; align-items: flex-start; font-size: 0.9rem; }
.legend-swatch { width: 34px; height: 10px; border-radius: 999px; flex: none; margin-top: 5px; }
.legend-item b { display: block; font-size: 0.9rem; }
.legend-item span { color: var(--tx-mut); font-size: 0.85rem; }

/* --------------------------------------------------------------- quotes */

/* Kept deliberately, though nothing emits it right now. The homepage's Reviews
   section says "none yet" instead of showing invented quotes; when real ones
   arrive they go back into this layout. Not drift — see the note at the top of
   pages/index.mjs. */
.quotes { display: grid; gap: 20px; }
@media (min-width: 900px) { .quotes { grid-template-columns: repeat(3, 1fr); } }
.quote {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 24px;
  display: flex; flex-direction: column; gap: 14px;
}
.quote blockquote { margin: 0; font-size: 0.99rem; line-height: 1.6; }
.quote .who { display: flex; align-items: center; gap: 10px; margin-top: auto; }
.quote .av {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--tint); color: var(--spruce);
  display: grid; place-items: center; font-weight: 600; font-size: 0.82rem;
}
.quote .who b { font-size: 0.87rem; display: block; font-weight: 600; }
.quote .who span { font-size: 0.78rem; color: var(--tx-mut); }

/* Placeholder marking. Deliberately visible: an unmarked fake testimonial on
   a real marketing site is a lie, and this site has no real ones yet. */
[data-placeholder] { position: relative; }
.ph-banner {
  display: flex; gap: 10px; align-items: flex-start;
  border: 1px dashed var(--alpenglow);
  background: color-mix(in oklab, var(--alpenglow) 8%, transparent);
  border-radius: var(--r); padding: 13px 16px; margin-bottom: 22px;
  font-size: 0.86rem; color: var(--tx);
}
.ph-banner svg { width: 17px; height: 17px; color: var(--alpenglow); flex: none; margin-top: 2px; }
.ph-banner b { color: var(--alpenglow-tx); }
.quote[data-placeholder] { border-style: dashed; }

/* --------------------------------------------------------------- pricing */

.price-toggle {
  display: inline-flex; align-items: center; gap: 3px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 999px; padding: 4px; margin: 0 auto 40px;
}
.price-toggle button {
  font: inherit; font-size: 0.88rem; font-weight: 600;
  padding: 8px 18px; border-radius: 999px; border: 0;
  background: transparent; color: var(--tx-mut); cursor: pointer;
  transition: background-color 140ms ease, color 140ms ease;
}
.price-toggle button[aria-pressed='true'] {
  background: var(--surface); color: var(--tx); box-shadow: var(--shadow-sm);
}
.save-tag {
  font-size: 0.68rem; font-weight: 700; margin-left: 6px;
  color: var(--spruce); text-transform: uppercase; letter-spacing: .06em;
}

.tiers { display: grid; gap: 22px; align-items: start; }
@media (min-width: 760px)  { .tiers { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .tiers.three { grid-template-columns: repeat(3, 1fr); } }

.tier {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 28px 24px;
  display: flex; flex-direction: column; height: 100%;
}
.tier.hot {
  border-color: var(--spruce);
  box-shadow: 0 0 0 1px var(--spruce), var(--shadow);
  position: relative;
}
.tier-flag {
  position: absolute; top: -11px; left: 24px;
  background: var(--spruce); color: var(--on-spruce);
  font-size: 0.66rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  padding: 4px 11px; border-radius: 999px;
}
.tier h3 { font-size: 1.34rem; margin-bottom: 4px; }
.tier .desc { font-size: 0.87rem; color: var(--tx-mut); min-height: 2.6em; margin-bottom: 18px; }
.tier .cost { display: flex; align-items: baseline; gap: 5px; margin-bottom: 4px; }
.tier .cost .num {
  font-family: var(--f-disp); font-size: 2.5rem; font-weight: 600;
  letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums;
}
.tier .cost .per { font-size: 0.88rem; color: var(--tx-mut); }
.tier .alt-cost { font-size: 0.78rem; color: var(--tx-mut); margin-bottom: 20px; min-height: 1.2em; }
.tier .btn { width: 100%; margin-bottom: 20px; }
.tier ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 9px; }
.tier li { display: flex; gap: 9px; font-size: 0.87rem; align-items: flex-start; line-height: 1.45; }
.tier li svg { width: 16px; height: 16px; color: var(--spruce); flex: none; margin-top: 3px; }
.tier li.lead { font-weight: 600; }

/* Comparison table */
.cmp-scroll { overflow-x: auto; margin-top: 12px; -webkit-overflow-scrolling: touch; }
table.cmp {
  width: 100%; min-width: 660px; border-collapse: collapse;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  font-size: 0.9rem;
}
table.cmp th, table.cmp td { padding: 12px 15px; text-align: left; border-bottom: 1px solid var(--line); }
table.cmp thead th {
  font-family: var(--f-mono); font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--tx-mut); font-weight: 500; background: var(--panel);
  position: sticky; top: 0;
}
table.cmp td.c, table.cmp th.c { text-align: center; }
table.cmp tbody tr:last-child td { border-bottom: 0; }
table.cmp .yes { color: var(--spruce); font-weight: 600; }
/* Sized deliberately rather than left to the icon default: a tick in a dense
   table wants to read as a mark in the row, not as an illustration. */
table.cmp .yes svg { width: 18px; height: 18px; margin: 0 auto; }
table.cmp .no  { color: var(--tx-mut); }
table.cmp caption { caption-side: top; text-align: left; font-size: .8rem; color: var(--tx-mut); padding-bottom: 8px; }

/* -------------------------------------------------------------------- faq */

.faq { display: grid; gap: 0; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: center; gap: 14px;
  padding: 20px 4px; cursor: pointer; list-style: none;
  font-weight: 600; font-size: 1.02rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ''; margin-left: auto; flex: none;
  width: 11px; height: 11px;
  border-right: 2px solid var(--tx-mut); border-bottom: 2px solid var(--tx-mut);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 180ms ease;
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.faq .ans { padding: 0 4px 22px; color: var(--tx-mut); max-width: 72ch; }
.faq .ans p { font-size: 0.97rem; }
@media (prefers-reduced-motion: reduce) { .faq summary::after { transition: none; } }

/* --------------------------------------------------------------- cta band */

.cta-photo { position: relative; overflow: hidden; isolation: isolate; }
.cta-photo img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: -2;
  /* The band is ~470px tall over a 1100x733 frame, so `cover` crops hard, and
     centred it landed on the black spruce forest across the bottom half — the
     one part of the photograph with no light in it. The gold on the peaks sits
     at roughly 37-55% of the frame height; 42% puts it in the band. This, not
     the overlay, was the main reason the photograph read as a black rectangle. */
  object-position: center 42%;
}
/* Grade the photograph toward the palette so it reads as brand, not stock. */
/* Dark enough for white type on the left, light enough on the right that the
   ridge is actually visible. Two passes buried the photograph entirely, which
   is the same as not having one — the note survived both. Now that the crop
   holds the lit peaks there is something to protect, so the veil is pulled back
   to where the type still clears AA and the light is allowed through. */
.cta-photo::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to right, rgba(12,19,16,.88) 0%, rgba(12,19,16,.62) 42%, rgba(12,19,16,.12) 100%),
    linear-gradient(to bottom, rgba(15,107,78,.16), rgba(12,19,16,.10));
}
.cta-photo .wrap { position: relative; }
.cta-inner { max-width: 60ch; }
.cta-inner h2 { margin-bottom: 16px; }
.cta-inner .lede { color: var(--on-ink-mut); margin-bottom: 26px; }

.photo-credit {
  position: absolute; right: 10px; bottom: 8px;
  font-size: 0.64rem; color: rgba(255,255,255,.5);
  font-family: var(--f-mono);
}
.photo-credit a { color: inherit; }

/* ----------------------------------------------------------------- figure */

figure.shot { margin: 0; }
figure.shot img { border-radius: var(--r-lg); border: 1px solid var(--line); box-shadow: var(--shadow); }
figure.shot figcaption {
  font-size: 0.78rem; color: var(--tx-mut); margin-top: 10px; line-height: 1.5;
}

/* ----------------------------------------------------------------- footer */

/* A full-width page ground, so --band rather than --panel. */
.foot { border-top: 1px solid var(--line); background: var(--band); padding: clamp(44px, 6vw, 68px) 0 32px; }
.foot-grid { display: grid; gap: 34px; }
@media (min-width: 700px)  { .foot-grid { grid-template-columns: 1.6fr repeat(2, 1fr); } }
@media (min-width: 1000px) { .foot-grid { grid-template-columns: 1.8fr repeat(4, 1fr); } }

.foot .foot-title {
  font-family: var(--f-mono); font-size: 0.66rem; text-transform: uppercase;
  letter-spacing: 0.13em; color: var(--tx-mut); margin: 0 0 14px; font-weight: 500;
  line-height: 1.4;
}
.foot ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 9px; }
.foot a { color: var(--tx-mut); text-decoration: none; font-size: 0.9rem; }
.foot a:hover { color: var(--spruce); }
.foot-about p { font-size: 0.88rem; color: var(--tx-mut); max-width: 34ch; margin: 14px 0 0; }

.foot-bar {
  margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 12px 22px; align-items: center;
  font-size: 0.8rem; color: var(--tx-mut);
}
.foot-bar .spacer { margin-left: auto; }

/* --------------------------------------------------------------- reveals */

/* Reveals are OPT-IN, armed by site.js itself (`.js-reveal` on <html>).
   The naive form — .reveal { opacity: 0 } undone by script — hides the entire
   page if that script 404s, is blocked, or throws before it runs. Here the
   default is visible, and only the code that can also un-hide content is
   allowed to hide it. */
.reveal { opacity: 1; }
.js-reveal .reveal { opacity: 0; transform: translateY(14px); }
.js-reveal .reveal.in {
  opacity: 1; transform: none;
  transition: opacity 620ms cubic-bezier(.2,.7,.3,1), transform 620ms cubic-bezier(.2,.7,.3,1);
}
/* Already on screen when the page loaded — show it, don't animate it. */
.js-reveal .reveal.now { transition: none !important; transition-delay: 0s !important; }
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.in { opacity: 1; transform: none; transition: none; }
}

/* ------------------------------------------------------------------- misc */

.prose h2 { margin: 1.8em 0 .5em; }
.prose h3 { margin: 1.6em 0 .4em; }
.prose ul, .prose ol { padding-left: 1.3em; margin: 0 0 1.1em; }
.prose li { margin: .35em 0; }
.prose > p:first-child { margin-top: 0; }

.callout {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--spruce); border-radius: var(--r-sm);
  padding: 16px 20px; margin: 1.6em 0;
}
.callout.warn { border-left-color: var(--alpenglow); }
.callout .lbl {
  font-family: var(--f-mono); font-size: 0.64rem; text-transform: uppercase;
  letter-spacing: 0.13em; color: var(--tx-mut); display: block; margin-bottom: 6px;
}

.big-404 {
  font-family: var(--f-disp); font-size: clamp(5rem, 20vw, 11rem);
  line-height: .9; color: var(--spruce); margin: 0 0 12px; font-variant-numeric: tabular-nums;
}

/* ============================================================== walkthroughs
   Animated product demos. lib/demo.mjs explains the shape; this is how it
   looks and, more importantly, how it behaves when the JavaScript that drives
   it never arrives.

   The load-bearing rule is that `.js-demo` — set on <html> before first paint,
   and removed by a watchdog if site.js does not run — is what turns a stack of
   frames into a player. Everything that hides a frame is scoped under it. Left
   alone, every frame renders in document order with its caption, which is a
   perfectly good storyboard. The animation is an enhancement; the lesson is
   not.
   ========================================================================== */

.demo {
  margin: 34px 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--panel);
  overflow: hidden;
}
.demo-lede {
  margin: 0; padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  font-size: 0.93rem; color: var(--tx-mut);
  background: var(--surface);
}
.demo-body { display: grid; gap: 0; }
@media (min-width: 900px) {
  .demo-body { grid-template-columns: minmax(0, 1.15fr) minmax(240px, .85fr); }
}

.demo-stage { padding: 20px; min-width: 0; }
.demo-frame { min-width: 0; }
.demo-frame + .demo-frame { margin-top: 22px; }
.demo-screen { position: relative; }

.demo-cap {
  margin: 12px 2px 0; font-size: 0.86rem; line-height: 1.5; color: var(--tx-mut);
}
.demo-cap b { color: var(--tx); font-weight: 600; }

/* ------------------------------------------------------------ the side rail */

.demo-side {
  border-top: 1px solid var(--line);
  background: var(--surface);
  display: flex; flex-direction: column;
}
@media (min-width: 900px) {
  .demo-side { border-top: 0; border-left: 1px solid var(--line); }
}
/* align-content:start matters — the rail is a grid inside a stretched flex
   column, so without it the rows spread to fill the stage's height and the
   steps drift apart from each other. */
.demo-track {
  list-style: none; margin: 0; padding: 10px;
  display: grid; gap: 2px; align-content: start; flex: 1;
}
.demo-go {
  width: 100%; display: flex; align-items: center; gap: 11px;
  background: none; border: 0; border-radius: var(--r-sm);
  padding: 9px 10px; text-align: left; cursor: pointer;
  font: inherit; font-size: 0.88rem; color: var(--tx-mut);
}
.demo-go .n {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 0.68rem;
  background: var(--panel); color: var(--tx-mut);
}
.demo-go:hover { background: var(--panel); color: var(--tx); }
.demo-go.is-on { background: var(--spruce-lo); color: var(--tx); font-weight: 600; }
.demo-go.is-on .n { background: var(--spruce); color: var(--on-spruce); }

.demo-ctl {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px; border-top: 1px solid var(--line);
}
.demo-play {
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 1px solid var(--line); border-radius: 999px;
  padding: 5px 12px 5px 10px; cursor: pointer;
  font: inherit; font-size: 0.78rem; font-weight: 600; color: var(--tx);
}
.demo-play:hover { border-color: color-mix(in oklab, var(--spruce) 45%, var(--line)); }
.demo-play-ico {
  width: 9px; height: 11px; flex: none; background: currentColor;
  /* Two bars = pause. Swapped for a triangle when paused. */
  clip-path: polygon(0 0, 34% 0, 34% 100%, 0 100%, 0 0, 66% 0, 100% 0, 100% 100%, 66% 100%, 66% 0);
}
.demo.is-paused .demo-play-ico { clip-path: polygon(0 0, 100% 50%, 0 100%); }
.demo-status {
  margin: 0; font-family: var(--f-mono); font-size: 0.7rem;
  color: var(--tx-mut); letter-spacing: .04em;
}

/* Without the player, the rail is a duplicate table of contents for frames
   that are all visible anyway — and its buttons would do nothing. */
.demo-side { display: none; }
.js-demo .demo-side { display: flex; }

/* ------------------------------------------------------------- player mode */

/* Inactive frames are lifted out of flow so the stage is the height of the
   step you are looking at, not of the longest one — otherwise every short step
   sits above a slab of dead space. site.js then sets that height explicitly and
   this transition animates between steps, so nothing below the demo jumps. */
.js-demo .demo-stage {
  position: relative;
  transition: height 400ms cubic-bezier(.4, 0, .2, 1);
}
.js-demo .demo-frame {
  position: absolute; top: 20px; left: 20px; right: 20px;
  opacity: 0; visibility: hidden;
  transform: translateY(10px);
  transition: opacity 380ms ease, transform 380ms ease;
}
.js-demo .demo-frame + .demo-frame { margin-top: 0; }
.js-demo .demo-frame.is-on {
  position: relative; top: auto; left: auto; right: auto;
  opacity: 1; visibility: visible; transform: none;
}

/* Rows arrive in sequence. --d is set per row by demo.mjs's row(). */
.js-demo .demo-frame .anim { opacity: 0; transform: translateY(8px); }
.js-demo .demo-frame.is-on .anim {
  opacity: 1; transform: none;
  transition: opacity 420ms ease var(--d, 0ms), transform 420ms ease var(--d, 0ms);
}

.split > span { width: var(--w); }
.js-demo .demo-frame .split > span { width: 0; }
.js-demo .demo-frame.is-on .split > span {
  width: var(--w);
  transition: width 760ms cubic-bezier(.2, .7, .2, 1) 300ms;
}

/* The tap ring: where the finger went. */
.demo-tap { display: none; }
.js-demo .demo-frame.is-on .demo-tap {
  display: block; position: absolute; width: 34px; height: 34px;
  margin: -17px 0 0 -17px; border-radius: 50%;
  border: 2px solid var(--spruce); pointer-events: none;
  animation: tap 1.6s ease-out 700ms 2;
  opacity: 0;
}
@keyframes tap {
  0%   { transform: scale(.35); opacity: 0; }
  35%  { opacity: .85; }
  100% { transform: scale(1.5); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .js-demo .demo-stage,
  .js-demo .demo-frame,
  .js-demo .demo-frame.is-on .anim,
  .js-demo .demo-frame.is-on .split > span { transition: none; }
  .js-demo .demo-frame .anim { opacity: 1; transform: none; }
  .js-demo .demo-frame .split > span { width: var(--w); }
  .js-demo .demo-frame.is-on .demo-tap { animation: none; opacity: .7; }
}

/* ====================================================== frame vocabulary
   Small pieces the guide frames are assembled from. They live with the demo
   styles because nothing else on the site uses them.
   ====================================================================== */

.mocknote {
  margin: 2px 0 0; font-size: 0.8rem; line-height: 1.55; color: var(--tx-mut);
}
.mocknote b { color: var(--tx); font-weight: 600; }

.bignum {
  font-family: var(--f-disp); font-size: 2.1rem; font-weight: 600;
  text-align: center; padding: 6px 0 2px; letter-spacing: -.01em;
}

.wiz-dots { display: flex; gap: 6px; justify-content: center; padding-bottom: 4px; }
.wiz-dots i { width: 22px; height: 4px; border-radius: 999px; background: var(--line); }
.wiz-dots i.on { background: var(--spruce); }

.fld {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 10px 13px; background: var(--surface);
}
.fld-k { font-size: 0.78rem; color: var(--tx-mut); }
.fld-v { margin-left: auto; font-size: 0.88rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.fld.focus { border-color: var(--spruce); box-shadow: 0 0 0 3px var(--spruce-lo); }

.opt {
  display: flex; align-items: center; gap: 11px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 10px 13px; background: var(--surface);
}
.opt.sel { border-color: var(--spruce); background: var(--spruce-lo); }
.opt-ic {
  width: 28px; height: 28px; flex: none; border-radius: 8px;
  background: var(--panel); display: grid; place-items: center; font-size: 14px;
}
.opt-tx { display: grid; min-width: 0; }
.opt-tx b { font-size: 0.88rem; font-weight: 600; }
.opt-tx span { font-size: 0.74rem; color: var(--tx-mut); }
.opt-tick { margin-left: auto; color: var(--spruce); font-weight: 700; }

.btnrow { display: flex; flex-wrap: wrap; gap: 8px; }
.mockbtn {
  display: inline-block; border-radius: 999px; padding: 7px 14px;
  font-size: 0.78rem; font-weight: 600;
  border: 1px solid var(--line); background: var(--surface); color: var(--tx);
}
.mockbtn.pri { background: var(--spruce); border-color: var(--spruce); color: var(--on-spruce); }

.kbar {
  display: flex; align-items: baseline; gap: 10px;
  font-size: 0.85rem; padding: 8px 0; border-top: 1px solid var(--line);
}
.kbar:first-child { border-top: 0; }
.kbar > :last-child { margin-left: auto; font-variant-numeric: tabular-nums; }
.kbar.strong { font-weight: 600; }
.amt.pos, .kbar .pos { color: var(--spruce); }
.amt.neg, .kbar .neg { color: var(--alpenglow-tx); }

/* Covered vs carried, on one bar. Same grammar as the envelope bar: the solid
   part is settled, the textured part is the part that still owes an answer. */
.split {
  display: flex; height: 12px; border-radius: 999px; overflow: hidden;
  background: var(--panel);
}
.split > span { display: block; height: 100%; }
.split .covered { background: var(--spruce); }
.split .carried {
  background: repeating-linear-gradient(135deg,
    var(--alpenglow) 0 5px, color-mix(in oklab, var(--alpenglow) 68%, transparent) 5px 10px);
}

.tabsrow { display: flex; gap: 6px; flex-wrap: wrap; }
.tabsrow span {
  border-radius: 999px; padding: 5px 11px; font-size: 0.73rem; font-weight: 600;
  background: var(--panel); color: var(--tx-mut);
}
.tabsrow span.on { background: var(--spruce); color: var(--on-spruce); }

/* One reconciliation row: the bank's version, ours, and the verdict. Two
   columns on a phone would make both sides unreadable, so it stacks. */
.match {
  display: grid; gap: 4px 12px; align-items: center;
  grid-template-columns: 1fr auto;
  border: 1px solid var(--line); border-left: 3px solid var(--line);
  border-radius: var(--r-sm); background: var(--surface); padding: 10px 13px;
}
@media (min-width: 560px) {
  .match { grid-template-columns: 1fr 24px 1fr auto; }
}
.match.ok { border-left-color: var(--spruce); }
.match.new { border-left-color: var(--alpenglow); }
.match.ask { border-left-color: var(--tx-mut); }
.match-side { display: grid; min-width: 0; }
.match-side b { font-size: 0.85rem; font-weight: 600; overflow-wrap: anywhere; }
.match-side .mt { font-size: 0.72rem; color: var(--tx-mut); }
.match-lbl {
  font-family: var(--f-mono); font-size: 0.6rem; text-transform: uppercase;
  letter-spacing: .12em; color: var(--tx-mut);
}
.match-join {
  display: none; place-items: center; font-family: var(--f-mono);
  font-size: 0.95rem; color: var(--tx-mut);
}
@media (min-width: 560px) { .match-join { display: grid; } }
.match-end { display: grid; justify-items: end; gap: 3px; }
.match-end .amt { font-size: 0.88rem; font-weight: 600; }
.conf {
  font-family: var(--f-mono); font-size: 0.6rem; letter-spacing: .06em;
  border-radius: 999px; padding: 2px 7px; white-space: nowrap;
}
.conf.hi { background: var(--spruce-lo); color: var(--spruce); }
.conf.mid { background: var(--panel); color: var(--tx-mut); }
.conf.rule { background: color-mix(in oklab, var(--alpenglow) 16%, transparent); color: var(--alpenglow-tx); }

.cmpbal { display: grid; gap: 0; }
.cmpbal > div {
  display: flex; align-items: baseline; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--line); font-size: 0.87rem;
}
.cmpbal > div:first-child { border-top: 0; }
.cmpbal b { margin-left: auto; font-variant-numeric: tabular-nums; }
.cmpbal .ok { border-top-width: 2px; font-weight: 600; }
.cmpbal .ok b { color: var(--spruce); }

/* ============================================================ guide chrome */

/* Chapter rail. A numbered strip rather than a sidebar: it survives a phone,
   it shows how many chapters there are, and it never needs opening. */
.rail { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rail ol {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: 8px; min-width: min-content;
}
.rail a {
  display: inline-flex; align-items: center; gap: 9px; white-space: nowrap;
  border: 1px solid var(--line); border-radius: 999px;
  padding: 8px 15px 8px 9px; text-decoration: none;
  font-size: 0.87rem; font-weight: 600; color: var(--tx-mut);
  background: var(--surface);
}
.rail a:hover { color: var(--tx); border-color: color-mix(in oklab, var(--spruce) 45%, var(--line)); }
.rail .n {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 0.68rem;
  background: var(--panel); color: var(--tx-mut);
}
.rail a[aria-current='page'] {
  background: var(--spruce); border-color: var(--spruce); color: var(--on-spruce);
}
/* The pip is derived from the foreground rather than restated per theme, so it
   follows --on-spruce automatically instead of needing its own pair of rules. */
.rail a[aria-current='page'] .n {
  background: color-mix(in srgb, var(--on-spruce) 22%, transparent);
  color: var(--on-spruce);
}

.band-tight { padding-top: 26px; padding-bottom: 26px; }

/* Chapter cards on the hub. */
.chapters { display: grid; gap: 18px; margin-top: 34px; }
@media (min-width: 780px) { .chapters { grid-template-columns: repeat(3, 1fr); } }
.chapter {
  display: grid; align-content: start; gap: 9px;
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); padding: 24px 22px 22px;
  text-decoration: none; color: inherit;
  transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}
.chapter:hover {
  border-color: color-mix(in oklab, var(--spruce) 45%, var(--line));
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}
.chapter .n {
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: .12em;
  color: var(--spruce);
}
.chapter h3 { font-size: 1.2rem; margin: 0; }
.chapter p { margin: 0; font-size: 0.9rem; color: var(--tx-mut); }
.chapter .go {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.87rem; font-weight: 600; color: var(--spruce); margin-top: 4px;
}
.chapter .go svg { width: 16px; height: 16px; }
@media (prefers-reduced-motion: reduce) {
  .chapter, .chapter:hover { transition: none; transform: none; }
}

/* A tier requirement, said out loud and early. */
.tier-note {
  display: flex; align-items: baseline; gap: 11px; flex-wrap: wrap;
  margin: 22px 0 0; font-size: 0.9rem; color: var(--tx-mut);
}
.tier-chip {
  font-family: var(--f-mono); font-size: 0.63rem; text-transform: uppercase;
  letter-spacing: .13em; border-radius: 999px; padding: 4px 10px;
  background: var(--tint); color: var(--spruce); font-weight: 700;
}

/* The icon tile is 40px in the app, not 32. */
.eico {
  width: 40px; height: 40px; flex: none; border-radius: 12px;
  display: grid; place-items: center;
  background: color-mix(in oklab, var(--c) 14%, transparent);
  color: var(--c);
}
.eico svg { display: block; }
.opt > .eico { width: 28px; height: 28px; border-radius: 8px; }
.txn > .eico { width: 28px; height: 28px; border-radius: 8px; }

.wiz-dots i.done { background: color-mix(in oklab, var(--spruce) 45%, var(--line)); }

/* ========================================== three models, side by side
   The comparison only works if the three columns move together and stay
   visually equal — so they share a grid, and only the accent says which one
   is ours. Overstating the difference with colour would undercut the argument
   the copy is trying to make honestly.
   ================================================================== */

.models { display: grid; gap: 12px; }
@media (min-width: 760px) { .models { grid-template-columns: repeat(3, 1fr); } }

.model {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface); overflow: hidden;
  display: flex; flex-direction: column;
}
.model-hd {
  padding: 10px 13px; border-bottom: 1px solid var(--line);
  background: var(--panel);
}
.model-hd b { display: block; font-size: 0.88rem; font-weight: 600; }
.model-hd span {
  display: block; font-family: var(--f-mono); font-size: 0.62rem;
  letter-spacing: .04em; color: var(--tx-mut); margin-top: 2px;
}
.model-bd { padding: 11px 13px; display: grid; gap: 7px; align-content: start; }
.model.ours { border-color: color-mix(in oklab, var(--spruce) 50%, var(--line)); }
.model.ours .model-hd {
  background: var(--spruce-lo);
  border-bottom-color: color-mix(in oklab, var(--spruce) 30%, var(--line));
}
.model.ours .model-hd b { color: var(--spruce); }

/* Stacked, not a label/value row. Three narrow columns cannot give both halves
   enough width, and the flex version wrapped "Budget comes from" onto three
   lines while its value broke across two — which made the columns impossible
   to compare at a glance, the one job this table has. */
.mline { display: grid; gap: 1px; font-size: 0.78rem; }
.mline > :first-child { color: var(--tx-mut); line-height: 1.35; }
.mline > :last-child { font-weight: 600; color: var(--tx); font-size: 0.84rem; }

.mflag {
  margin: 3px 0 0; font-size: 0.75rem; line-height: 1.5;
  border-radius: var(--r-sm); padding: 8px 10px;
  background: var(--panel); color: var(--tx-mut);
}
.mflag b { color: var(--tx); }
.mflag.warn {
  background: color-mix(in oklab, var(--alpenglow) 11%, transparent);
  color: color-mix(in oklab, var(--alpenglow) 78%, var(--tx));
}
.mflag.warn b { color: var(--alpenglow-tx); }
.mflag.good { background: var(--spruce-lo); color: color-mix(in oklab, var(--spruce) 74%, var(--tx)); }
.mflag.good b { color: var(--spruce); }

/* ------------------------------------------------------- switching cards */

.switchgrid { display: grid; gap: 20px; margin-top: 36px; }
@media (min-width: 900px) { .switchgrid { grid-template-columns: 1fr 1fr; } }
.switchcard {
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); padding: 28px 26px;
}
.switchcard .from {
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--tx-mut); margin: 0 0 10px;
}
.switchcard .from b { color: var(--spruce); font-weight: 600; }
.switchcard h3 { margin: 0 0 12px; font-size: 1.4rem; }
.sw { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }
.sw .lbl {
  font-family: var(--f-mono); font-size: 0.63rem; text-transform: uppercase;
  letter-spacing: .13em; color: var(--tx-mut); margin: 0 0 8px;
}
.sw p:not(.lbl) { font-size: 0.93rem; color: var(--tx-mut); margin: 0; }
.sw .ticks { margin: 0; }
.sw .ticks li { font-size: 0.9rem; }

/* ==================================================== bottom sheets
   Every screen in the app that takes input is a Sheet — a draggable bottom
   sheet with a grabber and a Cancel beside a centred title. The guide drew
   them in desktop window chrome, which put the right fields on the wrong
   surface. Full screens keep the window; anything you type into gets this.
   ================================================================== */

.sheetmock { padding-top: 8px; border-radius: 18px 18px var(--r-lg) var(--r-lg); }
.sheet-grab {
  display: block; width: 38px; height: 4px; border-radius: 99px;
  background: var(--line); margin: 0 auto 6px;
}
.sheet-hd {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 14px 12px; border-bottom: 1px solid var(--line);
}
.sheet-cancel { font-size: 0.85rem; color: var(--spruce); flex: 1; }
.sheet-t { font-size: 0.98rem; font-weight: 600; white-space: nowrap; }
.sheet-sp { flex: 1; }

/* Expense | Refund. A pill in a track: the active half is a raised white
   surface, exactly as the app draws it. */
.segbar {
  display: flex; gap: 3px; padding: 3px;
  background: var(--panel); border-radius: 11px;
}
.segbar span {
  flex: 1; text-align: center; padding: 7px 0; border-radius: 8px;
  font-size: 0.82rem; font-weight: 500; color: var(--tx-mut);
}
.segbar span.on {
  background: var(--surface); color: var(--tx);
  box-shadow: var(--shadow-sm); font-weight: 600;
}

/* The amount, as AddTransactionSheet sets it: label, then the symbol at about
   a third the figure's size, both centred. */
.amtfield { display: grid; gap: 2px; padding: 6px 0 2px; }
.amtlbl { font-size: 0.78rem; color: var(--tx-mut); }
.amtbig {
  display: flex; align-items: baseline; justify-content: center; gap: 3px;
  font-family: var(--f-disp); font-size: 2.5rem; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -.015em; padding: 6px 0;
}
.amtbig i { font-style: normal; font-size: 1.5rem; color: var(--tx-mut); }

.btnrow.full .mockbtn { flex: 1; text-align: center; padding: 11px 14px; }
/* An icon tile used inline in a transaction row, where .txn expects its own
   28px square. Keeps the row rhythm without a second nested tile. */
.txn > .eico { width: 28px; height: 28px; border-radius: 8px; }

/* Step arrows. Auto-play suits a first read; stepping suits a careful one, and
   the rail alone means aiming at a named step rather than just going forward. */
.demo-arrow {
  width: 30px; height: 30px; flex: none; padding: 0;
  display: grid; place-items: center;
  background: none; border: 1px solid var(--line); border-radius: 8px;
  color: var(--tx); cursor: pointer;
}
.demo-arrow svg { width: 16px; height: 16px; }
.demo-arrow:hover { border-color: color-mix(in oklab, var(--spruce) 45%, var(--line)); }
.demo-ctl { gap: 7px; flex-wrap: wrap; }
.demo-ctl .demo-status { width: 100%; }
@media (min-width: 420px) {
  .demo-ctl .demo-status { width: auto; margin-left: auto; }
}

/* A diagram is not a screen, and must not be mistakable for one. No window bar,
   no sheet grabber, a dashed edge and a label that says what it is. The guide
   mixes the two deliberately — some steps explain what moved, which no single
   screen in the app shows — and the reader is entitled to know which they are
   looking at. */
.diagram {
  border-style: dashed;
  border-color: color-mix(in oklab, var(--tx-mut) 42%, var(--line));
  background: var(--paper);
  box-shadow: none;
}
.diagram-hd {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px; border-bottom: 1px dashed color-mix(in oklab, var(--tx-mut) 32%, var(--line));
}
.diagram-hd .t { font-family: var(--f-disp); font-size: 0.98rem; font-weight: 600; }
.diagram-tag {
  font-family: var(--f-mono); font-size: 0.58rem; letter-spacing: .13em;
  text-transform: uppercase; border-radius: 99px; padding: 3px 9px;
  background: color-mix(in oklab, var(--tx-mut) 16%, transparent); color: var(--tx-mut);
}

/* ============================================ the Add Expense sheet, as built
   Rebuilt against a render of the real AddTransactionSheet. The guide used to
   draw four label/value rows and a Date field; the sheet actually has a Today
   chip, a merchant input with its own placeholder, an account SELECT, envelope
   TILES rather than a picker row, a Split control and a Make Recurring switch.
   ========================================================================== */

.chiprow { display: flex; justify-content: center; }
.daychip {
  font-size: 0.76rem; border-radius: 999px; padding: 5px 12px;
  background: var(--panel); color: var(--tx-mut);
}

.afield { display: grid; gap: 6px; }
.afield-hd { display: flex; align-items: center; gap: 10px; }
.afield-lbl { font-size: 0.8rem; color: var(--tx-mut); }
.asplit {
  margin-left: auto; font-size: 0.72rem; font-weight: 500;
  border: 1px solid var(--line); border-radius: 8px; padding: 4px 10px;
  background: var(--panel); color: var(--tx-mut);
}
.ainput, .aselect {
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px;
  background: var(--panel); font-size: 0.88rem; color: var(--tx-mut);
}
.ainput.filled { color: var(--tx); font-weight: 500; background: var(--surface); }
.aselect {
  background: var(--surface); color: var(--tx); font-weight: 500;
  display: flex; align-items: center;
}
.aselect span { margin-left: auto; color: var(--tx-mut); }

/* Envelope tiles: a 4-up grid of tinted icon over name. */
.etiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.etile {
  display: grid; justify-items: center; gap: 5px; text-align: center;
  border-radius: 12px; padding: 10px 6px; background: var(--panel);
  font-size: 0.7rem; line-height: 1.2;
}
.etile.sel { background: var(--spruce-lo); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--spruce) 40%, transparent); }
.etile .eico { width: 34px; height: 34px; border-radius: 11px; }

.arow {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--line); border-radius: 12px;
  padding: 12px 14px; background: var(--surface); font-size: 0.86rem;
}
.arow .mt { font-size: 0.74rem; color: var(--tx-mut); }
.aswitch {
  margin-left: auto; flex: none; width: 42px; height: 24px; border-radius: 999px;
  background: var(--line); position: relative;
}
.aswitch::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--surface); box-shadow: var(--shadow-sm);
}

/* The amount, at the size the app actually sets it — 48px, with the symbol
   subordinate. The site drew 40px and I had assumed the app was smaller. */
.amtbig { font-size: 3rem; }
.amtbig i { font-size: 1.5rem; }

/* ================================================================ annotations
   A render with the site's commentary beside it, and — where a note is about
   one PART of the frame — a line to that part.

   The line is drawn by script into `.ann-lines`. Everything here has to look
   deliberate without it, because the connector is the only piece that needs
   JavaScript: the notes are ordinary text and the pins still number them. */

.ann { position: relative; margin: 0; display: grid; gap: 14px; }
.ann-stage { position: relative; }

/* Spans the whole figure, not just the stage — a line starts at a note below
   the frame and ends inside it. `pointer-events: none` so it never eats a
   click, and it stays empty until the script fills it. */
.ann-lines {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none; z-index: 2;
}
.ann-lines path {
  fill: none;
  stroke: var(--alpenglow-tx);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 3 3;
}
.ann-lines circle { fill: var(--alpenglow-tx); }
/* The in-frame number. It sits over the render, so it needs its own ground to
   stay legible against whatever the app painted underneath it. */
.ann-lines circle.ann-badge { fill: var(--alpenglow-tx); stroke: var(--surface); stroke-width: 1.5; }
.ann-lines text.ann-badge-t {
  fill: var(--surface); font-family: var(--f-mono); font-size: 9px; font-weight: 700;
  text-anchor: middle; stroke: none;
}

.ann-notes { display: grid; gap: 8px; }
.ann-note {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--tx-mut);
}
.ann-note b, .ann-note strong { color: var(--tx); font-weight: 600; }

/* The pin is the line's endpoint and its own fallback: with no script it still
   says "this note is about a specific part", which is most of the value. */
.ann-pin {
  display: inline-grid; place-items: center;
  width: 17px; height: 17px; border-radius: 50%;
  margin-right: 7px; vertical-align: -3px;
  background: var(--alpenglow-tx); color: var(--paper);
  font-family: var(--f-mono); font-size: 0.63rem; font-weight: 700;
}

/* A leader line across a narrow column would cross the frame diagonally and
   obscure what it points at, so below the breakpoint the pins carry it alone. */
@media (max-width: 560px) {
  .ann-lines { display: none; }
}
