/* =====================================================================
   site.css — Unbuild Lab · Quote Intake Assistant tour

   Built on the Aperture/Unbuild Lab tokens in
   prototype/_ds/aperture-design-system-.../colors_and_type.css.

   House rules this file obeys, from that system's README:
     · One accent (teal), fourteen grays. Color means something.
     · Numbers are the hero — mono, tabular, sized up.
     · Hairline borders instead of shadows on static surfaces.
     · No gradients, no stock photography, no textures, no patterns.
     · 4pt spacing ladder. Off-ladder measurements are bugs.
     · Pills for buttons, 16px cards, three shadow tiers only.
     · Nothing bounces. Over 400ms is ceremony, used once.
   ===================================================================== */

/* ------------------------------------------------ token overrides -------
   Scoped to the sales page. The imported design system is left byte-faithful;
   these are the two places its defaults fail the people this page is for.

   --fg-3 (--ink-400) measures 3.26:1 on white and carries every eyebrow,
   caption and piece of metadata at 10–13px — below the 4.5:1 AA floor, on a
   page read by 45–65 year olds in poor light. Stepping both muted greys one
   rung darker keeps the three-level hierarchy and clears AA at every size.
   --------------------------------------------------------------------- */
:root {
  --fg-2: var(--ink-600);   /* 8.59:1 on white — was 5.99:1 */
  --fg-3: var(--ink-500);   /* 5.99:1 on white — was 3.26:1, failing */

  --success-bg: #E8F7ED;    /* the tint the DS uses but never named */
  --dur-pulse: 1400ms;      /* ambient looping cues, distinct from the five
                               transition durations, which govern transitions */
}

/* ---------------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg-1); overflow-x: hidden; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }
:where(a) { color: var(--blue-500); text-decoration: none; }
:where(a):hover { color: var(--blue-600); }
::selection { background: var(--blue-100); color: var(--blue-700); }

/* The system's focus contract is a 3px --blue-100 ring plus a border shift to
   --blue-500. On white, that ring alone measures 1.23:1 — below the 3:1 floor
   for non-text indicators, i.e. invisible on most of this page. Keeping the
   brand ring and closing it with a --blue-500 hairline satisfies both. */
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--blue-100), 0 0 0 4px var(--blue-500);
  border-color: var(--blue-500);
  border-radius: var(--r-sm);
}
.section--dark :focus-visible, .hero :focus-visible {
  box-shadow: 0 0 0 3px var(--blue-500), 0 0 0 4px var(--blue-100);
}

/* ------------------------------------------------------------- skeleton */
.wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 var(--s-6); }
@media (min-width: 760px)  { .wrap { padding: 0 var(--s-8); } }
@media (min-width: 1100px) { .wrap { padding: 0 var(--s-12); } }

.section { padding: var(--s-16) 0; }
/* #tour used to carry `padding-top: var(--s-16)` here, from when it was its own
   section a third of the way down the page. In the hero it is 64px of nothing
   above the demo, which pushed the whole right column — and with it the bottom
   edge the left column now aligns to — past the fold. */
@media (min-width: 760px) { .section { padding: 96px 0; } }
.section--tight { padding-top: var(--s-12); }
.section--near { background: var(--bg-2); }
.section--dark { background: var(--ink-950); color: var(--ink-0); }

.rule { height: 1px; background: var(--border); border: 0; margin: 0; }

/* ------------------------------------------------------------ type kit */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 10px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-accent);
  display: flex; align-items: center; gap: var(--s-3);
  margin: 0 0 var(--s-4);
}
.eyebrow::after {
  content: ""; flex: 1; height: 1px; background: var(--border); max-width: 120px;
}
.section--dark .eyebrow { color: var(--blue-300); }
.section--dark .eyebrow::after { background: rgba(255,255,255,.14); }

.h-xl { font-size: clamp(34px, 6.2vw, 64px); font-weight: 600; letter-spacing: -.035em; line-height: 1.02; margin: 0; }
.h-lg { font-size: clamp(28px, 4.4vw, 48px); font-weight: 600; letter-spacing: -.03em;  line-height: 1.06; margin: 0; }
.h-md { font-size: clamp(23px, 2.8vw, 32px); font-weight: 600; letter-spacing: -.025em; line-height: 1.12; margin: 0; }
.h-sm { font-size: 22px; font-weight: 600; letter-spacing: -.018em; line-height: 1.2; margin: 0; }

.lede { font-size: 17px; line-height: 1.5; letter-spacing: -.01em; color: var(--fg-2); margin: var(--s-4) 0 0; max-width: 56ch; }
.section--dark .lede { color: var(--ink-300); }
.muted { color: var(--fg-2); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }

/* --------------------------------------------------------------- links */
.link-arrow {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 500;
}
.link-arrow svg { transition: transform var(--dur-fast) var(--ease-standard); }
.link-arrow:hover svg { transform: translateX(3px); }

