/* Nex Stay Collabs — homepage only. Loaded after styles.css by index.html.
   Everything here is index-only: hero, phone mockup, proof band, loop, economics.
   Shared selectors (.step, .section-sub, .card, forms, footer) stay in styles.css —
   console/pilot/setup pages depend on them. */

:root {
  --ink-2: #221F27;          /* raised surface on ink */
  --gold-lit: #E8B94A;
  --on-ink: rgba(245, 240, 224, .62);
}

/* ============================================================
   HERO
   ============================================================ */
.hero { padding: 76px 0 72px; position: relative; }
.hero-grid {
  display: grid;
  grid-template-columns: 1.02fr .98fr;
  gap: 40px;
  align-items: center;
}
.eyebrow {
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--red); font-weight: 700; margin-bottom: 18px;
}
.hero h1 {
  font-family: var(--serif); font-weight: 600; letter-spacing: -.032em;
  font-size: clamp(44px, 7vw, 88px); line-height: .97;
  margin: 0 0 24px; max-width: 15ch; text-wrap: balance;
}
.hero h1 em { font-style: italic; color: var(--red); }
.hero .lede {
  font-size: clamp(16.5px, 1.9vw, 19px); line-height: 1.62;
  color: var(--muted); max-width: 54ch; margin: 0 0 32px;
}
.hero .lede b { color: var(--ink); font-weight: 600; }
.hero .lede-short { display: none; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }

/* ---------- Hero visual: layered phone + booking-engine payoff ---------- */
/* Phone sits right, the two proof cards stack down the left. Keeps the promo
   card inside the phone fully visible — the cards only kiss the phone's edge. */
.stage {
  position: relative;
  display: flex; justify-content: flex-end; align-items: center;
  padding-right: 4px;
  min-height: 620px;
}

