/* Parametric — marketing site.
   Visual world: "Instrument". The product's whole argument is that it is
   calibrated, so the page is built like a measuring device: enamel panel
   ground, engraved ink, hairline scales with real ticks, every figure set in
   tabular mono, and ONE accent — needle vermilion — which is only ever allowed
   to mark a measurement. Never a decorative glow.

   Density and grid come from the Linear/Stripe/ClickHouse/Palantir token sets
   skillui extracted into design-refs/extracted/: 4px base grid, near-monochrome
   palette with one sparing accent, mono carrying the data, hierarchy from two
   faces rather than size alone.

   Nothing here animates on a timer. Scroll drives everything. */

:root {
  /* ── palette. near-monochrome + one accent ── */
  --paper:   #EFF0EC;   /* enamel panel ground */
  --paper-2: #E9EBE6;   /* recessed */
  --face:    #FFFFFF;   /* instrument face */
  --ink:     #15191A;   /* engraved */
  --ink-2:   #3E4648;
  --dim:     #5B6465;
  --dimmer:  #767F80;
  --line:    #D2D6D0;   /* the scale */
  --line-2:  #E2E5DF;   /* the fainter scale */
  --needle:  #C2452B;
  --needle-d:#A2381F;
  --needle-soft: #F3DFDA;

  /* legacy aliases so /demo and /demo/thanks keep working unchanged */
  --bg: var(--paper);
  --bg-2: var(--paper-2);
  --panel: var(--face);
  --accent: var(--needle);
  --accent-d: var(--needle-d);
  --good: #2F6B4F;
  --tint: var(--needle-soft);

  --sans: Archivo, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --serif: var(--sans);          /* the serif is gone; .serif now emphasises in-family */

  /* 4px base grid */
  --s1: 4px;  --s2: 8px;   --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 48px;  --s8: 64px; --s9: 96px; --s10: 128px;

  --gut: clamp(20px, 4vw, 56px);
  --maxw: 1360px;
  --phone-w: clamp(200px, 18vw, 288px);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-variation-settings: 'wdth' 100;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
html.lenis { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }

img, canvas, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul { list-style: none; padding: 0; }

/* ── browser surfaces. The parts we did not draw still carry the design. ── */
::selection { background: var(--ink); color: var(--paper); }
:focus-visible { outline: 2px solid var(--needle); outline-offset: 3px; border-radius: 2px; }
html { scrollbar-color: var(--line) var(--paper); scrollbar-width: thin; caret-color: var(--needle); }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--paper); }
::-webkit-scrollbar-thumb { background: var(--line); border: 3px solid var(--paper); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: #B9BFB9; }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding-inline: var(--gut); }

/* ---------- type ---------------------------------------------------------- */
/* Two faces. Archivo carries language, Geist Mono carries every figure.
   Hierarchy comes from width and weight, not from a second family. */

.mono, .num, .fig { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

.h1, .h2, .h3 {
  font-variation-settings: 'wdth' 114;
  font-weight: 700;
  letter-spacing: -.038em;
  line-height: 1.0;
  text-wrap: balance;
}
.h1 { font-size: clamp(38px, 5.6vw, 74px); line-height: .98; }
.h2 { font-size: clamp(30px, 3.9vw, 50px); }
.h3 { font-size: clamp(20px, 2.1vw, 27px); line-height: 1.08; letter-spacing: -.03em; }
/* Emphasis stays in-family — Archivo's own italic, not a borrowed serif
   dropped into a sans headline. That mixed-family move is the single most
   recognisable AI tell and it is what the old build did three times. */
.serif { font-style: italic; font-variation-settings: 'wdth' 104; font-weight: 700; }

.lede { color: var(--ink-2); font-size: clamp(15px, 1.15vw, 17px); line-height: 1.55; max-width: 62ch; }
.small { font-size: 13px; color: var(--dim); }

.eyebrow {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--dimmer);
  font-weight: 400;
}

/* the label that marks each section — the page's wayfinding, in place of an
   uppercase eyebrow above every headline. It used to lead with a clock time
   (19:42, 08:30, ...) in the accent colour; those were invented, and on a
   sales page an invented number is a liability, so only the label remains.
   `--dim`, not `--dimmer`: the red time used to carry the eye here, and with
   it gone the label was the faintest thing on the page. */
.stamp {
  display: inline-flex; align-items: baseline; gap: var(--s2);
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
  color: var(--dim); font-variant-numeric: tabular-nums;
}

/* ---------- buttons ------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: var(--s2);
  height: 42px; padding: 0 var(--s4);
  border: 1px solid var(--line);
  background: var(--face);
  color: var(--ink);
  font-family: var(--sans); font-size: 14px; font-weight: 600;
  letter-spacing: -.01em;
  border-radius: 2px;
  cursor: pointer; white-space: nowrap;
  transition: background .18s ease, border-color .18s ease, transform .12s ease, color .18s ease;
}
.btn:hover { border-color: var(--ink); }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn-primary:hover { background: var(--needle); border-color: var(--needle); color: #fff; }
.btn .arr { transition: transform .18s ease; }
.btn:hover .arr { transform: translateX(3px); }

/* ---------- reveal primitives --------------------------------------------- */
html.ready [data-reveal] { visibility: hidden; }
html.ready [data-reveal].is-in { visibility: visible; }
.w { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .16em; margin-bottom: -.16em; }
.w > span { display: inline-block; will-change: transform; }

/* ---------- nav ----------------------------------------------------------- */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  height: 60px;
  display: flex; align-items: center; gap: var(--s5);
  padding-inline: var(--gut);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .25s ease, background .25s ease;
}
.nav.is-stuck { border-bottom-color: var(--line); }
.brand { display: inline-flex; align-items: center; gap: var(--s2); font-weight: 700; font-size: 15px; font-variation-settings: 'wdth' 112; letter-spacing: -.025em; }
.brand .dot { width: 10px; height: 10px; background: var(--needle); border-radius: 1px; }
.nav-links { display: flex; align-items: center; gap: var(--s5); margin-left: auto; }
.nav-links a:not(.btn) { font-size: 13.5px; font-weight: 500; color: var(--dim); transition: color .18s ease; }
.nav-links a:not(.btn):hover { color: var(--ink); }
.nav-links .btn { height: 34px; font-size: 13px; }

