/* AI OS — scrollcraft theme. Six tokens + two faces, per the brand book.
   Do not restyle .sc-stage, .sc-copy or any [data-sc-*] selector — those are
   the engine's mechanism. Everything below is page-specific. */

:root {
  --sc-canvas:     #FFFDFA;
  --sc-surface:    #FFFDFA;
  --sc-ink:        #342A1F;
  --sc-ink-soft:   #6B5B49;
  --sc-accent:     #FCE7DA;
  --sc-accent-ink: #342A1F;
  --sc-font-display: "Instrument Serif", Georgia, serif;
  --sc-font-text:    "Inter Tight", system-ui, sans-serif;

  --line: rgba(52, 42, 31, .16);

  /* The full brand-book palette, brought back in at the client's explicit
     direction for this page — each colour paired with its own book-specified
     ink for contrast, not the "one sector colour" rule the book states
     elsewhere (that rule governs sector-specific sales material; the client
     wants this page more visually rich, and it's their brand to spend). */
  --coral:        #F79C8C; --coral-ink:   #5C2418;
  --apricot:      #FAB48C; --apricot-ink: #7A3524;
  --butter:       #FFFAB9; --butter-ink:  #5A4A18;
  --teal:         #76C8CB; --teal-ink:    #123638;
  --mint:         #A0D5B6; --mint-ink:    #1F4635;
  --orchid:       #C97AB2; --orchid-ink:  #3D1934;
  --violet:       #9A73B3; --violet-ink:  #2E1B3D;
  /* Violet is the darkest of the seven tokens, so its book-specified ink
     pairing measures under 4.5:1 at text sizes — this deepened ink is used
     wherever body copy sits directly on violet. */
  --violet-ink-strong: #221430;
}

body { background: var(--sc-canvas); }

/* ---------- header ---------- */
.site-bar {
  position: fixed; inset: 0 0 auto 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px clamp(20px, 5vw, 64px);
  background: transparent;
  transition: background .3s var(--sc-ease-out, ease), box-shadow .3s var(--sc-ease-out, ease);
}
/* The header is fixed and drift is a page-ground effect, so its own colours
   are pinned to the light scheme rather than reading the drifting tokens —
   otherwise it goes dark-on-dark the moment the page drifts to an ink ground
   (the close act). */