.phone-frame {
  position: relative;
  width: min(292px, 76vw);
  aspect-ratio: 9 / 19.2;
  border-radius: 44px;
  background: linear-gradient(150deg, #2A2830, #121116 42%, #08080B);
  padding: 9px;
  box-shadow:
    0 2px 0 rgba(255, 255, 255, .10) inset,
    0 28px 70px rgba(26, 26, 26, .34),
    0 4px 14px rgba(26, 26, 26, .18);
  transform: perspective(1500px) rotateY(-8deg) rotateX(2deg) rotate(.6deg);
  transform-style: preserve-3d;
}
.phone-screen {
  position: relative;
  height: 100%;
  border-radius: 35px;          /* frame radius 44 − 9px padding = true inner radius */
  overflow: hidden;
  background: #14121A;
  isolation: isolate;
  /* iOS Safari won't clip a <video> to the parent's border-radius — the scene
     videos render square corners. A mask forces the clip; it must be flat opaque
     (white→black would fade the screen edges out). */
  -webkit-mask-image: -webkit-radial-gradient(#fff, #fff);
  mask-image: linear-gradient(#fff, #fff);
}

/* SWAP SEAM ──────────────────────────────────────────────────────────────
   Each .phone-scene is a deliberately graphic gradient composition, not an
   imitation of a photo. When permission-cleared creator video lands, replace
   a scene's inner layers with:
     <video class="scene-media" muted loop playsinline preload="metadata"
            poster="/img/hero/<name>.jpg" src="/img/hero/<name>.mp4"></video>
   Nothing else in the markup, CSS, or JS needs to change — home-motion.js
   crossfades whatever is inside .phone-scene.
   ──────────────────────────────────────────────────────────────────────── */
.phone-scene {
  position: absolute; inset: 0;
  opacity: 0;
  transform: scale(1.06);
  will-change: opacity, transform;
}
.phone-scene:first-of-type { opacity: 1; }
.scene-media { width: 100%; height: 100%; object-fit: cover; display: block; }

.phone-scene[data-scene="golden"] {
  background:
    /* crisp disc, then a wide separate glow — one soft fade reads as a smudge */
    radial-gradient(circle 27px at 70% 30%, #FCE49A 0%, #F5C862 76%, #EDB44C 96%, rgba(237, 180, 76, 0) 100%),
    radial-gradient(circle 96px at 70% 30%, rgba(247, 202, 100, .34) 0%, rgba(247, 202, 100, 0) 72%),
    linear-gradient(180deg, #241C33 0%, #4A3050 32%, #9E5540 58%, #DE9E5A 75%, #6B4437 87%, #201B2B 100%);
}
.phone-scene[data-scene="pool"] {
  background:
    radial-gradient(circle 74px at 24% 16%, rgba(255, 248, 224, .42) 0%, rgba(255, 248, 224, 0) 74%),
    linear-gradient(180deg, #0C1E31 0%, #17506B 30%, #2E92A2 54%, #7FD6CB 68%, #C9EFE6 74%, #2C7F8C 82%, #0E2C3A 100%);
}
.phone-scene[data-scene="suite"] {
  background:
    radial-gradient(ellipse 120px 92px at 30% 20%, rgba(255, 231, 182, .60) 0%, rgba(255, 231, 182, 0) 72%),
    linear-gradient(180deg, #241C15 0%, #57402D 36%, #B3854B 60%, #E6C288 70%, #8A6236 84%, #201A13 100%);
}

/* horizon shimmer — abstract reflected light, reads as motion not as water */
.scene-shimmer {
  position: absolute; left: 0; right: 0; bottom: 0; height: 46%;
  background: repeating-linear-gradient(
    180deg,
    rgba(255, 255, 255, .16) 0 1.5px,
    rgba(255, 255, 255, 0) 1.5px 8px
  );
  mask-image: linear-gradient(180deg, transparent, #000 34%, #000 62%, transparent);
}

/* scrim keeps the white UI legible over any scene (contrast ≥ 4.5:1) */
.phone-vignette {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, .42) 0%, transparent 22%, transparent 52%, rgba(0, 0, 0, .58) 100%);
  box-shadow: inset 0 0 80px 26px rgba(0, 0, 0, .34);
}
.phone-grain {
  position: absolute; inset: 0; pointer-events: none; opacity: .16;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* persistent UI chrome */
.phone-ui { position: absolute; inset: 0; pointer-events: none; }
.phone-notch {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  width: 74px; height: 5px; border-radius: 3px; background: rgba(0, 0, 0, .55);
}
.phone-rail {
  position: absolute; right: 12px; bottom: 128px;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  color: #fff; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .55));
}
.rail-item { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.rail-item svg { width: 22px; height: 22px; }
.rail-item span { font: 700 10.5px/1 var(--sans); letter-spacing: .01em; }
.phone-meta {
  position: absolute; left: 16px; right: 66px; bottom: 112px;
  color: #fff; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .6));
}
.phone-handle { display: block; font: 700 13px/1.3 var(--sans); }
.phone-caption { display: block; font: 400 11.5px/1.4 var(--sans); opacity: .84; margin-top: 3px; }

.phone-promo {
  position: absolute; left: 10px; right: 10px; bottom: 14px;
  background: #fff; border-radius: 16px; padding: 14px 16px;
  display: flex; align-items: center; gap: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
  will-change: transform, opacity;
}
.promo-copy { flex: 1; min-width: 0; }
.promo-kicker {
  display: block; font: 700 8.5px/1 var(--sans); letter-spacing: .15em;
  text-transform: uppercase; color: var(--muted);
}
.promo-headline { display: block; font: 600 13.5px/1.3 var(--sans); color: var(--ink); margin-top: 6px; }
.promo-fine { display: block; font: 400 10px/1.3 var(--sans); color: var(--muted); margin-top: 3px; }
.promo-go {
  position: relative; flex: none;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--red); color: #fff;
  display: grid; place-items: center;
}
.promo-go svg { width: 17px; height: 17px; }
.promo-tap {
  position: absolute; inset: -6px; border-radius: 50%;
  border: 2px solid var(--red); opacity: 0;
  will-change: transform, opacity;
}

/* the payoff card — the booking landed on the hotel's own engine */
.engine-card {
  position: absolute; z-index: 3;
  left: -16px; bottom: 68px;
  width: 238px;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 15px 17px; box-shadow: var(--shadow-lg);
  opacity: 0; will-change: transform, opacity;
}
.engine-kicker {
  display: block; font: 700 8.5px/1 var(--sans); letter-spacing: .15em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 9px;
}
.engine-room { display: block; font: 600 13.5px/1.35 var(--sans); color: var(--ink); }
.engine-rate { display: block; font: 400 11.5px/1.5 var(--sans); color: var(--muted); margin-top: 2px; }
.engine-rate code {
  font: 600 11px/1 var(--sans); letter-spacing: .04em;
  background: var(--cream); border: 1px solid var(--line);
  border-radius: 5px; padding: 2px 5px; color: var(--ink);
}
.engine-ok {
  display: flex; align-items: center; gap: 7px; margin-top: 11px;
  padding-top: 11px; border-top: 1px solid var(--line);
  font: 600 11.5px/1.3 var(--sans); color: #1c7a3f;
}
.engine-ok svg { width: 14px; height: 14px; flex: none; }

.chip {
  position: absolute; z-index: 3;
  display: flex; align-items: center; gap: 8px; white-space: nowrap;
  background: var(--card); border: 1px solid var(--line); border-radius: 999px;
  box-shadow: var(--shadow-lg); font: 600 12.5px/1 var(--sans); color: var(--red-deep);
  padding: 11px 15px;
  top: 78px; left: 10px;
}
.chip svg { width: 15px; height: 15px; flex: none; }

/* ============================================================
   STAT STRIP
   ============================================================ */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(164px, 1fr));
  gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; margin-top: 52px;
}
.stat { background: var(--card); padding: 24px; position: relative; }
.stat::before {
  content: ""; position: absolute; top: 0; left: 24px; width: 26px; height: 2px;
  background: var(--gold);
}
.stat b {
  display: block; font-family: var(--serif); font-weight: 600;
  font-size: clamp(32px, 3.6vw, 44px); letter-spacing: -.022em; line-height: 1.08;
  margin-top: 6px;
}
.stat span { display: block; font-size: 12.5px; line-height: 1.45; color: var(--muted); margin-top: 7px; }

/* ============================================================
   PROOF BAND
   ============================================================ */
.proofband {
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, .45); padding: 22px 0;
}
.proofband .wrap {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px 44px; flex-wrap: wrap;
}
.proof-group { display: flex; align-items: baseline; gap: 12px 26px; flex-wrap: wrap; }
.proof-label {
  font: 700 10.5px/1.4 var(--sans); letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted);
}
.wordmark {
  font: 600 15px/1.4 var(--sans); color: var(--ink); opacity: .5;
  transition: opacity .18s ease;
}
.wordmark:hover { opacity: 1; }

/* ============================================================
   THE LOOP — full-bleed ink, scrubbed on desktop
   ============================================================ */
.loop-section {
  background: var(--ink); color: var(--cream);
  padding: 96px 0 84px; margin: 0;
  position: relative; overflow: hidden;
}
.loop-section::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(900px 420px at 78% -8%, rgba(201, 162, 39, .13), transparent 62%),
    radial-gradient(700px 400px at 4% 108%, rgba(228, 0, 43, .11), transparent 60%);
}
.loop-section .wrap { position: relative; }
.loop-section .section-title { color: var(--cream); }
.loop-section .section-sub { color: var(--on-ink); }

.loop-pin { padding: 8px 0; }
/* padding and row-gap are kept tight on purpose: the whole composition is pinned at
   "center center", so anything over ~680px tall gets clipped at both ends on a 13"
   laptop (720px viewport) instead of centring. */
.loop-stage { position: relative; padding: 22px 24px 4px; max-width: var(--maxw); margin: 0 auto; }

/* THE MEANDER — the five steps descend the page instead of sitting in a row: odd
   steps left, even steps right, one per grid row, threaded by a right-angle line
   that runs the full width of each row. row-gap has to clear the corner radius the
   connector uses (see R in home-motion.js) or the arcs run into the cards. Explicit
   grid-area per node because sparse auto-placement would pack steps 1 and 2 into
   the same row. */
.loop-rail {
  position: relative;
  display: grid;
  grid-template-columns: 40% 40%;
  justify-content: space-between;
  row-gap: 28px;
}
.loop-node:nth-of-type(1) { grid-area: 1 / 1; }
.loop-node:nth-of-type(2) { grid-area: 2 / 2; }
.loop-node:nth-of-type(3) { grid-area: 3 / 1; }
.loop-node:nth-of-type(4) { grid-area: 4 / 2; }
.loop-node:nth-of-type(5) { grid-area: 5 / 1; }

/* No viewBox — the SVG's user unit is a CSS pixel, so the `d` strings JS writes
   from getBoundingClientRect() need no transform to line up with the cards. */
.loop-path {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none;
}
.loop-path path { fill: none; stroke-linecap: round; }
.loop-path-bg  { stroke: rgba(245, 240, 224, .14); stroke-width: 2; }
.loop-path-lit { stroke: var(--gold-lit); stroke-width: 2.5; }

/* z-index 2 so the packet rides over the cards — the curve runs behind them, and a
   packet that vanished for each card would break the sense of one continuous trip */
.loop-packet {
  position: absolute; z-index: 2; top: 0; left: 0; width: 11px; height: 11px;
  margin: -5.5px 0 0 -5.5px; border-radius: 50%;
  background: var(--gold-lit);
  box-shadow: 0 0 0 4px rgba(232, 185, 74, .22), 0 0 18px 4px rgba(232, 185, 74, .45);
  opacity: 0;
}

/* opaque background + position: relative is what hides the curve inside each card,
   leaving it visible only in the gaps */
.loop-node {
  position: relative;
  display: flex; align-items: center; gap: 15px;
  background: var(--ink-2);
  border: 1px solid rgba(245, 240, 224, .13);
  border-radius: var(--radius);
  padding: 16px 18px;
  transition: background .35s ease, border-color .35s ease, box-shadow .35s ease, transform .35s ease;
}
.loop-node div { flex: 1; min-width: 0; }
.loop-node svg {
  width: 28px; height: 28px; flex: none;
  color: rgba(245, 240, 224, .45);
  transition: color .35s ease;
}
.loop-node b { display: block; font: 600 13.5px/1.3 var(--sans); color: var(--cream); margin-bottom: 4px; }
.loop-node span { display: block; font-size: 11.5px; line-height: 1.45; color: var(--on-ink); }

/* no lift — with only some nodes lit, a translate reads as a misaligned row
   rather than as emphasis. Gold border + glow + gold icon is signal enough. */
.loop-node.is-live {
  background: #2C2617;
  border-color: rgba(232, 185, 74, .55);
  box-shadow: 0 14px 40px rgba(201, 162, 39, .16);
}
.loop-node.is-live svg { color: var(--gold-lit); }

/* last node is the full stop: gold fill, ink type */
.loop-node.loop-end.is-live {
  background: var(--gold-lit); border-color: var(--gold-lit);
  box-shadow: 0 16px 48px rgba(232, 185, 74, .34);
}
.loop-node.loop-end.is-live svg { color: var(--ink); }
.loop-node.loop-end.is-live b { color: var(--ink); }
/* .82 not .68 — on #E8B94A, .68 measures 4.43:1 and misses the 4.5:1 floor */
.loop-node.loop-end.is-live span { color: rgba(26, 26, 26, .82); }

/* footnote under the diagram, not a card in it. The dashed top rule is the tie back
   to the dashed return leg — same language, so it reads as that line's caption. */
/* not flex: the icon flows inline with the first line, so it reads as part of the
   sentence instead of a detached bullet beside a centred block. Rule spans the full
   wrap so it separates the whole diagram rather than floating under the middle. */
.loop-return {
  margin: 30px 0 0;
  border-top: 1px dashed rgba(232, 185, 74, .3);
  padding: 18px 0 0; text-align: center;
  font: 600 12.5px/1.6 var(--sans); color: var(--on-ink);
}
.loop-return svg {
  width: 14px; height: 14px; color: var(--gold-lit);
  vertical-align: -3px; margin-right: 5px;
}

/* the 4 explainer cards stay inside the ink section (keeps H2 → H3 intact).
   Two columns, not the base .steps auto-fit: at 4 across the copy set in ~14ch
   columns and every card ran 8-plus ragged lines. */
.loop-steps { margin-top: 44px; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
.loop-steps .step {
  background: var(--ink-2);
  border-color: rgba(245, 240, 224, .12);
  box-shadow: none;
}
/* serif titles, matching .section-title — the numbers are gone, so the heading is
   the only thing marking where a card starts and it has to carry that on its own */
.loop-steps .step h3 {
  font-family: var(--serif); font-weight: 600; font-size: 21px;
  letter-spacing: -.015em; color: var(--cream); margin-bottom: 10px;
}
.loop-steps .step p { color: var(--on-ink); }
.loop-steps .step em { color: var(--gold-lit); }
.loop-steps .step:hover {
  border-color: rgba(232, 185, 74, .40);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .28);
}

/* ============================================================
   ECONOMICS — one $600 room, split two ways

   Each full-width track is the room rate, so the coloured slice is what the channel
   costs and the remainder is what the hotel keeps. Scaling to the larger cost instead
   would fill the OTA bar end to end, which reads as "all of it, gone".

   Figures sit UNDER the bar, not inside the slice. Inside looks stronger on a wide
   screen, but the 10% slice is 29px on a phone and clips its own label; under the bar
   there is no width at which it can break, and one rule covers every viewport.

   Red for the travel site, gold for direct — gold already means "the direct loop" in
   the section above, so the old green was off-palette and a second word for one idea.
   ============================================================ */
.econ {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 26px 28px 24px; margin: 0;
}
/* CONTROLS — real range inputs and radios, so keyboard and screen readers get the
   native behaviour for free. The track is hand-styled rather than left to
   accent-color: that leaves the unfilled half near-black, which is heavy on cream and
   makes the control read as the same kind of horizontal bar as the data below it. A
   thin rounded track with a round thumb can't be mistaken for a chart. */
.econ-controls {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px 30px;
  padding-bottom: 24px; margin-bottom: 24px;
  border-bottom: 1px solid var(--line);
}
.econ-field { min-width: 0; margin: 0; padding: 0; border: 0; }
.econ-field label, .econ-field legend {
  display: block; padding: 0;
  font: 600 11px/1.3 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
}
.econ-field output {
  display: block; margin: 5px 0 7px;
  font: 600 25px/1 var(--serif); letter-spacing: -.02em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* --fill is written by js/econ-calc.js so the gold portion tracks the thumb */
.econ-field input[type="range"] {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: 6px; margin: 0; padding: 0;
  border-radius: 999px; cursor: grab;
  background: linear-gradient(90deg,
    var(--gold) 0 var(--fill, 50%), var(--line) var(--fill, 50%) 100%);
}
.econ-field input[type="range"]:active { cursor: grabbing; }
.econ-field input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--ink); border: 3px solid var(--gold);
  box-shadow: 0 1px 4px rgba(26, 26, 26, .25);
}
.econ-field input[type="range"]::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--ink); border: 3px solid var(--gold);
  box-shadow: 0 1px 4px rgba(26, 26, 26, .25);
}
.econ-field input[type="range"]::-moz-range-track { background: transparent; }
.econ-field input[type="range"]:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 5px;
}