/* ---------- the device ---------------------------------------------------- */
/* One host, fixed, re-posed by scroll. pm-phone3d parks its canvas on <body>
   and re-aims it at this element's live rect every frame, so a fixed host with
   a transform is exactly what it wants. */
#phone-host {
  position: fixed;
  left: 50%; top: 50%;
  width: var(--phone-w);
  aspect-ratio: 392 / 812;
  /* --ph-y is the hero->stage slide; --ph-lift is the exit drift after the
     pin releases. Two variables so the two triggers never fight over one. */
  transform: translate(-50%, -50%)
             translate(var(--ph-x, 0px), calc(var(--ph-y, 0px) + var(--ph-lift, 0px)))
             scale(var(--ph-s, 1));
  z-index: 5;
  pointer-events: none;
  opacity: var(--ph-o, 0);
  will-change: transform, opacity;
}
#phone-host .fallback {
  position: absolute; inset: 0;
  border-radius: 11.5%/5.5%;
  overflow: hidden;
  background: #0B0E13;
  box-shadow: 0 34px 80px rgba(21,25,26,.20), 0 4px 14px rgba(21,25,26,.08);
}
#phone-host .fallback img { width: 100%; height: 100%; object-fit: cover; }
#phone-host.webgl .fallback { opacity: 0; transition: opacity .5s ease; }

/* the two anchors the fixed device flies between.
   `position: relative` matters: the tappable phone is absolutely positioned
   against this slot. Without it, it centred on `.hero` instead of the column. */
.ph-slot { position: relative; aspect-ratio: 392 / 812; width: 100%; }