/* ------------------------------------------------------------- buttons */
.b {
  font-size: 14px; font-weight: 500; letter-spacing: -.005em;
  padding: var(--s-3) var(--s-6); border-radius: var(--r-pill);
  border: 1px solid transparent; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.b:active { transform: scale(.98); }
.b-primary { background: var(--blue-500); color: var(--ink-0); }
.b-primary:hover { background: var(--blue-600); color: var(--ink-0); }
.b-secondary { background: var(--bg-1); color: var(--fg-1); border-color: var(--border-strong); }
.b-secondary:hover { border-color: var(--ink-300); color: var(--fg-1); }
.b-onDark { background: var(--ink-0); color: var(--ink-950); }
.b-onDark:hover { background: var(--ink-50); color: var(--ink-950); }
.b-ghostDark { background: transparent; color: var(--ink-0); border-color: rgba(255,255,255,.24); }
.b-ghostDark:hover { border-color: rgba(255,255,255,.5); color: var(--ink-0); }
.b-lg { font-size: 16px; padding: var(--s-4) var(--s-8); }
.b-sm { font-size: 12px; padding: var(--s-3) var(--s-4); }

/* ------------------------------------------------------------------ nav */
.nav {
  position: fixed; top: var(--s-3); left: 50%; transform: translateX(-50%);
  z-index: 40; width: calc(100% - var(--s-6)); max-width: 1000px;
}
.nav-inner {
  display: flex; align-items: center; gap: var(--s-6);
  padding: 8px 8px 8px var(--s-4);
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: rgba(255,255,255,.82);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  box-shadow: var(--shadow-2);
  transition: background var(--dur-standard) var(--ease-standard),
              border-color var(--dur-standard) var(--ease-standard);
}
.nav-brand { display: inline-flex; align-items: center; gap: var(--s-2); font-weight: 600; font-size: 14px; letter-spacing: -.015em; color: var(--fg-1); }
.nav-brand:hover { color: var(--fg-1); }
.nav-links { display: none; align-items: center; gap: var(--s-6); margin-left: auto; }
@media (min-width: 900px) { .nav-links { display: flex; } }
.nav-links a { font-size: 13px; font-weight: 500; color: var(--fg-2); }
.nav-links a:hover { color: var(--fg-1); }

/* Over the near-black hero and closing CTA the translucent white pill has
   nothing to blur against, so it renders as a flat light slab pasted onto
   the black. Swap to the system's dark pair while it is over a dark section. */
.nav-inner.on-dark {
  background: rgba(28,28,30,.78);
  border-color: rgba(255,255,255,.16);
}
.nav-inner.on-dark .nav-brand { color: var(--ink-0); }
.nav-inner.on-dark .nav-links a { color: var(--ink-300); }
.nav-inner.on-dark .nav-links a:hover { color: var(--ink-0); }
.nav .b { margin-left: auto; }
@media (min-width: 900px) { .nav .b { margin-left: 0; } }

/* ----------------------------------------------------------------- hero */
.hero {
  background: var(--ink-950); color: var(--ink-0);
  padding: 132px 0 var(--s-16);
  position: relative; overflow: hidden;
}
@media (min-width: 760px) { .hero { padding: 168px 0 96px; } }
.hero h1 { color: var(--ink-0); }
.hero-grid { display: grid; gap: var(--s-12); align-items: end; }
@media (min-width: 980px) { .hero-grid { grid-template-columns: 1.35fr 1fr; gap: var(--s-16); } }

.hero-sub { color: var(--ink-300); font-size: 17px; line-height: 1.5; letter-spacing: -.01em; margin: var(--s-6) 0 0; max-width: 46ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-8); }

/* The worked example. Assumptions first, then the number they produce — a big
   figure that fires before its inputs reads as a stat being sold at you. */
.leak {
  border: 1px solid rgba(255,255,255,.14); border-radius: var(--r-lg);
  padding: var(--s-6);
}
.leak-label { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-400); font-family: var(--font-mono); }
.leak-rows { display: flex; flex-direction: column; gap: 0; }
.leak-rows--top { margin-top: var(--s-4); }
.leak-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-4); font-size: 13px; color: var(--ink-300); padding: var(--s-3) 0; border-bottom: 1px solid rgba(255,255,255,.1); }
.leak-row b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 500; color: var(--ink-0); }
.leak-out { padding-top: var(--s-4); }
.leak-out-label { font-size: 13px; color: var(--ink-300); }
.leak-num {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: clamp(40px, 7vw, 56px); font-weight: 700; letter-spacing: -.03em;
  line-height: 1; margin: var(--s-2) 0 0; color: var(--ink-0);
}
.leak-foot { font-size: 12px; color: var(--ink-400); line-height: 1.5; margin: var(--s-4) 0 0; }
.leak-foot a { color: var(--blue-300); }
.leak-foot a:hover { color: var(--ink-0); }

/* fit filter next to the ask, so the founder's calendar stays useful */
.cta-fit {
  margin: var(--s-6) 0 0; font-size: 13px; line-height: 1.55;
  color: var(--ink-400); max-width: 48ch;
}

/* localhost-only reminder that the booking link is still a placeholder */
.devbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  background: var(--warning-ink); color: #fff;
  padding: 10px var(--s-4); font-size: 12px; line-height: 1.4; text-align: center;
}
.devbar code { background: rgba(255,255,255,.16); color: #fff; }

/* --------------------------------------------------------------- stakes */
.stakes { display: grid; gap: var(--s-8); }
@media (min-width: 860px) { .stakes { grid-template-columns: repeat(3, 1fr); gap: var(--s-12); } }
/* four steps in a three-column grid left the last one orphaned on its own row */
@media (min-width: 640px) { .stakes--4 { grid-template-columns: repeat(2, 1fr); gap: var(--s-8) var(--s-12); } }
@media (min-width: 1100px) { .stakes--4 { grid-template-columns: repeat(4, 1fr); gap: var(--s-8); } }
.stake { border-top: 1px solid var(--border); padding-top: var(--s-4); }
.stake-num { font-family: var(--font-mono); font-size: 40px; font-weight: 700; letter-spacing: -.03em; font-variant-numeric: tabular-nums; line-height: 1.05; }
.stake h3 { font-size: 15px; font-weight: 600; letter-spacing: -.01em; margin: var(--s-3) 0 var(--s-2); }
.stake p { color: var(--fg-2); margin: 0; font-size: 14px; line-height: 1.5; }

/* ------------------------------------------------------------ calculator */
.calc { display: grid; gap: var(--s-8); align-items: start; }
@media (min-width: 900px) { .calc { grid-template-columns: 1fr 1fr; gap: var(--s-16); } }

.calc-controls { display: flex; flex-direction: column; gap: var(--s-8); }
.ctrl-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-4); margin-bottom: var(--s-3); }
.ctrl-head label { font-size: 14px; font-weight: 500; letter-spacing: -.005em; }
.ctrl-head output { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.ctrl-hint { font-size: 12px; color: var(--fg-3); margin: var(--s-2) 0 0; }

input[type="range"].slider {
  appearance: none; -webkit-appearance: none;
  width: 100%; height: 3px; border-radius: var(--r-pill);
  background: var(--ink-100); outline: none; margin: 0; cursor: pointer;
}
input[type="range"].slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: var(--s-6); height: var(--s-6); border-radius: 50%;
  background: var(--bg-1); border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-1); cursor: grab;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
input[type="range"].slider::-webkit-slider-thumb:hover { border-color: var(--blue-500); }
input[type="range"].slider::-moz-range-thumb {
  width: var(--s-6); height: var(--s-6); border-radius: 50%;
  background: var(--bg-1); border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-1); cursor: grab;
}
input[type="range"].slider:focus-visible { box-shadow: 0 0 0 3px var(--blue-100); }