/* pills: the radio stays in the DOM and focusable, the span is what's painted */
.econ-picks { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.econ-picks label { cursor: pointer; }
.econ-picks input {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; clip-path: inset(50%);
}
.econ-picks span {
  display: block; padding: 8px 13px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--cream);
  font: 600 13px/1 var(--sans); color: var(--muted);
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.econ-picks label:hover span { border-color: var(--gold); color: var(--ink); }
.econ-picks input:checked + span {
  background: var(--ink); border-color: var(--ink); color: var(--cream);
}
.econ-picks input:focus-visible + span { outline: 2px solid var(--ink); outline-offset: 3px; }

.econ-scale {
  font: 700 10.5px/1 var(--sans); letter-spacing: .15em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 24px;
}
.econ-scale b { color: var(--ink); }
.econ-row + .econ-row { margin-top: 26px; }
.econ-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 4px 18px; flex-wrap: wrap; margin-bottom: 10px;
}
.econ-head b { font: 600 15px/1.3 var(--sans); }
.econ-head span { font-size: 12.5px; color: var(--muted); }

.econ-bar {
  height: 26px; border-radius: 6px; overflow: hidden;
  background: var(--cream-deep);
}
/* transform-origin so the reveal in home-motion.js grows the slice from the left */
.econ-seg {
  display: block; height: 100%; border-radius: 6px 0 0 6px;
  transform-origin: left center;
}
.econ-seg-ota { width: 20%; background: linear-gradient(90deg, var(--red), var(--red-deep)); }
.econ-seg-direct { width: 10%; background: linear-gradient(90deg, var(--gold), #A8841C); }

/* Each figure sits under the slice it measures. The cost figure carries its channel's
   colour, which is what binds label to slice — cheaper than a legend swatch. */
.econ-legend {
  display: flex; justify-content: space-between; gap: 12px; margin-top: 9px;
  font-size: 12.5px; color: var(--muted);
}
/* tabular-nums so a counting figure doesn't jitter its own label sideways */
.econ-legend b {
  font: 600 17px/1 var(--serif); color: var(--ink); margin-right: 3px;
  font-variant-numeric: tabular-nums;
}
.econ-cost b { color: var(--red-deep); }

/* the one bold thing in the card: the answer */
.econ-delta {
  margin: 26px 0 0; padding: 16px 18px; border-radius: 10px;
  background: rgba(201, 162, 39, .12);
  border-left: 3px solid var(--gold);
}
.econ-delta b {
  display: block; font: 600 19px/1.35 var(--serif); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.econ-delta p {
  margin: 4px 0 0; font-size: 13.5px; line-height: 1.55; color: #5C4A10;
}
.econ-delta p b { display: inline; font-size: inherit; font-family: inherit; font-weight: 600; }
.econ-note { margin: 14px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--muted); }

/* announced, never shown — see the aria-live note in index.html */
.econ-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip-path: inset(50%);
}

/* ============================================================
   PLATFORM CARDS — brand mark as a watermark

   Scoped to .platforms so overflow: hidden doesn't reach the other .step grids. The
   mark is placed to bleed off the bottom-right corner, so the clip is the point: a
   cropped mark reads as texture, a fully contained one reads as an icon that lost its
   label. Each brand's own colour, at a per-card alpha tuned so all three land at the
   same visual weight — red at .10 carries much further than ink at .10.
   ============================================================ */
.platforms .step { overflow: hidden; }
.plat-mark {
  position: absolute; z-index: 0; right: -20px; bottom: -24px;
  width: 116px; height: 116px; pointer-events: none;
}
/* Alphas are not equal on purpose. Ink carries far more contrast on white than a mid
   hue at the same alpha, and the Instagram frame has roughly twice the stroke length
   of the TikTok note — so matching the numbers would not match what the eye sees.
   These are tuned to land at the same faint weight. Instagram takes its purple rather
   than its pink so it doesn't read as a near-repeat of YouTube's red. */
.plat-tiktok { color: rgba(26, 26, 26, .085); }
.plat-meta { color: rgba(131, 58, 180, .13); }
.plat-youtube { color: rgba(228, 0, 43, .11); }

/* ============================================================
   CARD SPOTLIGHT + FOCUS
   Two ideas ported from Aceternity UI (React/Tailwind/Framer there, plain CSS here).

   Spotlight: a soft glow tracking the cursor inside the hovered card. --mx/--my are
   written by js/home-motion.js; the fallback centre means it degrades to a static
   glow rather than a misplaced one if that never runs.

   Focus: the siblings of the hovered card recede. The original dims their opacity,
   which is not safe here — .platforms body copy is #6B6B6B on white at 5.33:1, and
   dimming to even 75% drops it to ~3.5:1, under the 4.5 floor. So the card SURFACE
   flattens (shadow away, border lightened, a hair smaller) and the text never loses
   contrast. :focus-within is included too — the original is pointer-only, which
   leaves keyboard users with no equivalent cue.
   ============================================================ */
.steps .step { --spot: rgba(201, 162, 39, .14); }
.loop-steps .step { --spot: rgba(232, 185, 74, .11); }
.steps .step::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  border-radius: inherit; pointer-events: none;
  background: radial-gradient(200px circle at var(--mx, 50%) var(--my, 50%),
    var(--spot), transparent 68%);
  opacity: 0; transition: opacity .3s ease;
}
.steps .step:hover::before, .steps .step:focus-within::before { opacity: 1; }
/* the copy needs its own layer to sit above the glow. Named elements rather than
   `> *`, which would outrank .plat-mark's z-index and lift the watermark too. */