/* ---------- hero ---------------------------------------------------------- */
.hero { position: relative; padding: 128px 0 var(--s9); overflow: clip; }
/* the survey hatch — a faint drafted ground, not a gradient blob */
.hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image: repeating-linear-gradient(112deg, transparent 0 34px, rgba(21,25,26,.028) 34px 35px);
  mask-image: linear-gradient(180deg, rgba(0,0,0,.85), transparent 88%);
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,.85), transparent 88%);
}
.hero-grid {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) var(--phone-w);
  gap: clamp(32px, 6vw, 104px);
  align-items: center;
}
.hero-copy { max-width: none; }
.hero .h1 { margin-bottom: var(--s5); max-width: 13ch; }
.hero .lede { margin-bottom: var(--s6); max-width: 46ch; }
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* ---------- the readout strip -------------------------------------------- */
/* Data-strip family. Compact, mono, hairline-separated — the panel of gauges
   under the windscreen, not four marketing cards. */
.readout { border-block: 1px solid var(--line); background: var(--face); }
.readout-grid { display: grid; grid-template-columns: repeat(5, 1fr); }
.readout-cell { padding: var(--s6) var(--s5) var(--s5); border-left: 1px solid var(--line-2); }
.readout-cell:first-child { border-left: 0; padding-left: 0; }
.readout-cell .k { font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--dimmer); }
.readout-cell .v { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: clamp(24px, 2.5vw, 34px); font-weight: 500; letter-spacing: -.045em; margin-top: var(--s2); line-height: 1; }
.readout-cell .d { font-size: 12.5px; color: var(--dim); margin-top: var(--s3); line-height: 1.45; max-width: 30ch; }
.readout-cell .bar { height: 2px; background: var(--line-2); margin-top: var(--s4); position: relative; }
.readout-cell .bar i { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--needle); }

/* ---------- section furniture --------------------------------------------- */
/* more space above a heading than below it */
.sec { padding: 112px 0 var(--s9); position: relative; }
/* The stage releases with the log still on screen and ~400px of empty paper
   between it and this heading — a whole scroll of nothing. The pin block
   already supplies the breathing room, so this section does not need a
   second helping of it. */
#accuracy { padding-top: var(--s7); }
.sec-head { max-width: 46ch; margin-bottom: var(--s8); }
.sec-head .stamp { margin-bottom: var(--s5); }
.sec-head .h2 { margin-bottom: var(--s5); }

/* ---------- the stage (pinned, scrubbed) ---------------------------------- */
/* Phone LEFT, work-log RIGHT. Each chapter's copy sits above a log that
   accumulates a stamped line as each step completes — so the section is one
   composition that fills in, not six identical rows. */
.stage { position: relative; }
.stage-pin { height: 100svh; display: flex; align-items: center; overflow: hidden; }
.stage-grid {
  display: grid;
  grid-template-columns: var(--phone-w) minmax(0, 1fr);
  gap: clamp(40px, 7vw, 120px);
  align-items: center;
  width: 100%;
}
.stage-right { position: relative; min-height: 60svh; display: flex; flex-direction: column; justify-content: center; }

/* Tallest chapter panel measures 305px (see sr.mjs). At 300 the longest
   one ate into the gap above the log while the shortest left a 100px hole,
   so the distance between the copy and the log changed chapter to chapter.
   Sized to the tallest, with the gap below tightened to match. */
.panels { position: relative; min-height: 312px; }
.panel {
  position: absolute; inset: 0 auto auto 0; width: 100%;
  will-change: transform, opacity;
}
.panel .n { font-family: var(--mono); font-size: 11px; color: var(--needle); letter-spacing: .1em; }
.panel .h3 { margin: var(--s3) 0 var(--s4); max-width: 15ch; }
.panel p { color: var(--ink-2); font-size: 15.5px; line-height: 1.55; max-width: 44ch; }
.panel ul { margin-top: var(--s5); display: grid; gap: var(--s2); }
.panel li { position: relative; padding-left: var(--s5); font-size: 13.5px; color: var(--dim); }
.panel li::before { content: ''; position: absolute; left: 0; top: .62em; width: 8px; height: 1px; background: var(--needle); }