.calc-out {
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--bg-1); padding: var(--s-8);
}
.calc-out-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--fg-3); }
.calc-big {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: clamp(38px, 6vw, 52px); font-weight: 700; letter-spacing: -.03em;
  line-height: 1; margin: var(--s-3) 0 var(--s-6);
}
.calc-line { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-4); padding: var(--s-3) 0; border-top: 1px solid var(--border); font-size: 14px; }
.calc-line span { color: var(--fg-2); }
.calc-line b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 500; }
.calc-payback {
  margin-top: var(--s-6); padding: var(--s-4);
  background: var(--success-bg); color: var(--success-ink);
  border-radius: var(--r-md); font-size: 14px; line-height: 1.5;
  display: flex; gap: 10px; align-items: flex-start;
}
.calc-payback svg { flex: none; margin-top: 2px; }
.calc-payback b { font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ tour */
.tour { display: grid; gap: var(--s-8); align-items: start; }
@media (min-width: 1040px) { .tour { grid-template-columns: 360px 1fr; gap: var(--s-16); } }

/* narration rail — the tour drives itself, so these are compact jump targets
   rather than scroll-linked chapters */
.acts { display: flex; flex-direction: column; gap: 0; }
.act {
  padding: var(--s-4) 0 var(--s-4) var(--s-6);
  border-left: 1px solid var(--border);
  position: relative; cursor: pointer; background: none;
  border-top: 0; border-right: 0; border-bottom: 0;
  text-align: left; width: 100%; display: block;
  transition: border-color var(--dur-standard) var(--ease-standard);
}
.act::before {
  content: attr(data-num);
  position: absolute; left: 0; top: var(--s-4); transform: translateX(-50%);
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--bg-1); border: 1px solid var(--border);
  color: var(--fg-3); font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  transition: all var(--dur-standard) var(--ease-standard);
}
.act:first-child::before { top: var(--s-3); }
.act h3 { font-size: 17px; font-weight: 600; letter-spacing: -.014em; line-height: 1.3; margin: 0; color: var(--fg-2); transition: color var(--dur-standard) var(--ease-standard); }
.act p { font-size: 14px; line-height: 1.5; color: var(--fg-3); margin: var(--s-2) 0 0; max-width: 46ch; display: none; }
.act.is-active { border-left-color: var(--blue-500); }
.act.is-active::before { background: var(--blue-500); border-color: var(--blue-500); color: var(--ink-0); }
.act.is-active h3 { color: var(--fg-1); }
.act.is-active p { display: block; color: var(--fg-2); }
.act.is-done::before { background: var(--bg-3); border-color: var(--border-strong); color: var(--fg-2); }
.act:hover h3 { color: var(--fg-1); }

/* A caption, not a card. It used to be a black slab carrying a full argument,
   which competed with the device for attention and cost the demo the height it
   needed. The argument now lives in the end-of-demo receipt; this just names
   the step. */
.stage-note {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: baseline; gap: var(--s-2);
  font-size: 13px; line-height: 1.3; color: var(--fg-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: noteIn var(--dur-fast) var(--ease-enter) both;
}
.stage-note > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.stage-note b { font-weight: 600; }
.stage-note[hidden] { display: none; }
.stage-note-slot { flex: none; min-height: 76px; width: 100%; display: flex; justify-content: center; align-items: flex-start; }
@media (max-width: 640px) { .stage-note-slot { min-height: 104px; } }
.note-cta {
  display: block; margin-top: var(--s-2); padding-top: var(--s-2);
  border-top: 1px solid rgba(255,255,255,.16);
  color: var(--ink-300); font-size: 12px;
}
.note-cta i { font-style: italic; }
.note-cta button {
  pointer-events: auto;
  background: none; border: 0; padding: 0; margin-left: 4px;
  color: var(--blue-300); font-weight: 500; font-size: 12px;
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.note-cta button:hover { color: var(--ink-0); }

/* end-of-tour payoff — the ask, at the moment of most conviction */
.stage-end {
  position: absolute; inset: 0; z-index: 6;
  background: rgba(249,249,251,.86);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: var(--s-6);
  animation: noteIn var(--dur-deliberate) var(--ease-enter) both;
}
.stage-end[hidden] { display: none; }
.stage-end-in {
  background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3); padding: var(--s-8);
  max-width: 420px; text-align: left;
  /* This card is a light panel wherever it lands. On the demo-first hero the
     stage around it is set to white text so it can sit on the dark section,
     and the headline — which sets no colour of its own — inherited that and
     disappeared into the card. */
  color: var(--fg-1);
}
.stage-end-in h3 { margin: 0 0 var(--s-3); }
.stage-end-in p { color: var(--fg-2); margin: 0; font-size: 14px; line-height: 1.55; }
.stage-end-actions { display: flex; flex-direction: column; gap: var(--s-2); margin-top: var(--s-6); }
.stage-end-actions .b { width: 100%; }
.note-k {
  font-family: var(--font-mono); font-size: 9px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--blue-500); white-space: nowrap;
}
@keyframes noteIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .stage-note { animation-duration: 80ms; } }

/* stage */
.stage-col { position: relative; display: flex; flex-direction: column; }
/* The stage is a column: device on top, narration in a reserved row beneath.
   The note used to float over the device and consistently landed on the very
   control or total it was describing. */
.stage {
  border: 1px solid var(--border); border-radius: var(--r-xl);
  background: var(--bg-2);
  /* A light panel inside a dark section. Without this reset, text that does not
     set its own colour inherits the hero's white and vanishes — which is what
     happened to the end card's headline. */
  color: var(--fg-1);
  padding: var(--s-6);
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-4);
  min-height: 0;   /* every context sets its own height */
  transition: border-color var(--dur-standard) var(--ease-standard),
              box-shadow var(--dur-standard) var(--ease-standard);
}
@media (max-width: 640px) { .stage { padding: var(--s-6) var(--s-3) var(--s-3); height: 600px; } }

/* Landscape phones: 600px of stage in a 390px viewport means no act is ever
   fully visible. Shrink the whole rig rather than let it overflow. */
@media (max-height: 480px) and (orientation: landscape) {
  .stage { height: 320px; padding: var(--s-4); }
  .phone { width: 240px; }
}

 /* A flow row, not an overlay: the laptop frame is wide enough to reach the
    stage's top-left corner and was sitting under this label. */