.steps .step h3, .steps .step p { position: relative; z-index: 1; }

/* No opacity in this transition list. GSAP writes inline opacity frame by frame for
   the card reveal, and a CSS transition on the same property fights it — the cards
   settled at opacity 0 and vanished. The focus effect doesn't touch opacity anyway. */
.steps .step {
  transition: transform .2s ease, box-shadow .25s ease, border-color .2s ease;
}
.steps .step:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: #D8CFB0;
}
/* no border-color here: the two grids sit on opposite backgrounds, and a single value
   would put a cream border on the ink cards. Non-hovered cards keep their own. */
.steps:has(.step:hover) .step:not(:hover),
.steps:has(.step:focus-within) .step:not(:focus-within) {
  transform: scale(.985);
  box-shadow: none;
}
.steps .step em { font-style: italic; color: var(--red); }

/* sticky mobile CTA — mobile only, appears once the hero is past */
.mobile-cta {
  position: fixed; z-index: 60; left: 12px; right: 12px; bottom: 12px;
  display: none; align-items: center; gap: 12px;
  background: rgba(26, 26, 26, .94);
  backdrop-filter: blur(8px);
  border-radius: 999px; padding: 10px 12px 10px 20px;
  box-shadow: 0 12px 34px rgba(26, 26, 26, .34);
  transform: translateY(140%);
}
.mobile-cta p { margin: 0; flex: 1; font: 600 13px/1.3 var(--sans); color: var(--cream); }
.mobile-cta .btn { padding: 10px 18px; font-size: 14px; flex: none; }