/* the accumulating log */
.log { margin-top: var(--s6); border-top: 1px solid var(--line); }
.log li {
  display: grid; grid-template-columns: 1fr auto; gap: var(--s4);
  align-items: baseline;
  padding: var(--s3) 0; border-bottom: 1px solid var(--line-2);
  font-size: 13px; color: var(--dimmer);
  opacity: .34; transition: opacity .35s ease, color .35s ease;
}
.log li .s { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; }
.log li.on { opacity: 1; color: var(--ink); }
.log li.on .s { color: var(--needle); }
.log li.done { opacity: 1; color: var(--dim); }
.log li.done .s { color: var(--dim); }

.stage-count { position: absolute; right: var(--gut); bottom: var(--s7); font-family: var(--mono); font-size: 11px; color: var(--dimmer); font-variant-numeric: tabular-nums; }
.stage-count b { color: var(--ink); font-weight: 500; }
/* ---------- the stage on a phone ------------------------------------------ */
/* One device, not six. It sticks under the nav and its screen changes as the
   six steps scroll past it — the same idea as the pinned desktop stage, done
   with position:sticky instead of a pin, because a fixed-position phone plus
   a scrolling page is exactly the combination that fights with iOS Safari's
   collapsing toolbar. */
.stage-mobile { display: none; }
.sm-sticky {
  position: sticky; top: 60px; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
  /* Full-bleed paper behind the device. A gradient that went transparent
     under the phone let the next step's copy scroll up THROUGH it and read
     straight across the screenshot. The ground is opaque for the whole
     device and only feathers out in the last 26px. */
  margin-inline: calc(var(--gut) * -1);
  padding: 0 var(--gut) 26px;
  background: var(--paper);
  -webkit-mask-image: linear-gradient(#000 calc(100% - 26px), transparent);
          mask-image: linear-gradient(#000 calc(100% - 26px), transparent);
}
/* Sized against viewport HEIGHT, not just width — the constraint on a phone
   is vertical. At 390x844 the width-only rule made the device 226px wide, so
   the sticky block stood 516px tall: 61% of the viewport, leaving 268px for
   the step's heading, lede and three bullets, which do not fit in it
   (measured 2026-09-01). The 21svh term caps the block near 425px and gives
   the copy ~419px. Keep all three terms: vw still governs a wide short
   window, svh governs every real phone. */
.sm-phone { width: min(210px, 54vw, 21svh); }
.sm-body {
  position: relative; border-radius: 12.5%/6%; overflow: hidden;
  background: #0B0E13; border: 5px solid #2A2F38;
  box-shadow: 0 24px 54px rgba(21,25,26,.18), 0 3px 10px rgba(21,25,26,.07);
}
/* every screen stacked in the same box; the first one sizes it, the rest are
   absolutely positioned on top and cross-fade */
.sm-screen { width: 100%; height: auto; display: block; opacity: 0; transition: opacity .34s ease; }
.sm-screen:not(:first-child) { position: absolute; inset: 0; }
.sm-screen.on { opacity: 1; }
.sm-step { margin-top: var(--s4); font-size: 11px; color: var(--dimmer); font-variant-numeric: tabular-nums; letter-spacing: .12em; }
.sm-step b { color: var(--needle); font-weight: 500; }

.sm-item { padding: var(--s6) 0 var(--s8); border-top: 1px solid var(--line); }
.sm-item:first-child { border-top: 0; }
.sm-item .h3 { margin: var(--s4) 0 var(--s3); }
/* Enough room that one step is what you are reading when its screen is up.
   Less than this and two steps share the viewport, so the phone swaps while
   you are still mid-sentence on the previous one. */
.sm-item { min-height: 46svh; }
.mob-list { margin-top: var(--s4); display: grid; gap: var(--s2); }
.mob-list li { position: relative; padding-left: var(--s5); font-size: 13.5px; color: var(--dim); }
.mob-list li::before { content: ''; position: absolute; left: 0; top: .62em; width: 8px; height: 1px; background: var(--needle); }

/* ---------- the live valuation -------------------------------------------- */
/* Ledger family. One real address, the price resolving digit by digit and the
   comparables arriving ranked — all scrubbed off scroll. */
.val { background: var(--face); border: 1px solid var(--line); }
.val-head {
  display: flex; flex-wrap: wrap; gap: var(--s5); justify-content: space-between; align-items: flex-end;
  padding: var(--s6); border-bottom: 1px solid var(--line);
}
.val-head .addr { font-family: var(--mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase; color: var(--dimmer); }
.val-price { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: clamp(38px, 5.4vw, 68px); font-weight: 500; letter-spacing: -.05em; line-height: 1; margin-top: var(--s3); }
.val-price em { font-style: normal; color: var(--line); }
.val-price { transition: none; }
.val-count { text-align: right; }
.val-count .v { font-family: var(--mono); font-size: 22px; font-variant-numeric: tabular-nums; margin-top: var(--s2); }
.val-count .v s { text-decoration: none; color: var(--line); }

.val-rows { padding: var(--s3) var(--s6) var(--s6); }
.val-row {
  display: grid; grid-template-columns: minmax(0,1fr) 96px 120px 46px; gap: var(--s4);
  align-items: center; padding: var(--s3) 0; border-bottom: 1px solid var(--line-2);
  font-size: 13.5px;
  opacity: 0;
}
.val-row:last-child { border-bottom: 0; }
.val-row .a { color: var(--ink); font-weight: 500; letter-spacing: -.01em; }
.val-row .p { font-family: var(--mono); font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--dim); text-align: right; }
.val-row .b { height: 3px; background: var(--line-2); position: relative; }
.val-row .b i { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--ink); }
.val-row .s { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; color: var(--dimmer); }
.val-foot { padding: var(--s5) var(--s6); border-top: 1px solid var(--line); background: var(--paper); font-size: 12.5px; color: var(--dim); }
.val-foot b { color: var(--ink); font-weight: 600; }

/* ---------- the gauge ----------------------------------------------------- */
/* Gauge family. The signature object of the world: a real scale with real
   ticks, the ±1.75% band, and a needle. */
.gauge { margin-top: var(--s9); display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: clamp(32px, 5vw, 80px); align-items: end; }
.gauge-face { background: var(--face); border: 1px solid var(--line); padding: var(--s7) var(--s6) var(--s5); }
.gauge-lab { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--dimmer); }
.gauge-scale { position: relative; height: 84px; margin: var(--s5) 0 var(--s3); }
.gauge-band { position: absolute; bottom: 22px; height: 30px; background: var(--needle-soft); left: 50%; width: 0; transform: translateX(-50%); }
.gauge-ticks { position: absolute; inset: auto 0 22px; height: 30px; display: flex; justify-content: space-between; }
.gauge-ticks i { width: 1px; background: var(--line); height: 9px; align-self: flex-end; }
.gauge-ticks i.maj { height: 20px; background: #B9BFB9; }
.gauge-needle { position: absolute; left: 50%; bottom: 14px; width: 2px; height: 48px; background: var(--needle); transform: translateX(-50%); }
.gauge-needle::after { content: ''; position: absolute; top: -5px; left: -3px; width: 8px; height: 8px; background: var(--needle); border-radius: 50%; }
.gauge-axis { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 11px; color: var(--dimmer); font-variant-numeric: tabular-nums; border-top: 1px solid var(--line); padding-top: var(--s3); }
.gauge-note { font-size: 14px; color: var(--ink-2); line-height: 1.55; }
.gauge-note b { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 500; }
.gauge-note .big { display: block; font-family: var(--mono); font-size: clamp(30px, 3.6vw, 46px); font-weight: 500; letter-spacing: -.05em; color: var(--ink); margin-bottom: var(--s4); }

/* ---------- coverage ------------------------------------------------------ */
.cov-grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: clamp(32px, 5vw, 88px); align-items: center; }
/* This section's heading lives beside the map, not above it. It is the one
   place on the page where the instrument leads and the argument follows,
   which is what stops accuracy / coverage / specs reading as three
   identical stacks in a row. */