.stage-hint {
  flex: none; align-self: flex-start; margin-bottom: -4px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--fg-3);
  display: flex; align-items: center; gap: 6px; z-index: 3;
}
.stage-hint i { width: 6px; height: 6px; border-radius: 50%; background: var(--blue-500); display: block; }
.stage-hint.is-live i { animation: pulse var(--dur-pulse) var(--ease-standard) infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* device frames */
/* The stage owns the height; the device fills whatever the narration leaves.
   Filling it also makes the phone taller than it is wide by a sensible margin,
   which reads more like a phone than the stubby frame a fixed height gave. */
.stage-body {
  flex: 1 1 auto; min-height: 0; width: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-3);
}
.devices {
  position: relative; flex: 1 1 auto; min-height: 0; width: 100%;
  display: flex; align-items: stretch; justify-content: center;
}
.device { display: flex; min-width: 0; }
/* The phone is a fixed width; the laptop should take everything going. Without
   this the laptop's own width:100% resolves against a content-sized flex item
   and collapses to about 60% of the panel. */
.stage.on-phone .device { flex: 0 0 auto; }
.stage.on-laptop .device { flex: 1 1 auto; width: 100%; }
.phone, .laptop { display: flex; flex-direction: column; min-height: 0; }
.phone-screen, .laptop-screen { flex: 1 1 auto; min-height: 0; }

.device {
  transition: opacity var(--dur-deliberate) var(--ease-standard),
              transform var(--dur-deliberate) var(--ease-standard);
  will-change: opacity, transform;
}
.device[hidden] { display: none; }
.device.is-away { opacity: 0; transform: scale(.96); pointer-events: none; position: absolute; }

/* No bezel. The black frame was 20px of chrome in each direction and it made
   the screen a picture of a phone rather than the thing itself; a hairline and
   a soft shadow read as a screen without spending the room. The laptop keeps
   its browser bar, because the URL is the point — this runs on your site. */
.phone {
  width: 320px; max-width: 100%;
  border: 1px solid var(--border); border-radius: var(--r-xl);
  background: var(--bg-1); box-shadow: var(--shadow-2);
  overflow: hidden; position: relative;
}
/* Never scrolls. Every act is laid out to fit, and fitScreen() shrinks the
   whole screen if one ever does not — a viewer must see the entire device in
   one look, or the demo stops explaining itself. */
.phone-screen {
  overflow: hidden; background: var(--bg-2); position: relative;
}
/* No min-height here: a .scr pinned to 100% of the frame reports the frame's
   own height back to fitScreen, which then shrinks against a number that never
   changes and walks the zoom down to the floor. */
.phone-screen > .scr { display: block; }
.phone-screen > .scr.is-filling { display: flex; flex-direction: column; min-height: 100%; }
.phone-screen > .scr.is-filling > .ph { flex: 1 1 auto; }
/* An app fills its window — the inbox should not float in the top half of the
   laptop with white below it. */
.laptop-screen > .scr.is-filling { display: flex; flex-direction: column; min-height: 100%; }
.laptop-screen > .scr.is-filling > .con { flex: 1 1 auto; }
.laptop-screen > .scr.is-filling .con-grid { flex: 1 1 auto; }
.phone-screen .ph-foot { position: static; }

.laptop { width: 100%; max-width: 760px; }
.laptop-bar {
  display: flex; align-items: center; gap: 6px;
  padding: 10px var(--s-4);
  background: var(--ink-900); border-radius: 12px 12px 0 0;
}
.laptop-bar i { width: 9px; height: 9px; border-radius: 50%; background: rgba(255,255,255,.22); display: block; }
.laptop-url {
  margin-left: var(--s-3); font-family: var(--font-mono); font-size: 10px;
  color: rgba(255,255,255,.45); letter-spacing: .02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.laptop-screen {
  overflow: hidden; background: var(--bg-1);
  border: 1px solid var(--border); border-top: 0;
  border-radius: 0 0 12px 12px;
  box-shadow: var(--shadow-2);
  position: relative;
}

/* handoff pulse between the two devices */
.handoff {
  position: absolute; inset: 0; pointer-events: none;
  display: flex; align-items: center; justify-content: center; z-index: 4;
  opacity: 0;
}
.handoff.is-on { animation: handoff var(--dur-ceremony) var(--ease-standard) 2; }
.handoff span {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-0);
  background: var(--ink-950); padding: 10px 18px; border-radius: var(--r-pill);
  display: inline-flex; align-items: center; gap: 8px;
}
@keyframes handoff {
  0% { opacity: 0; transform: translateY(6px); }
  30%, 70% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(-6px); }
}

/* tour controls */
.tour-bar {
  display: flex; align-items: center; gap: var(--s-2);
  flex-wrap: wrap; margin-bottom: var(--s-3);
}
.tour-bar .b-sm svg { flex: none; }
.scen {
  font-size: 12px; font-weight: 500; padding: 7px 13px; border-radius: var(--r-pill);
  border: 1px solid var(--border-strong); background: var(--bg-1); color: var(--fg-2);
  cursor: pointer; transition: all var(--dur-fast) var(--ease-standard);
}
.scen:hover { border-color: var(--ink-300); color: var(--fg-1); }
.scen[aria-pressed="true"] { background: var(--blue-50); border-color: var(--blue-500); color: var(--blue-600); }

.wheel-on .stage { border-color: var(--blue-500); box-shadow: 0 0 0 3px var(--blue-100); }

/* ------------------------------------------------- two Tuesdays, one clock
   The comparison table this replaces gave its widest column to the row labels
   — three words each — and squeezed the two columns carrying the whole
   argument into the remaining two thirds. Here the clock is the fixed column
   and the prose gets the rest.

   The two tracks are deliberately unequal in length and the grid is
   `align-items: start`, so the shorter one simply stops. That gap is the
   argument; do not balance the columns. */
.tl { display: grid; gap: var(--s-12); }
@media (min-width: 760px) {
  .tl { grid-template-columns: 1fr 1fr; gap: var(--s-16); align-items: start; }
}

.tl-head {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--fg-3);
  margin: 0 0 var(--s-6); padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--border);
}
.tl-track--now .tl-head { color: var(--blue-600); border-bottom-color: var(--blue-500); }

.tl-stops { list-style: none; margin: 0; padding: 0; }
.tl-stops li {
  position: relative;
  border-left: 1px solid var(--border);
  padding: 0 0 var(--s-6) var(--s-6);
  display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: var(--s-3);
  align-items: baseline;
}
/* the rule is drawn by each stop's left border, so the last one must not draw
   a tail below the final dot */