.site-bar.is-scrolled {
  background: color-mix(in srgb, #FFFDFA 92%, transparent);
  box-shadow: 0 1px 0 var(--line);
  backdrop-filter: blur(6px);
}
.site-bar__mark {
  font-family: var(--sc-font-display); font-size: 22px; letter-spacing: -.03em;
  color: #342A1F; text-decoration: none;
  background: color-mix(in srgb, #FFFDFA 70%, transparent);
  padding: 6px 14px; border-radius: 999px;
}
.site-bar__nav {
  display: flex; gap: clamp(14px, 2vw, 28px); align-items: center;
  font-family: var(--sc-font-text); font-size: 14px;
}
.site-bar__nav a {
  color: #342A1F; text-decoration: none; opacity: .85;
  background: color-mix(in srgb, #FFFDFA 55%, transparent);
  padding: 6px 10px; border-radius: 999px;
  transition: opacity .15s var(--sc-ease-out, ease);
}
.site-bar__nav a:hover, .site-bar__nav a:focus-visible { opacity: 1; }
.site-bar__nav a:focus-visible { outline: 2px solid #342A1F; outline-offset: 2px; }
@media (max-width: 860px) { .site-bar__nav { display: none; } }
.site-bar__cta {
  font-family: var(--sc-font-text); font-size: 14px; font-weight: 500;
  color: #342A1F; text-decoration: none;
  border: 1px solid #342A1F; border-radius: 999px;
  padding: 9px 18px; background: color-mix(in srgb, #FFFDFA 70%, transparent);
  transition: background .15s var(--sc-ease-out, ease), color .15s var(--sc-ease-out, ease);
}
.site-bar__cta:hover { background: #342A1F; color: #FFFDFA; }
.site-bar__cta:focus-visible { outline: 2px solid #342A1F; outline-offset: 3px; }

.site-bar__menu-btn {
  display: none; width: 40px; height: 40px; border-radius: 999px;
  border: 1px solid #342A1F; background: color-mix(in srgb, #FFFDFA 70%, transparent);
  align-items: center; justify-content: center; cursor: pointer; padding: 0;
  transition: background .15s var(--sc-ease-out, ease);
}
.site-bar__menu-btn:hover { background: #342A1F; }
.site-bar__menu-btn:hover .site-bar__menu-icon,
.site-bar__menu-btn:hover .site-bar__menu-icon::before,
.site-bar__menu-btn:hover .site-bar__menu-icon::after { background: #FFFDFA; }
.site-bar__menu-btn:focus-visible { outline: 2px solid #342A1F; outline-offset: 3px; }
.site-bar__menu-icon,
.site-bar__menu-icon::before,
.site-bar__menu-icon::after {
  display: block; width: 18px; height: 2px; border-radius: 2px; background: #342A1F;
  transition: transform .2s var(--sc-ease-out, ease), opacity .2s var(--sc-ease-out, ease), background .15s ease;
}
.site-bar__menu-icon { position: relative; }
.site-bar__menu-icon::before, .site-bar__menu-icon::after { content: ""; position: absolute; left: 0; }
.site-bar__menu-icon::before { transform: translateY(-6px); }
.site-bar__menu-icon::after { transform: translateY(6px); }
.site-bar__menu-btn[aria-expanded="true"] .site-bar__menu-icon { background: transparent; }
.site-bar__menu-btn[aria-expanded="true"] .site-bar__menu-icon::before { transform: translateY(0) rotate(45deg); }
.site-bar__menu-btn[aria-expanded="true"] .site-bar__menu-icon::after { transform: translateY(0) rotate(-45deg); }

@media (max-width: 860px) {
  .site-bar__cta { display: none; }
  .site-bar__menu-btn { display: inline-flex; }
}

/* Full-screen link list standing in for .site-bar__nav below 860px. Hidden
   with the same [hidden]/class pairing as the rest of the page so it never
   depends on the scrollcraft engine, which owns .sc-* selectors only. */
.mobile-nav {
  position: fixed; inset: 0; z-index: 35;
  background: var(--sc-canvas);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(20px, 5vh, 40px);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity .28s var(--sc-ease-out, ease), transform .28s var(--sc-ease-out, ease), visibility 0s linear .28s;
}
.mobile-nav.is-open {
  opacity: 1; visibility: visible; transform: translateY(0);
  transition: opacity .28s var(--sc-ease-out, ease), transform .28s var(--sc-ease-out, ease);
}
.mobile-nav__links { display: flex; flex-direction: column; align-items: center; gap: clamp(16px, 4vh, 26px); }
.mobile-nav__links a {
  font-family: var(--sc-font-display); font-size: clamp(1.7rem, 7vw, 2.4rem);
  color: var(--sc-ink); text-decoration: none; letter-spacing: -.02em;
}
.mobile-nav__links a:focus-visible { outline: 2px solid var(--sc-ink); outline-offset: 4px; }
.mobile-nav__cta { margin-top: 8px; }
@media (min-width: 861px) { .mobile-nav { display: none; } }

/* ---------- shared type ---------- */
.eyebrow {
  font-family: var(--sc-font-text); font-size: 12px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--sc-ink-soft);
  margin: 0 0 14px;
}
/* A full sentence read worse in tracked capitals than the short labels this
   class was built for — drop the shout, keep the weight and colour. */
.eyebrow--sentence { text-transform: none; letter-spacing: normal; font-size: 13px; }
.sc-body { font-family: var(--sc-font-text); color: var(--sc-ink-soft); }

/* ================= Act 1 — text ================= */
/* COLD OPEN ---------------------------------------------------------------
   One fixed-size wordmark, centred on the first screen, that shrinks and flies
   into the header bar as the act scrubs. --co-tx/--co-ty/--co-scale are written
   by JS from the header mark's measured box, so the landing is exact at any
   viewport width. Pure transform + opacity: compositor work only. */
.coldopen [data-sc-stage] {
  display: grid; place-items: center; position: relative;
}
.coldopen__mark {
  font-family: var(--sc-font-display);
  /* Instrument Serif is narrow: "AI OS" at 58px spans only ~100px, so a
     viewport-relative size that looks right on desktop reads as a tiny label
     on a phone. Sized so the mark spans roughly half the screen at any width. */
  font-size: clamp(5rem, 32vw, 16rem);
  letter-spacing: -.03em; line-height: 1; color: var(--sc-ink);
  white-space: nowrap; display: block;
  transform:
    translate(calc(var(--co-tx, 0px) * var(--sc-p, 0)),
              calc(var(--co-ty, 0px) * var(--sc-p, 0)))
    scale(calc(1 + (var(--co-scale, .18) - 1) * var(--sc-p, 0)));
  transform-origin: center center;
  will-change: transform;
}
/* The belief line holds the first screen with the wordmark, then clears out
   early so the mark finishes its flight alone. */
.coldopen__sub {
  position: absolute; left: 50%; translate: -50% 0;
  top: calc(50% + clamp(4.6rem, 21vw, 10.5rem));
  font-family: var(--sc-font-text); font-size: clamp(11px, 1.05vw, 13px);
  font-weight: 600; letter-spacing: .3em; text-transform: uppercase;
  color: #9a9086; white-space: nowrap;
  opacity: clamp(0, calc(1 - var(--sc-p, 0) * 3.4), 1);
}
/* Header mark is hidden only while the travelling copy is still in flight.
   Default is VISIBLE, so a JS failure or reduced motion leaves a working header. */
html.co-flying .site-bar__mark { opacity: 0; }
.site-bar__mark { transition: opacity .2s var(--sc-ease-out, ease); }

/* HERO — centred, per the BRIEF's own miro reference. The previous version was
   left-aligned inside a centred wrap with a 14ch cap on the headline, so on a
   1900px screen the type filled 474px and left 818px of dead space to its right:
   neither centred nor deliberately asymmetric. It also stood 658px tall in a
   900px viewport, which let the next act's caption intrude on the first screen. */
.hero-text {
  min-height: 100svh;
  display: grid; place-items: center;
  padding-top: clamp(96px, 12vh, 150px);
  padding-bottom: clamp(56px, 9vh, 110px);
  position: relative; isolation: isolate;
}
/* The "soft gradient wash" the BRIEF asked for and the build never had. Chalk
   Blush, the brand's own accent — no invented colour. Sits behind the type. */
.hero-text::before {
  content: ""; position: absolute; z-index: -1;
  left: 50%; top: 46%; translate: -50% -50%;
  width: min(1180px, 96vw); aspect-ratio: 1.5;
  background: radial-gradient(ellipse at center,
    color-mix(in srgb, var(--sc-accent) 62%, transparent) 0%,
    color-mix(in srgb, var(--sc-accent) 22%, transparent) 42%,
    transparent 72%);
  pointer-events: none;
}
.hero-text .sc-wrap { max-width: 980px; text-align: center; }
.hero-text h1 {
  color: var(--sc-ink);
  font-size: clamp(2.6rem, 7.2vw, 6.1rem);
  line-height: 1.0; max-width: 19ch; margin-inline: auto;
}
.hero-text .sc-body {
  font-size: clamp(1.05rem, 1.6vw, 1.32rem);
  max-width: 52ch; margin: 26px auto 36px; line-height: 1.55;
}
.hero-text .sc-actions { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }

/* Scroll cue. There was none, so the first screen gave the eye nowhere to go. */
.hero-cue {
  position: absolute; left: 50%; translate: -50% 0; bottom: clamp(18px, 3.4vh, 38px);
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  font-family: var(--sc-font-text); font-size: 10px; font-weight: 600;
  letter-spacing: .34em; text-transform: uppercase; color: #9a9086;
  pointer-events: none;
}
.hero-cue__line { display: block; width: 1px; height: 44px; overflow: hidden; background: var(--line); }
.hero-cue__line::after {
  content: ""; display: block; width: 100%; height: 46%;
  background: var(--sc-ink); animation: hero-cue-run 2.1s var(--sc-ease-out, ease-in-out) infinite;
}
@keyframes hero-cue-run {
  0%   { transform: translateY(-105%); }
  55%  { transform: translateY(215%); }
  100% { transform: translateY(215%); }
}
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--sc-font-text); font-size: 15px; font-weight: 500;
  border-radius: 999px; padding: 14px 24px; text-decoration: none;
  white-space: nowrap;
  transition: transform .15s var(--sc-ease-out, ease), background .15s ease;
}
.btn:active { transform: scale(.97); }
.btn--primary { background: var(--sc-accent); color: var(--sc-accent-ink); }
.btn--primary:hover { background: color-mix(in srgb, var(--sc-accent) 80%, var(--sc-ink) 10%); }
.btn--ghost { border: 1px solid var(--sc-ink); color: var(--sc-ink); }
.btn--ghost:hover { background: var(--sc-ink); color: var(--sc-canvas); }
.btn:focus-visible { outline: 2px solid var(--sc-ink); outline-offset: 3px; }

/* ================= Act 2 — companies (signature move) ================= */
.companies { background: var(--sc-canvas); }
.companies [data-sc-stage] {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(20px, 3vh, 36px); padding: clamp(24px, 5vh, 60px) clamp(20px, 5vw, 64px);
}
.companies .eyebrow { text-align: center; position: relative; z-index: 5; background: var(--sc-canvas); padding: 4px 14px; border-radius: 999px; }
.companies .stats-row, .companies .logo-row { position: relative; z-index: 5; }

/* Typed so the browser stores these as NUMBERS instead of re-parsing a token
   list on every style recalc. Untyped custom properties inside nested calc()
   are re-tokenised each frame across all 20 tiles — that alone was doubling
   the worst frame times. */
@property --cp { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --ce { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --rp { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --rq { syntax: '<number>'; inherits: true; initial-value: 0; }

.collage {
  position: relative; width: min(1100px, 92vw);
  aspect-ratio: 1366 / 768;
  perspective: 1600px;

  /* Two phases off one --sc-p: converge, then rush.
     --ce EASES THE CONVERGE OUT so its velocity reaches zero exactly where the
     rush's velocity starts from zero. Without it the wall stopped dead at the
     halfway point and the eye read that hard stop as a stutter, which is the
     real reason the first pass felt less smooth than a single monotonic zoom. */
  --p:  var(--sc-p, 0);
  --cp: clamp(0, calc(var(--p) / 0.5), 1);
  --ce: calc(1 - (1 - var(--cp)) * (1 - var(--cp)));
  --rp: clamp(0, calc((var(--p) - 0.5) / 0.5), 1);
  --rq: calc(var(--rp) * var(--rp));
}

/* Static feather. The first pass drove the gradient stops off --rp, which
   re-rasterised the mask every frame for every tile; a fixed 3% edge is
   visually the same during the rush and free at rest. */
.collage__tiles {
  position: absolute; inset: 0; overflow: hidden; border-radius: 14px;
  contain: paint;
  -webkit-mask-image:
    linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent),
    linear-gradient(180deg, transparent, #000 3%, #000 97%, transparent);
  mask-image:
    linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent),
    linear-gradient(180deg, transparent, #000 3%, #000 97%, transparent);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.collage__tile {
  position: absolute; border-radius: 10px; overflow: hidden;
  box-shadow: 0 8px 20px -8px rgba(52, 42, 31, .28);
  /* Depth is derived from each tile's own scatter distance (--sx/--sy), not a
     31st authored value: squaring both cancels the sign, so every tile always
     emerges from behind the glass and settles flush at --sc-p 1, regardless of
     which direction it scattered toward. */
  --tile-z: calc((var(--sx, 0px) * var(--sx, 0px) + var(--sy, 0px) * var(--sy, 0px)) / 100px * -1);
  transform:
    translate3d(
      calc(var(--sx, 0px) * (1 - var(--ce)) + var(--rx, 0vw) * var(--rq)),
      calc(var(--sy, 0px) * (1 - var(--ce)) + var(--ry, 0vw) * var(--rq)),
      calc(var(--tile-z) * (1 - var(--ce)))
    )
    rotate(calc(var(--srot, 0) * (1 - var(--ce)) * 1deg))
    scale(calc(1 + (var(--rs, 2.5) - 1) * var(--rq)));
  opacity: calc((.55 + .45 * var(--ce)) * (1 - clamp(0, calc((var(--p) - 0.74) / 0.2), 1)));
  will-change: transform;
}
.collage__tile img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The owner-story video is the section's centerpiece: a portrait (phone-shaped)
   panel centred in the collage, sitting above the client photos that converge
   around and behind it. It fades in on the act's own --sc-p like the tiles do,
   but stays fully visible from halfway so it's never dimmer than the proof
   around it. */
.collage__video {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  height: 84%; aspect-ratio: 404 / 720; z-index: 6;
  border-radius: 18px; overflow: hidden;
  background: color-mix(in srgb, var(--sc-ink) 88%, black);
  box-shadow: 0 30px 60px -24px rgba(52, 42, 31, .5), 0 2px 0 rgba(255, 253, 250, .5) inset;
  opacity: clamp(0, calc(var(--sc-p, 0) * 2), 1);
  transform: scale(calc(1 + 0.26 * var(--rq)));
}
.collage__video-el { width: 100%; height: 100%; object-fit: cover; display: block; background: #342A1F; }

/* Sound control. Lives inside .collage__video so it inherits that panel's own
   --sc-p fade and its rush scale for free. The button is a FIXED-SIZE circle and
   the prompt is a separate sibling, so toggling never moves the hit target. */
.collage__soundwrap {
  position: absolute; left: 10px; bottom: 10px; z-index: 8;
  display: flex; align-items: center; gap: 8px;
  opacity: 0; pointer-events: none; transition: opacity .28s ease;
}
.collage__soundwrap.is-live { opacity: 1; }
.collage__sound {
  flex: 0 0 auto; width: 34px; height: 34px; padding: 0; margin: 0; border: 0;
  border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: #FFFDFA; background: rgba(24, 19, 14, .66);
  -webkit-backdrop-filter: blur(9px); backdrop-filter: blur(9px);
  box-shadow: 0 6px 18px -8px rgba(0, 0, 0, .65);
  pointer-events: auto; transition: background .18s ease;
}
.collage__sound:hover, .collage__sound:focus-visible { background: rgba(24, 19, 14, .86); }
.collage__sound:focus-visible { outline: 2px solid #FFFDFA; outline-offset: 2px; }
.collage__sound svg { width: 18px; height: 18px; display: block; }
.collage__sound .collage__sound-wave { display: none; }
.collage__sound[aria-pressed="true"] .collage__sound-slash { display: none; }
.collage__sound[aria-pressed="true"] .collage__sound-wave { display: inline; }

.collage__soundhint {
  font-family: var(--sc-font-text); font-size: 12px; font-weight: 600; line-height: 1;
  letter-spacing: .01em; color: #FFFDFA; white-space: nowrap;
  padding: 7px 11px; border-radius: 999px; background: rgba(24, 19, 14, .58);
  -webkit-backdrop-filter: blur(9px); backdrop-filter: blur(9px);
  pointer-events: none; transition: opacity .22s ease;
}
.collage__soundwrap.is-used .collage__soundhint { opacity: 0; }

@media (max-width: 760px) {
  .collage__soundwrap { left: 8px; bottom: 8px; }
  .collage__soundhint { display: none; }   /* the panel is smaller; icon is enough */
}
@media (prefers-reduced-motion: reduce) {
  .collage__soundwrap { display: none; }   /* native <video controls> carries a mute */
  /* the cue stays as a static mark — it still says "there is more below" without
     anything travelling, which is what this mode asks for */
  .hero-cue__line::after { animation: none; height: 100%; opacity: .3; }
}

@media (max-width: 760px), (prefers-reduced-motion: reduce) {
  .collage__tile { transform: none; opacity: 1; }
  .collage__video { transform: none; }
}
@media (max-width: 760px) {
  .collage { aspect-ratio: auto; width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
  /* The inline left/top/width/height percentages are authored for the desktop
     absolute-positioned layout; in the grid fallback they must be overridden,
     not just repositioned, or every tile shrinks to its percentage of nothing. */
  .collage__tiles { display: contents; }
  .collage__tile {
    position: static !important; inset: auto !important;
    left: auto !important; top: auto !important;
    width: 100% !important; height: 100% !important;
    aspect-ratio: 3/4;
  }
  /* The video is now real featured content, not a placeholder to hide: on
     mobile it becomes a centred portrait sitting in its own full-width row
     above the photo grid. Opacity is forced to 1 because the mobile section is
     a 'flow' act, so --sc-p never advances and the desktop fade would leave it
     invisible. */
  .collage__video {
    position: static; translate: none; inset: auto;
    grid-column: 1 / -1; order: -1; justify-self: center;
    height: min(56vh, 460px); width: auto; margin-bottom: 6px; opacity: 1;
  }
}

.stats-row {
  display: flex; gap: clamp(28px, 6vw, 72px); flex-wrap: wrap; justify-content: center;
  border-top: 1px solid var(--line); padding-top: 22px; margin-top: 6px;
}
.stats-row > div { text-align: center; }
.stats-row .sc-nums {
  display: block; font-family: var(--sc-font-display); font-size: clamp(2rem, 4vw, 3.2rem);
  line-height: 1;
}
.stats-row > div:nth-child(1) .sc-nums { color: var(--coral-ink); }
.stats-row > div:nth-child(2) .sc-nums { color: var(--teal-ink); }
.stats-row p { margin: 8px 0 0; font-size: 14px; color: var(--sc-ink-soft); font-family: var(--sc-font-text); }

/* Logo banner beneath the collage: a single unbroken row that scrolls sideways
   for real, two identical sets chasing each other so the loop never shows a
   seam. Edges fade into the page ground rather than cutting off hard. */
.logo-marquee {
  position: relative; z-index: 5; width: 100%; max-width: 1100px;
  overflow: hidden; margin-top: 4px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.logo-marquee__track {
  display: flex; width: max-content;
  animation: logo-marquee 42s linear infinite;
}
.logo-marquee:hover .logo-marquee__track { animation-play-state: paused; }
.logo-marquee__set {
  display: flex; align-items: center; gap: clamp(32px, 5vw, 60px);
  padding-right: clamp(32px, 5vw, 60px); flex: 0 0 auto;
}
.logo-marquee__set img { height: 26px; width: auto; object-fit: contain; filter: grayscale(1); opacity: .7; }
@keyframes logo-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .logo-marquee__track { animation: none; flex-wrap: wrap; justify-content: center; }
  .logo-marquee__set:not(:first-child) { display: none; }
  .logo-marquee__set { flex-wrap: wrap; justify-content: center; row-gap: 20px; padding-right: 0; }
  .logo-marquee { -webkit-mask-image: none; mask-image: none; }
}

/* ================= Act 3 — the problem (pan) ================= */
.problem [data-sc-stage] { display: flex; align-items: center; }
.problem .rail {
  display: flex; gap: clamp(20px, 3vw, 40px); padding: 0 clamp(20px, 6vw, 90px);
  align-items: stretch;
}
.problem .rail__lead { flex: 0 0 clamp(240px, 26vw, 380px); align-self: center; }
.problem .rail__lead h2 { color: var(--sc-ink); font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1.05; margin: 0; }
.problem .rail__lead-note {
  font-family: var(--sc-font-text); font-size: 14px; color: var(--sc-ink-soft);
  line-height: 1.5; margin: 18px 0 0; max-width: 32ch;
}
.problem .leak-card {
  flex: 0 0 clamp(300px, 34vw, 440px);
  border-radius: 16px; padding: 32px;
  display: flex; flex-direction: column; gap: 12px; justify-content: flex-start;
  box-shadow: 0 10px 28px -14px rgba(52, 42, 31, .28);
}
.problem .leak-card h3 { font-family: var(--sc-font-display); font-size: 1.7rem; margin: 0; }
/* Full-strength ink, not a dimmed opacity: opacity blends toward each card's
   own saturated background rather than toward white, so on the darker cards
   (violet especially) it silently dropped body text and the num badge below
   the 4.5:1 floor even though the base ink token itself passes cleanly. */
.problem .leak-card p { font-size: 15px; line-height: 1.55; margin: 0; }
.problem .leak-card .num { font-family: var(--sc-font-text); font-size: 12px; letter-spacing: .12em; }
/* Colour ties to each lens's own temperature rather than an arbitrary
   rotation: coral (warm, urgent) for money actively leaking out; violet
   (deep, singular) for risk concentrated in one place; teal (cool, distant)
   for opportunity going cold. */
.problem .leak-card:nth-child(2) { background: var(--coral); color: var(--coral-ink); }
.problem .leak-card:nth-child(3) { background: var(--violet); color: var(--violet-ink-strong); }
.problem .leak-card:nth-child(4) { background: var(--teal); color: var(--teal-ink); }

/* ================= Act 4 — the process (PEAK) ================= */
.process [data-sc-stage] {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 clamp(20px, 8vw, 120px);
  /* No position/overflow override here: the engine's .sc-stage rule needs
     position:sticky to actually pin, and position:relative on this same
     element silently wins that property in the cascade (a bug I shipped
     once already) and turns the whole act into normal scrolling content.
     position:sticky already works as a containing block for the absolutely
     positioned glow blobs below, so nothing extra is needed here. */
}
/* Two soft colour fields cross-fade behind the stage as the argument moves
   from Discovery (warm) to Implementation (cool) — driven straight off the
   act's own --sc-p, same mechanism as the collage tiles. */
.process .glow {
  position: absolute; border-radius: 50%; filter: blur(70px); pointer-events: none; z-index: 0;
}
.process .glow--a {
  width: min(50vw, 600px); height: min(50vw, 600px); left: -12%; top: 8%;
  background: var(--apricot); opacity: calc(.5 * (1 - var(--sc-p, 0)));
}
.process .glow--b {
  width: min(54vw, 640px); height: min(54vw, 640px); right: -14%; bottom: 4%;
  background: var(--teal); opacity: calc(.45 * var(--sc-p, 0));
}

.process .argument { max-width: 760px; position: relative; z-index: 2; min-height: clamp(260px, 34vh, 380px); width: 100%; }
.process .argument p {
  font-family: var(--sc-font-display);
  font-size: clamp(1.3rem, 2.6vw, 2.1rem); line-height: 1.32; margin: 0;
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
  border-radius: 22px; padding: clamp(26px, 4vw, 44px) clamp(28px, 5vw, 52px);
  box-shadow: 0 18px 40px -22px rgba(52, 42, 31, .38);
}
.process .argument p:nth-child(1) {
  background: var(--sc-surface); color: var(--sc-ink);
  border: 1px dashed color-mix(in srgb, var(--sc-ink) 35%, transparent); box-shadow: none;
}
/* Card colour follows the argument's own temperature: neutral before
   commitment, then warm-to-cool across Discovery -> Implementation, the same
   logic the glow cross-fade above already carries — apricot warmest at
   Discovery, cooling through the report hand-off to violet at the measured
   result. */
.process .argument p:nth-child(2) { background: var(--apricot); color: var(--apricot-ink); }
.process .argument p:nth-child(3) { background: var(--butter);  color: var(--butter-ink); }
.process .argument p:nth-child(4) { background: var(--teal);   color: var(--teal-ink); }
.process .argument p:nth-child(5) { background: var(--violet); color: var(--violet-ink-strong); }

/* Full-strength ink for the same reason as .leak-card above: opacity here
   blended toward each card's own background and dropped two of the four
   colour pairings below 4.5:1. */
.process .argument .stage-tag {
  display: block; font-family: var(--sc-font-text); font-size: 12px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; margin-bottom: 12px;
}
.process .argument .stage-tag + span { display: inline; }
/* The free-call tag runs a full sentence rather than a short label — shouting
   it in tracked capitals hurts readability more than it adds emphasis. */
.process .argument p:nth-child(1) .stage-tag { text-transform: none; letter-spacing: normal; }

.process .stepper {
  position: absolute; left: clamp(16px, 4vw, 40px); top: 50%; translate: 0 -50%;
  z-index: 2; display: flex; flex-direction: column; gap: 10px;
  list-style: none; margin: 0; padding: 0;
}
.process .stepper li {
  width: 4px; height: 26px; border-radius: 999px;
  --raw: calc((var(--sc-p, 0) - var(--step-at, 0)) / 0.09);
  background: color-mix(in srgb, var(--tick-color, var(--sc-ink)) calc(20% + 80% * clamp(0, var(--raw), 1)), transparent);
}
/* Below 640px there's no room at the card's edge, so the same stepper moves
   to a horizontal row above the card instead of disappearing — the process
   act is the longest pinned span on the page and mobile needs the "how much
   further" cue at least as much as desktop does. */
@media (max-width: 640px) {
  .process .stepper {
    left: 50%; top: clamp(16px, 5vh, 30px); translate: -50% 0;
    flex-direction: row; gap: 8px;
  }
  .process .stepper li { width: 22px; height: 4px; }
}

.process .cta-row {
  position: relative; z-index: 2; margin-top: clamp(32px, 5vh, 56px);
  display: flex; gap: 14px; flex-wrap: wrap; justify-content: center;
}

@media (prefers-reduced-motion: reduce) {
  .process .glow--a, .process .glow--b { opacity: .3; }
}

/* ================= Act 5 — reviews (flow) ================= */
.reviews { background: var(--sc-surface); }
.reviews .sc-wrap { max-width: 980px; }
.reviews h2 { color: var(--sc-ink); font-size: clamp(1.8rem, 3.4vw, 2.6rem); margin: 0 0 14px; }
/* A real, already-stated number standing in front of the honest placeholder
   below, so the highest-stakes ask (the close CTA right after this section)
   isn't preceded by an entirely empty proof beat. */
.review-proof {
  font-family: var(--sc-font-text); font-size: 15px; color: var(--sc-ink-soft);
  margin: 0 0 28px;
}
/* One reserved slot now that the owner-story video carries the real social
   proof — a single centred column, not a two-up grid with a hole in it. */
.review-grid { display: grid; grid-template-columns: minmax(0, 560px); justify-content: center; gap: 22px; }
.review-card--pending {
  border: 1px dashed color-mix(in srgb, var(--sc-ink) 40%, transparent);
  border-radius: 16px; padding: 40px 28px; background: transparent;
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 140px;
}
.review-card--pending p {
  font-family: var(--sc-font-text); font-size: 14px; font-weight: 500;
  font-style: italic; color: var(--sc-ink-soft); margin: 0;
}
.review-note {
  grid-column: 1 / -1; font-family: var(--sc-font-text); font-size: 13px; color: var(--sc-ink-soft);
  border-top: 1px dashed var(--line); padding-top: 16px; margin-top: 4px;
}
@media (max-width: 760px) { .review-grid { grid-template-columns: minmax(0, 1fr); } }

/* ================= Act 6 — close ================= */
/* Dark drifted ground: --sc-ink is redefined here and colour is restated on
   the same subtree, per taste.md's inheritance note (colour is inherited as
   a computed value, so redefining the token alone does not re-ink text that
   already resolved further up the tree). */
.close {
  --sc-ink: #FFFDFA; --sc-ink-soft: #C9BCAC;
  color: var(--sc-ink);
  display: flex; align-items: center; justify-content: center; text-align: center;
}
.close__inner { max-width: 640px; padding: 0 24px; }
.close h2 { color: var(--sc-ink); font-size: clamp(2rem, 4.4vw, 3.2rem); margin: 0 0 28px; }
.close .btn--primary { font-size: 17px; padding: 16px 30px; background: var(--sc-accent); color: var(--sc-accent-ink); }
.close__note { font-family: var(--sc-font-text); font-size: 14px; color: var(--sc-ink-soft); margin: 20px 0 0; }
.close__note a { color: var(--sc-ink); text-decoration: underline; text-underline-offset: 3px; }
.foot {
  position: absolute; left: 0; right: 0; bottom: 22px;
  display: flex; justify-content: center; gap: 18px; flex-wrap: wrap; padding: 0 20px;
  font-family: var(--sc-font-text); font-size: 12px; color: var(--sc-ink-soft);
}
.foot a { color: inherit; text-decoration: none; opacity: .85; }
.foot a:hover, .foot a:focus-visible { opacity: 1; text-decoration: underline; }

/* ================= The journey in depth ================= */
/* The page reads as stations on a route: each act arrives from below and
   behind — tilted back like the road ahead — settles flush while you are at
   it, then lifts past the camera as you leave. Driven by --je (arrival) and
   --jx (departure), published per act by the page script, plus the engine's
   own --sc-p inside pinned acts. Every rule uses the individual transform
   properties (translate / rotate), which compose with the engine's inline
   transform writes instead of overwriting them. Inspired by journey-map
   scroll sites, but built as actual depth rather than a drawn path. */
@media (prefers-reduced-motion: no-preference) {
  .hero-text, .reviews,
  .companies [data-sc-stage],
  .process [data-sc-stage],
  .close { perspective: 1400px; }
  .problem .rail { perspective: 1400px; }
  .process .argument { perspective: 1400px; }

  .hero-text .sc-wrap, .reviews .sc-wrap,
  .companies .collage,
  .problem .rail__lead,
  .process .argument, .process .cta-row,
  .close__inner {
    translate: 0
      calc((1 - var(--je, 1)) * 28px)
      calc((1 - var(--je, 1)) * -150px + var(--jx, 0) * 44px);
    rotate: x calc((1 - var(--je, 1)) * 5deg - var(--jx, 0) * 2.4deg);
  }

  /* Leak cards as signposts along the road: each one hinges on its left edge,
     angled away as the rail carries it in, swinging flush as it arrives. */
  .problem .leak-card { --ci: 0; transform-origin: left center; }
  .problem .leak-card:nth-child(3) { --ci: 1; }
  .problem .leak-card:nth-child(4) { --ci: 2; }
  .problem .leak-card {
    --jt: clamp(0, calc((var(--sc-p, 0) - var(--ci) * 0.24) * 2.6), 1);
    translate: 0 0 calc((1 - var(--jt)) * -90px);
    rotate: y calc((1 - var(--jt)) * 16deg);
  }

  /* Process cards travel the same route the client does: each chapter rises
     from deep, holds flush while it speaks, then passes the camera as the
     next one comes up. Windows mirror each card's data-sc-cue span; --wr is
     the precomputed reciprocal of the window width (calc multiplication is
     safe where division by a variable is not). */
  .process .argument p:nth-child(1) { --w0: 0;    --wr: 5; }
  .process .argument p:nth-child(2) { --w0: 0.16; --wr: 3.846; }
  .process .argument p:nth-child(3) { --w0: 0.38; --wr: 3.846; }
  .process .argument p:nth-child(4) { --w0: 0.60; --wr: 3.846; }
  .process .argument p:nth-child(5) { --w0: 0.78; --wr: 4.545; }
  .process .argument p {
    --ju: clamp(0, calc((var(--sc-p, 0) - var(--w0)) * var(--wr)), 1);
    --jin: clamp(0, calc(var(--ju) * 3.333), 1);
    --jout: clamp(0, calc((var(--ju) - 0.78) * 4.545), 1);
    translate: 0
      calc((1 - var(--jin)) * 14px)
      calc((1 - var(--jin)) * -160px + var(--jout) * 60px);
    rotate: x calc((1 - var(--jin)) * 7deg - var(--jout) * 3deg);
  }
  /* The closing chapter ends the act — it never recedes. */
  .process .argument p:nth-child(5) { --jout: 0; }
}