.cov-copy .h2 { max-width: 15ch; }
.cov-copy .lede { margin-top: var(--s5); max-width: 46ch; }
.mk-lab { margin-top: var(--s7); font-size: 9.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--dimmer); display: flex;
  justify-content: space-between; align-items: baseline; }
.mk-lab b { color: var(--needle); font-weight: 500; font-variant-numeric: tabular-nums; }
.mk-note { margin-top: var(--s5); font-size: 13px; line-height: 1.5; color: var(--dim); max-width: 52ch; }
/* the wrapper, not the <svg>, is what stops the mainland geometry from
   widening the document on a narrow screen. */
.map-box { overflow: hidden; border: 1px solid var(--line); background: var(--face); }
#map { width: 100%; aspect-ratio: 400 / 314; }
#map .land { fill: #E4E7E1; stroke: #CDD2CA; stroke-width: .7; }
#map .isle { fill: var(--paper); stroke: var(--ink); stroke-width: 1.1; }
#map .pin { fill: var(--needle); }
#map .halo { fill: none; stroke: var(--needle); opacity: .45; }
#map text { font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em; fill: var(--dim); text-transform: uppercase; }
/* Column flow, not row flow. Seven markets in two row-flowed columns left
   Campbell River stranded alone on the LEFT of a fourth row, which reads
   as a mistake. Filling down means the short column is the right-hand
   one, which reads as a list. */