.tl-stops li:last-child { border-left-color: transparent; padding-bottom: 0; }
.tl-stops li::before {
  content: ""; position: absolute; left: -4px; top: 5px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--bg-1); border: 1px solid var(--border-strong);
}
.tl-track--now .tl-stops li::before { background: var(--blue-500); border-color: var(--blue-500); }

/* Numbers are the hero: the clock is what makes this tangible, so it is mono,
   tabular and the same size as the prose beside it rather than a footnote. */
.tl-stops b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 600; letter-spacing: -.01em;
  color: var(--fg-3);
}
.tl-stops span { font-size: 14px; line-height: 1.5; color: var(--fg-2); }
.tl-track--now .tl-stops b { color: var(--fg-1); }
.tl-track--now .tl-stops span { color: var(--fg-1); }

.tl-done {
  margin: var(--s-6) 0 0; padding-left: var(--s-6);
  font-size: 14px; line-height: 1.5; color: var(--fg-2);
}

@media (max-width: 480px) {
  .tl-stops li { grid-template-columns: minmax(0, 1fr); gap: var(--s-1); }
}

/* -------------------------------------------------------------- pricing */
.price-grid { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 900px) { .price-grid { grid-template-columns: 1.15fr 1fr; gap: var(--s-12); } }
.price-card {
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--bg-1); padding: var(--s-8);
}
.price-card--lead { border-color: var(--ink-950); }

/* Not a card. Once the "From $2,000" row and the second booking button came
   out, this was a 288px box beside a 635px one, and a bordered box that stops
   short reads as truncated rather than finished. It is also not an offer you
   can buy — giving it a card's weight put it in competition with the price
   beside it. As plain text on the section it just ends, which is what a
   paragraph does. */
.price-fit { padding-top: var(--s-8); }
@media (max-width: 899px) { .price-fit { padding-top: 0; } }
.price-tag { display: flex; align-items: baseline; gap: var(--s-2); margin: var(--s-4) 0 var(--s-1); }
.price-tag b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: clamp(48px, 5vw, 64px); font-weight: 700; letter-spacing: -.03em; line-height: 1; }
.price-tag span { font-size: 14px; color: var(--fg-2); }
.price-mo { font-family: var(--font-mono); font-size: 14px; color: var(--fg-2); font-variant-numeric: tabular-nums; }
.price-list { list-style: none; margin: var(--s-6) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.price-list li { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; line-height: 1.5; color: var(--fg-2); }
.price-list svg { color: var(--blue-500); flex: none; margin-top: 3px; }
.price-list b { color: var(--fg-1); font-weight: 500; }

/* ------------------------------------------------------------------ faq */
.faq { border-top: 1px solid var(--border); }
.faq details { border-bottom: 1px solid var(--border); }
.faq summary {
  list-style: none; cursor: pointer; padding: var(--s-6) 0;
  display: flex; align-items: flex-start; gap: var(--s-4);
  font-size: 16px; font-weight: 500; letter-spacing: -.01em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; margin-left: auto; flex: none;
  width: 11px; height: 11px; margin-top: 6px;
  border-right: 1.5px solid var(--fg-3); border-bottom: 1.5px solid var(--fg-3);
  transform: rotate(45deg);
  transition: transform var(--dur-fast) var(--ease-standard);
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: 10px; }
.faq-a { color: var(--fg-2); font-size: 15px; line-height: 1.6; margin: 0 0 var(--s-6); max-width: 68ch; padding-left: calc(var(--s-4) + 22px); }
.faq-q-mark { font-family: var(--font-mono); font-size: 12px; color: var(--fg-3); width: 22px; flex: none; padding-top: 3px; }

/* ------------------------------------------------------------------ cta */
/* The points were centred against a column twice their height, so they floated
   in the middle of the band with 125px of nothing above and below. Ending level
   with the left column puts them beside the buttons and the fit line, which is
   what they are about, rather than beside the headline, which they compete
   with. */
.cta-box { display: grid; gap: var(--s-8); align-items: end; }
@media (min-width: 900px) { .cta-box { grid-template-columns: 1.3fr 1fr; gap: var(--s-16); } }
.cta-points { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-4); }
.cta-points li { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; line-height: 1.5; color: var(--ink-300); }
.cta-points svg { color: var(--blue-300); flex: none; margin-top: 3px; }

/* --------------------------------------------------------------- footer */
.footer { padding: var(--s-12) 0 var(--s-16); border-top: 1px solid var(--border); }
.footer-grid { display: flex; flex-wrap: wrap; gap: var(--s-6) var(--s-12); align-items: flex-start; }
.footer small { color: var(--fg-3); font-size: 12px; line-height: 1.6; display: block; max-width: 62ch; }

/* ------------------------------------------------------ sticky mobile CTA */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 35;
  padding: var(--s-3) var(--s-6) calc(var(--s-3) + env(safe-area-inset-bottom));
  background: rgba(255,255,255,.92);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  border-top: 1px solid var(--border);
  display: flex; gap: var(--s-3); align-items: center;
  transform: translateY(110%);
  transition: transform var(--dur-standard) var(--ease-standard);
}
.sticky-cta.is-up { transform: none; }
.sticky-cta .b { flex: 1; }
.sticky-cta small { font-size: 12px; color: var(--fg-2); display: none; }
@media (min-width: 620px) { .sticky-cta small { display: block; } }
@media (min-width: 900px) { .sticky-cta { display: none; } }


/* Very narrow phones (320px) were gaining a horizontal scrollbar under the
   tour: nowrap button labels plus a non-wrapping control row. */
@media (max-width: 380px) {
  .b { white-space: normal; text-align: center; }
  .tour-bar { gap: var(--s-2); }
  .stage { padding: var(--s-8) var(--s-2) var(--s-2); }
  .phone { width: 100%; max-width: 288px; }
}

/* ---------------------------------------------------- phone ergonomics
   The audience is 45–65 and mostly one-handed on a phone. Every secondary
   control was 30–40px tall; 44px is the comfortable floor. Desktop density
   is left alone. */
@media (max-width: 899px) {
  .b-sm { padding: var(--s-4) var(--s-4); }
  .tctl { min-height: 44px; padding: 0 var(--s-3); }
  .hero-demo .scen { min-height: 44px; }
  .nav-inner { padding: var(--s-2) var(--s-2) var(--s-2) var(--s-4); }
  /* The sticky bar is fixed over the page end — reserve the height back or
     the last footer line can never be scrolled out from under it. */
  .footer { padding-bottom: calc(var(--s-16) + var(--s-2)); }
}