/* floating WhatsApp button — brand green so it reads instantly as WhatsApp,
   not the site's own accent color; always on top of the sticky mobile CTA */
.whatsapp-fab {
  position: fixed; z-index: 70; right: 20px; bottom: 20px;
  width: 56px; height: 56px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: #25d366; color: #fff; box-shadow: 0 8px 24px rgba(26, 26, 26, .3);
  transition: transform .15s ease;
}
.whatsapp-fab:hover { transform: scale(1.06); }
.whatsapp-fab svg { width: 30px; height: 30px; }

@media (max-width: 760px) {
  /* lift above .mobile-cta so the two never overlap while both are visible */
  .whatsapp-fab { right: 14px; bottom: 90px; width: 50px; height: 50px; }
  .whatsapp-fab svg { width: 26px; height: 26px; }
}

/* ============================================================
   REVEAL (index-only)
   ============================================================ */
.reveal { opacity: 0; transform: translateY(14px); animation: rise .7s cubic-bezier(.2, .7, .2, 1) forwards; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1040px) {
  .engine-card { left: max(-18px, calc(50% - 232px)); width: 226px; }
}

@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: 44px; }
  .hero h1 { max-width: 18ch; }
  /* column, not row: as a row flex-item the engine card forced the stage to
     292px + 260px, which pushed the whole grid past the viewport */
  .stage {
    flex-direction: column; align-items: center; justify-content: flex-start;
    gap: 18px; min-height: 0; padding: 8px 0 0;
  }
  .phone-frame { transform: none; }
  .engine-card { position: relative; left: auto; bottom: auto; width: min(300px, 86vw); }
  /* sit fully inside the screen, below the 35px corner curve, and shrink the type
     so the pill clears the frame on narrow phones instead of straddling its edge.
     ponytail: fixed 11px — below ~330px viewport it touches again; wrap it then. */
  .chip {
    top: 44px; left: 50%; transform: translateX(-50%);
    font-size: 11px; padding: 9px 13px; gap: 6px;
  }
  .chip svg { width: 13px; height: 13px; }
}