.mk-list { display: grid; margin-top: var(--s3) !important; grid-template-columns: repeat(2, minmax(0,1fr));
  grid-template-rows: repeat(4, auto); grid-auto-flow: column;
  gap: 0 clamp(24px, 3vw, 48px); border-top: 1px solid var(--line); }
.mk-list span { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s3) 0; border-bottom: 1px solid var(--line-2); font-size: 14px; font-weight: 500; }
.mk-list span::before { content: ''; width: 5px; height: 5px; background: var(--needle); border-radius: 50%; flex: none; }

/* ---------- specs --------------------------------------------------------- */
/* Grouped-cluster family. Three clusters, one divider each — not a hairline
   under every row. */
.spec-groups { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: clamp(24px, 3vw, 56px); }
.spec-group { border-top: 2px solid var(--ink); padding-top: var(--s5); }
/* The cluster heading sits ON the 2px rule with its own row count at the
   far end, the way a printed spec sheet numbers its sections. It is the
   cheapest thing that turns three uniform stacks into a document. */
.spec-group > h3 { font-family: var(--mono); font-size: 10px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink); margin-bottom: var(--s4);
  display: flex; justify-content: space-between; align-items: baseline; }
.spec-group > h3 i { font-style: normal; color: var(--needle); font-variant-numeric: tabular-nums; letter-spacing: .05em; }
.spec { padding: var(--s3) 0 var(--s4); }
.spec + .spec { border-top: 1px solid var(--line-2); }
.spec .k { font-family: var(--mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--dimmer); }
.spec .v { font-size: 16px; font-weight: 650; letter-spacing: -.02em; margin-top: 2px; }
.spec .n { font-size: 13px; color: var(--dim); margin-top: var(--s1); line-height: 1.45; }

/* ---------- cta / footer -------------------------------------------------- */
.cta { padding: var(--s10) 0; border-top: 1px solid var(--line); text-align: center; }
.cta .h2 { max-width: 18ch; margin-inline: auto; }
.cta .lede { margin: var(--s5) auto var(--s7); text-align: center; }
.cta .hero-cta { justify-content: center; }
.cta-zero { font-family: var(--mono); font-size: clamp(44px, 7vw, 92px); font-weight: 500; letter-spacing: -.06em; line-height: 1; color: var(--line); margin-bottom: var(--s6); }

.foot { border-top: 1px solid var(--line); padding: var(--s7) 0; }
.foot-grid { display: flex; align-items: center; gap: var(--s5); flex-wrap: wrap; font-size: 13px; color: var(--dim); }
.foot-grid .sp { flex: 1 1 auto; }
.foot-grid a:not(.brand):hover { color: var(--ink); }