/* the dead cue: .is-cue is scoped to .p-ui, so marketing buttons never pulsed */
.b.is-cue {
  box-shadow: 0 0 0 3px var(--blue-100);
  border-color: var(--blue-500);
  animation: p-cue var(--dur-pulse) var(--ease-standard) infinite;
}

/* screen-reader-only live region for the tour narration */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Unfilled facts. Deliberately loud: this page must not go live claiming
   things nobody has confirmed, and a quiet TODO comment gets shipped. */
.todo {
  display: inline-block;
  background: var(--warning-ink); color: var(--ink-0);
  font-family: var(--font-mono); font-size: .85em;
  padding: 1px 6px; border-radius: var(--r-sm);
}

/* ------------------------------------------------------- scroll reveals */
.reveal { opacity: 0; transform: translateY(12px); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-ceremony) var(--ease-enter),
              transform var(--dur-ceremony) var(--ease-enter);
}
.reveal-2.is-in { transition-delay: 80ms; }
.reveal-3.is-in { transition-delay: 160ms; }
.reveal-4.is-in { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
  .reveal.is-in { transition-duration: 80ms; }
  .device, .handoff.is-on, .stage-hint.is-live i, .b.is-cue { animation: none; transition-duration: 80ms; }
}

/* ---------------------------------------------------------------------
   Frame sizing overrides. Must come after the base .phone-screen and
   .laptop-screen rules — same specificity, so source order decides.
   --------------------------------------------------------------------- */


/* =====================================================================
   Take-the-wheel takeover

   Driving the product is a task, not a glance. The stage goes full-screen so
   the phone is comfortable to type into and — the real gain — the contractor
   app renders at a desktop width instead of inside a 590px column.

   position:fixed rather than reparenting: every listener already bound inside
   the stage keeps working, and there is no second copy of the DOM to keep in
   step.
   ===================================================================== */
html.stage-open, html.stage-open body { overflow: hidden; }

.is-immersive .stage {
  position: fixed; inset: 0; z-index: 60;
  border: 0; border-radius: 0;
  height: 100dvh;
  padding: var(--s-16) var(--s-6) var(--s-6);
  background: var(--bg-2);
  box-shadow: none;
  gap: var(--s-4);
  animation: stageIn var(--dur-deliberate) var(--ease-enter) both;
}
@keyframes stageIn { from { opacity: 0; } to { opacity: 1; } }

/* the phone is roomier to type into */
.is-immersive .phone { width: 384px; }


/* the laptop finally gets to look like a laptop */
.is-immersive .laptop { max-width: 1120px; }


.is-immersive .stage-note { max-width: 720px; }
.is-immersive .stage-note-slot { min-height: 84px; }
.is-immersive .stage-hint { margin-bottom: var(--s-2); }

.stage-exit {
  position: absolute; top: var(--s-4); right: var(--s-4); z-index: 8;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 500; color: var(--fg-1);
  background: var(--bg-1); border: 1px solid var(--border-strong);
  border-radius: var(--r-pill); padding: var(--s-2) var(--s-4);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.stage-exit:hover { border-color: var(--ink-300); }
.stage-exit[hidden] { display: none; }
@media (max-width: 640px) {
  .is-immersive .stage { padding: var(--s-12) var(--s-3) var(--s-3); }
  .is-immersive .phone { width: 100%; max-width: 340px; }
  .stage-exit { top: var(--s-3); right: var(--s-3); }
}
@media (prefers-reduced-motion: reduce) {
  .is-immersive .stage { animation-duration: 80ms; }
}

/* =====================================================================
   Demo-first hero

   The demo used to sit 30% down the page, behind ~430 words of argument.
   It now sits beside the headline: proof at zero scroll, and the only part
   of the page that speaks fluent trade is the first thing anyone sees.

   The stage keeps its light panel on the near-black hero on purpose — the
   quiet dark side is the pitch, the lit panel is the product.
   ===================================================================== */
.hero { padding: 96px 0 var(--s-8); }
@media (min-width: 980px) { .hero { padding: 100px 0 var(--s-12); } }

/* Top-aligned, not centred: the demo column is the taller of the two, and
   centring the copy against it pushed the trust line below the fold while
   leaving a void above the headline — exactly the wrong way round. */
/* Message left, demo right, near enough even. The demo column is the whole
   point of the hero, so it gets the slightly larger half. */
.hero-grid { display: grid; gap: var(--s-8); align-items: start; }
@media (min-width: 980px) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
    grid-template-areas: "lead demo" "cta demo";
    grid-template-rows: auto 1fr;
    column-gap: var(--s-8); row-gap: var(--s-8);
  }
  .hero-lead { grid-area: lead; padding-top: var(--s-4); }
  /* Both columns end on the same line. The message column used to stop about
     240px above the demo's bottom edge, so the composition had a shared top
     edge and a ragged foot and the eye had nowhere to rest. Dropping the
     actions to the bottom of their row puts the one button on the page level
     with the bottom of the thing it is asking about. */
  .hero-cta  { grid-area: cta; align-self: end; }
  .hero-demo { grid-area: demo; }
}

/* This was capped at 46px, which made it smaller than every section heading on
   the page — the hero was the quietest headline on a page it is supposed to
   open. It was sized down when the message column had to share the width with
   a full-bleed hero; it does not any more, and the column beneath it had 359px
   of nothing in it. The extra two lines are paid for out of that hole. */
.h-hero {
  font-size: clamp(31px, 4.6vw, 62px); font-weight: 600;
  letter-spacing: -.032em; line-height: 1.04; margin: 0; color: var(--ink-0);
}
.hero-lead .hero-sub { margin-top: var(--s-6); max-width: 42ch; font-size: 18px; }
.hero-cta .hero-actions { margin-top: 0; }

/* the worked example, reduced from a card to a line */
.hero-line {
  margin: var(--s-6) 0 0; font-size: 13px; line-height: 1.6;
  color: var(--ink-400); max-width: 46ch;
}
.hero-line b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 17px; font-weight: 700; color: var(--ink-0); letter-spacing: -.01em;
}
.hero-line span { font-family: var(--font-mono); color: var(--ink-300); }
.hero-line a { color: var(--blue-300); }
.hero-line a:hover { color: var(--ink-0); }