@media (max-width: 760px) {
  .hero { padding: 34px 0 30px; }
  /* squeeze headline + short pitch + CTA + phone onto one screen: the clamp()
     floor (44px) and the 8-line .lede-full were what pushed the phone below
     the fold. Swap to the short pitch and tighten the gaps around it. */
  .hero h1 { font-size: 34px; margin: 0 0 12px; }
  .hero .lede-full { display: none; }
  .hero .lede-short { display: block; margin: 0 0 20px; }
  .hero-grid { gap: 20px; }
  .stage { gap: 10px; padding: 4px 0 0; }
  .loop-section { padding: 64px 0 60px; }
  /* .loop-stage sits outside .wrap (see index.html), so it needs its own 24px
     horizontal inset to match — without it the cards run edge-to-edge. */
  .loop-stage { padding: 22px 24px 0; }
  /* one column: at this width a 43%/43% serpentine leaves the cards too narrow to
     read, and the connector would have nowhere to curve. Cards stack, path is off. */
  .loop-rail { grid-template-columns: 1fr; row-gap: 10px; }
  .loop-node:nth-of-type(1), .loop-node:nth-of-type(2), .loop-node:nth-of-type(3),
  .loop-node:nth-of-type(4), .loop-node:nth-of-type(5) { grid-area: auto; }
  .loop-path, .loop-packet { display: none; }
  .loop-return { margin-top: 22px; text-align: left; }
  /* one column — the explicit 2-col grid replaces the base auto-fit, which used to
     collapse on its own at this width */
  .loop-steps { margin-top: 26px; grid-template-columns: 1fr; }
  .econ { padding: 20px 18px 18px; }
  /* stack the two figures — side by side they collide at this width */
  .econ-legend { flex-direction: column; gap: 3px; }
  .econ-controls { grid-template-columns: 1fr; gap: 18px; }
  .mobile-cta { display: flex; }
  body { padding-bottom: 76px; }
}

/* ============================================================
   REDUCED MOTION — every element must rest in its final state
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .reveal { animation: none; opacity: 1; transform: none; }
  .phone-scene { transition: none; }
  .phone-scene:first-of-type { opacity: 1; transform: scale(1.02); }
  .phone-promo, .engine-card { opacity: 1; transform: none; }
  .promo-tap { display: none; }
  /* JS zeroes stroke-dashoffset so the path rests fully drawn — see home-motion.js */
  .loop-packet { display: none; }
  .loop-node { transition: none; }
  .mobile-cta { transform: none; }
  .steps .step { transition: none; }
  .econ-seg { transition: none; }
}