/* ---------- responsive ---------------------------------------------------- */
@media (max-width: 1080px) {
  .readout-grid { grid-template-columns: repeat(3, 1fr); }
  .readout-cell:nth-child(4) { border-left: 0; padding-left: 0; }
  .readout-cell:nth-child(-n+3) { border-bottom: 1px solid var(--line-2); }
  .spec-groups { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .gauge { grid-template-columns: 1fr; align-items: start; }
}
@media (max-width: 900px) {
  .hero { padding-top: 104px; padding-bottom: var(--s8); min-height: 0; }
  .hero-grid { grid-template-columns: 1fr; }
  .hero-copy { max-width: none; }
  .cov-grid { grid-template-columns: 1fr; }
  .stage-pin { display: none; }
  .stage-mobile { display: block; }
  #phone-host { display: none; }
  .nav-links a:not(.btn) { display: none; }
  .val-row { grid-template-columns: minmax(0,1fr) 78px 46px; }
  .val-row .b { display: none; }
}
@media (max-width: 640px) {
  .readout-grid { grid-template-columns: repeat(2, 1fr); }
  .readout-cell:nth-child(3) { border-left: 0; padding-left: 0; }
  .readout-cell:nth-child(-n+4) { border-bottom: 1px solid var(--line-2); }
  .spec-groups { grid-template-columns: 1fr; }
  .mk-list { grid-template-columns: 1fr; grid-template-rows: none; grid-auto-flow: row; }
  .sec { padding: var(--s9) 0; }
}
@media (max-width: 900px) { #slotHero { aspect-ratio: auto; } #slotStage { display: none; } }

@media (prefers-reduced-motion: reduce) {
  html.ready [data-reveal] { visibility: visible !important; }
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
/* ---------- demo page -----------------------------------------------------
   /demo and /demo/thanks. These pages do NOT load js/site.js, so nothing here
   may depend on a reveal class being added — everything is visible as written. */

body.page { padding-top: 68px; }              /* the nav is fixed and always stuck here */

/* `.form` sets display:flex, which BEATS the hidden attribute's UA display:none
   — without this the submitted form stayed on screen under the confirmation. */
[hidden] { display: none !important; }

.demo-page { padding-block: clamp(44px, 6vw, 84px) clamp(72px, 9vw, 120px); }
.demo-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: clamp(36px, 5vw, 88px);
  align-items: start;
}
@media (max-width: 960px) { .demo-grid { grid-template-columns: 1fr; gap: 44px; } }

.demo-intro .h1 { margin-top: 18px; font-size: clamp(34px, 3.8vw, 50px); max-width: 13em; }
.demo-intro .lede { margin-top: 20px; max-width: 42ch; }

.demo-steps { margin-top: clamp(30px, 3.4vw, 44px); display: flex; flex-direction: column; gap: 0; }
.demo-steps li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 16px;
  padding: 18px 0; border-top: 1px solid var(--line); align-items: start; }
.demo-steps li:last-child { border-bottom: 1px solid var(--line); }
.demo-steps .i { font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em; color: var(--accent); padding-top: 4px; }
.demo-steps b { font-weight: 600; font-size: 15.5px; letter-spacing: -.01em; }
.demo-steps p { margin-top: 5px; font-size: 14px; color: var(--dim); line-height: 1.6; max-width: 40ch; }

.demo-note { margin-top: 26px; }
.demo-note p { font-size: 14px; color: var(--dim); line-height: 1.6; max-width: 42ch; }
.demo-note b { color: var(--ink); font-weight: 600; }
.demo-note .small { margin-top: 12px; }
.demo-note a, .f-fine a, .form-done a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* the card */
.form {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: clamp(22px, 2.6vw, 34px);
  box-shadow: 0 1px 2px rgba(21,25,26,.05), 0 14px 34px -10px rgba(21,25,26,.10);
  display: flex; flex-direction: column; gap: 16px;
}
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.f-row { display: grid; gap: 16px; }
.f-2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 520px) { .f-2 { grid-template-columns: 1fr; } }

.f { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.f > span { font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--dimmer); }
.f > span i { font-style: normal; text-transform: none; letter-spacing: .04em; opacity: .8; }