.hero-demo { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
.hero-demo .stage {
  height: clamp(468px, calc(100vh - 288px), 616px);
  padding: var(--s-3);
  box-shadow: var(--shadow-3);
  gap: var(--s-3);
}
.hero-demo .stage-note-slot { min-height: 0; }
.hero-demo .tour-bar { margin: 0; }

/* ------------------------------------------ frameless demo, ticker beneath
   The white panel was a frame around a frame. The device already reads as a
   screen, so the card only spent a border and 24px of padding restating it.
   That goes: the device sits straight on the dark hero.

   The steps went beside the device rather than under it because a bar
   underneath cost ~130px of the demo's height. That was true when the bar
   carried eleven controls and a paragraph. It carries two things now — five
   dots and one button — so it is a single 44px row, and beside the device it
   read as an orphan: a short block floating in the middle of 700px of black,
   with no edge tying it to anything. Underneath, it is what it is, a progress
   bar for the thing above it, and the demo gets the rail's width back.
   Scoped away from .is-immersive, which needs its lit panel. */
@media (min-width: 980px) {
  .hero-demo { gap: var(--s-3); }
  .hero-demo:not(.is-immersive) .stage {
    /* 252px = the hero's own padding, plus the ticker row and the fine print
       under it. Keeps the whole hero inside a 900px fold. */
    height: clamp(460px, calc(100vh - 252px), 700px);
    padding: 0;
    background: none; border-color: transparent; box-shadow: none;
    /* on the dark hero now, not on a light panel */
    color: var(--ink-0);
    gap: var(--s-3);
  }
  .hero-demo:not(.is-immersive) .stage-hint { color: var(--ink-500); }
  .hero-demo:not(.is-immersive) .stage-note { color: var(--ink-0); }
  .hero-demo:not(.is-immersive) .note-k { color: var(--blue-300); }
  /* the receipt still lands on a light card, so it brings its own scrim */
  .hero-demo:not(.is-immersive) .stage-end { background: rgba(10, 10, 11, .72); }
  /* no frame left to ring — the cue moves to the device itself */
  .wheel-on .hero-demo:not(.is-immersive) .phone,
  .wheel-on .hero-demo:not(.is-immersive) .laptop {
    box-shadow: 0 0 0 3px var(--blue-500), var(--shadow-3);
  }

  /* One row: where you are on the left, the one action on the right. The base
     .acts--rail is already a horizontal ticker showing only the active label,
     so there is nothing to override — the column variant that used to live
     here was the exception, not this. */
  .tour-rail {
    display: flex; align-items: center; gap: var(--s-6);
    border-top: 1px solid rgba(255, 255, 255, .1);
    padding-top: var(--s-3);
  }
  .tour-rail .acts--rail { flex: 1 1 auto; min-width: 0; }
  .tour-rail .tour-bar { flex: none; margin: 0; }
}
@media (min-width: 1240px) {
  /* Was 1.5fr, which handed the side rail's 168px back to the demo so the
     split the visitor saw stayed even. The rail is under the device now, so
     the whole column is demo and 1.5fr would make it 60% of the hero. */
  .hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
}

.hero-fine { margin: 0; font-size: 12px; line-height: 1.5; color: var(--ink-400); }
.hero-fine a { color: var(--blue-300); }
.hero-fine a:hover { color: var(--ink-0); }

/* --------------------------------------------------- the step ticker
   The vertical narration rail became five dots and one label. The prose it
   used to carry is in the stage note, which says the same thing at the
   moment it is actually true. */
.acts--rail {
  /* flex-direction is load-bearing: .acts sets `column` and this rule is the
     same specificity, so without it the five steps stack. */
  display: flex; flex-direction: row; flex-wrap: wrap; align-items: center;
  gap: var(--s-2) var(--s-3); padding: 0;
}
.acts--rail .act {
  border-left: 0; padding: 0; width: auto;
  display: flex; align-items: center; gap: var(--s-2);
}
.acts--rail .act::before {
  position: static; transform: none;
  width: 22px; height: 22px;
  background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.16);
  color: var(--ink-400);
}
.acts--rail .act.is-done::before { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.2); color: var(--ink-300); }
.acts--rail .act.is-active::before { background: var(--blue-500); border-color: var(--blue-500); color: var(--ink-0); }
.acts--rail .act h3 {
  display: none; font-size: 13px; font-weight: 500;
  letter-spacing: -.01em; color: var(--ink-0); white-space: nowrap;
}
.acts--rail .act.is-active h3 { display: block; }
.acts--rail .act:hover h3 { color: var(--ink-0); }
@media (max-width: 420px) { .acts--rail .act.is-active h3 { white-space: normal; } }

/* ------------------------------------------------ one loud thing
   Seventeen pill-shaped buttons shared the first screen and the accent sat on
   four of them, so it had stopped meaning "this is the action". Pause and
   Restart are utilities and the job switcher is a preference; neither is a
   call to action, so neither gets a button's weight. "Take the wheel" keeps
   the accent because it is the one thing worth doing here. */
.tctl {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 40px; padding: 0 var(--s-2);
  background: none; border: 0; border-radius: var(--r-sm);
  font-size: 12px; font-weight: 500; letter-spacing: -.005em;
  color: var(--ink-400); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard);
}
.tctl:hover { color: var(--ink-0); }
.tctl svg { flex: none; opacity: .85; }

/* The job switcher used to live on the dark hero as a text toggle and needed
   its own dark treatment. It now appears only inside the end card, which is a
   light panel, so the base .scen pill is already right. */

/* =============================================== the gap, as a strip
   Was a full section with a heading, a lede, a paragraph and three cards.
   The demo above it has already made the point; this only has to land the
   cost of the gap before the calculator quantifies it. */
.section--strip { padding: var(--s-12) 0; }
.strip-lede {
  font-size: clamp(19px, 2.2vw, 26px); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.3; margin: 0; max-width: 34ch;
}
.strip-row {
  display: grid; gap: var(--s-6); margin: var(--s-8) 0 0;
  border-top: 1px solid var(--border); padding-top: var(--s-6);
}
@media (min-width: 700px) { .strip-row { grid-template-columns: repeat(3, 1fr); gap: var(--s-12); } }
.strip-row b {
  display: block; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 28px; font-weight: 700; letter-spacing: -.025em;
}
.strip-row span { display: block; font-size: 14px; color: var(--fg-2); margin-top: 4px; line-height: 1.45; }
.strip-foot { margin: var(--s-8) 0 0; font-size: 14px; line-height: 1.6; color: var(--fg-2); max-width: 68ch; }

/* ================================================ how it ships, as a line */
/* A column inside the pricing grid now, not a four-across band under it — see
   the note in the markup. Its own eyebrow does the separating, so the rule and
   the big top margin it used to carry are gone. */
.ships {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--s-4);
}
.ships li { display: flex; gap: var(--s-3); align-items: baseline; }
.ships b {
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  color: var(--blue-500); flex: none;
}
.ships span { font-size: 13px; line-height: 1.55; color: var(--fg-2); }

/* Everything else we build, deliberately one line. See the note in the markup:
   this is a route for the visitor with a different problem, not a second offer
   competing with the call to action above it. */
/* No rule above it: the reading measure is capped at 68ch, so a border on this
   element stopped half way across and read as a broken version of the
   full-width one over the ships list. Space does the separating. */
.price-else {
  margin: var(--s-12) 0 0;
  font-size: 14px; line-height: 1.6; color: var(--fg-2); max-width: 68ch;
}

/* =====================================================================
   Stage composition

   A portrait phone in a landscape panel left 41% of the width empty and
   pushed the narration into a band underneath, which cost the device height
   it badly needed. On a phone act the narration moves into that side space
   instead: the device gets the full height of the panel, and the empty area
   becomes the thing explaining it.

   A laptop act needs the whole width, so there the narration goes back under.
   ===================================================================== */
/* The caption shares the status row at the top of the panel. Beside the device
   it stole width; beneath it, height. On its own thin row it costs the device
   almost nothing and the box below belongs entirely to the demo. */
.stage-top {
  flex: none; width: 100%; min-height: 34px;
  display: flex; align-items: center; gap: var(--s-4);
}
.stage-top .stage-hint { margin: 0; align-self: center; }

/* Pause and Restart, moved off the rail and onto the stage they act on. Icon
   only: they are utilities, and the row they sit in already ran three
   typographic voices in 34px. The label stays for screen readers. */
.stage-ctl { flex: none; margin-left: auto; display: flex; align-items: center; gap: var(--s-1); }
.stage-ctl .tctl { min-height: 32px; padding: 0 var(--s-2); }
.stage-ctl .tctl span {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* immersive mode has its own exit in that corner, and nothing is playing */
.is-immersive .stage-ctl { display: none; }

/* The status word was the third voice in the row — "PLAYING" in mono caps
   beside a mono-caps caption key beside a sentence. The dot says it: pulsing
   while it runs, still when it does not, and the Pause button carries the
   rest. Kept in the DOM for screen readers. */
.hero-demo:not(.is-immersive) .stage-hint { gap: 0; }
.hero-demo:not(.is-immersive) .js-stage-hint-text {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.hero-demo:not(.is-immersive) .stage-hint i { width: 7px; height: 7px; }
.hero-demo:not(.is-immersive) .stage-hint:not(.is-live) i { background: var(--ink-500); }


/* The phone keeps a plausible width and takes its height from the panel. */
/* The box is the device's now. A portrait phone still leaves side room — that
   is what a phone is — but it takes the full height, and the laptop takes the
   full width. */
.hero-demo .phone { width: 348px; }
@media (min-width: 1100px) { .hero-demo .phone { width: 396px; } }
@media (min-width: 1300px) { .hero-demo .phone { width: 416px; } }
.hero-demo .laptop { max-width: 100%; }

/* ---------------------------------------------------------------------
   Touch targets, last in the file on purpose.

   These override rules defined further up at the same specificity, and CSS
   resolves that by source order — an earlier @media block loses to a later
   plain rule. Two previous attempts at this silently did nothing.
   --------------------------------------------------------------------- */
@media (max-width: 899px) {
  .b { min-height: 44px; }
  .tctl { min-height: 44px; padding: 0 var(--s-3); }
  /* higher specificity than the desktop rule it is undoing, so it would win on
     specificity alone — but it also has to come after it */
  .stage-ctl .tctl { min-height: 44px; }
  .hero-demo .scen { min-height: 44px; }
  /* the ticker keeps its small dots but gets a comfortable hit area */
  .acts--rail .act { padding: var(--s-3) 0; }
  .acts--rail { gap: var(--s-2) var(--s-4); }
}

/* ---------------------------------------------- end-of-demo receipt
   Four lines of what just happened, in the specifics of the job that played.
   "Watch again" drops to a text link so the card carries one primary and one
   secondary, not three equal buttons at the moment of the ask. */
.stage-end-recap {
  list-style: none; margin: var(--s-4) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--s-2);
}
.stage-end-recap li {
  display: flex; gap: var(--s-2); align-items: flex-start;
  font-size: 13px; line-height: 1.45; color: var(--fg-2);
}
.stage-end-recap svg { color: var(--blue-500); flex: none; margin-top: 3px; }
.stage-end-recap b { color: var(--fg-1); font-weight: 600; }

/* Replay and the other two jobs, in one row. The hero used to carry a "Job"
   label and three toggles beside the demo; here the same control costs nothing
   and answers the question someone actually has at the end — does it do my
   trade. The job that just played is not offered again: "Watch it again" is
   already that button. */
.stage-end-replay {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
  margin-top: var(--s-1);
}
.stage-end-or { font-size: 12px; color: var(--fg-3); }
.stage-end-replay .scen { font-size: 12px; padding: 5px 11px; }

.stage-end-again {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0; padding: var(--s-2) 0;
  background: none; border: 0; cursor: pointer;
  font-size: 13px; color: var(--fg-2);
  text-decoration: underline; text-underline-offset: 3px;
}
.stage-end-again:hover { color: var(--fg-1); }
.stage-end-again svg { opacity: .8; }

/* the card has to sit inside the stage, which is short on a laptop viewport */
.stage-end-in { padding: var(--s-6); max-width: 440px; }
@media (max-height: 820px) {
  .stage-end-in { padding: var(--s-4) var(--s-6); }
  .stage-end-in h3 { font-size: 19px; }
  .stage-end-recap { gap: 6px; margin-top: var(--s-3); }
  .stage-end-actions { margin-top: var(--s-4); }
  /* the replay row costs a line the short-viewport card does not have spare */
  .stage-end-again { padding: 6px 0; }
  .stage-end-replay { margin-top: 0; }
}