.f input, .f select, .f textarea {
  font-family: var(--sans); font-size: 15.5px; color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 11px 13px;
  width: 100%;
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
  -webkit-appearance: none; appearance: none;
}
.f textarea { resize: vertical; min-height: 84px; line-height: 1.5; }
.f input::placeholder, .f textarea::placeholder { color: var(--dimmer); }
.f input:hover, .f select:hover, .f textarea:hover { border-color: rgba(16,20,24,.3); }
.f input:focus, .f select:focus, .f textarea:focus {
  outline: none; background: var(--panel);
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(43,84,212,.14);
}
/* the browser default arrow disappears with appearance:none, so draw one */
.f select {
  padding-right: 36px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238A93A0' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
}
.f select:invalid { color: var(--dimmer); }        /* the disabled placeholder option */

.f-submit { height: 48px; justify-content: center; margin-top: 4px; font-size: 15.5px; }
.f-submit[disabled] { opacity: .6; pointer-events: none; }
.f-fine { font-size: 12.5px; color: var(--dimmer); line-height: 1.6; }

/* the confirmation, inline on /demo and standalone on /demo/thanks */
.form-done { text-align: center; padding: clamp(34px, 5vw, 60px) clamp(20px, 3vw, 40px); }
.form-done .tick {
  width: 46px; height: 46px; margin: 0 auto 20px; border-radius: 50%;
  display: grid; place-items: center; font-size: 20px;
  background: rgba(14,159,110,.12); color: var(--good);
}
.form-done .lede { margin: 14px auto 0; max-width: 40ch; }
.form-done .small { margin-top: 20px; }
.thanks-page { display: grid; place-items: center; min-height: 62svh; }

/* iOS Safari zooms the viewport when a focused field is under 16px. */
@media (max-width: 820px) {
  .f input, .f select, .f textarea { font-size: 16px; }
}


/* ---------- the tappable phone --------------------------------------------
   DOM, so it can be pressed and stays crisp; it never animates. The WebGL
   device takes over the moment the hero starts sliding toward the stage.
   Hotspots are percentages of the 784x1624 screenshots, so they scale. */
.tapphone {
  position: absolute; left: 50%; top: 50%;
  width: var(--phone-w);
  transform: translate(-50%, -50%);
  will-change: opacity;
}
.tp-body {
  position: relative;
  border-radius: 12.5%/6%;
  overflow: hidden;
  background: #0B0E13;
  border: 5px solid #2A2F38;
  box-shadow: 0 34px 80px rgba(21,25,26,.20), 0 4px 14px rgba(21,25,26,.08),
              inset 0 0 0 1px rgba(255,255,255,.10);
}
.tp-screen { width: 100%; height: auto; display: block; -webkit-user-select: none; user-select: none; }
.tp-hot { position: absolute; inset: 0; }
.tp-btn {
  position: absolute; margin: 0; padding: 0;
  border: 0; background: transparent; border-radius: 9px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, box-shadow .16s ease;
}
/* A faint resting outline so it is obvious which parts of the screenshot are
   live. Without it people tap the dead space between controls and conclude
   the phone is a picture. */
.tp-btn { box-shadow: inset 0 0 0 1px rgba(21,25,26,.045); }
.tp-btn.is-tab { box-shadow: none; }   /* the tab bar already reads as a tab bar */
.tp-btn:hover   { background: rgba(194,69,43,.12); box-shadow: inset 0 0 0 1.5px rgba(194,69,43,.55); }
.tp-btn:active  { background: rgba(194,69,43,.20); }
.tp-btn:focus-visible { outline: none; background: rgba(194,69,43,.12); box-shadow: inset 0 0 0 2px var(--needle); }
.tp-btn.is-back { border-radius: 50%; }
.tp-hint {
  margin-top: var(--s4); text-align: center;
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--dimmer);
  transition: opacity .5s ease;
}
.tp-hint.used { opacity: 0; }
@media (max-width: 900px) {
  .tapphone { position: relative; left: auto; top: auto; transform: none;
              width: min(280px, 74%); margin: var(--s7) auto 0; }
}
@media (prefers-reduced-motion: reduce) { .tp-btn { transition: none; } }
