/* ============================================================
   XQUBE GLOBAL — design system
   Ink ground · glass surfaces · purple structural · pink editorial
   ============================================================ */

:root {
  /* color */
  --bg: #0A0A0E;
  --bg-raised: #0D0D13;
  --surface: rgba(255, 255, 255, 0.035);
  --surface-strong: rgba(255, 255, 255, 0.065);
  /* what a frosted card looks like once the blur is taken away (phones) */
  --glass-flat: rgba(20, 20, 28, 0.82);
  --line: rgba(255, 255, 255, 0.09);
  --line-strong: rgba(255, 255, 255, 0.17);
  --text: #F2F3F7;
  --mist: #A6AAB8;
  --faint: #878C9C;
  --purple: #5B4CFF;
  --purple-bright: #6E60FF;
  --purple-soft: #948AFF;
  --pink: #FF4D80;
  --pink-soft: #FF7DA1;
  /* --faint stays >=4.5:1 on glass surfaces at small sizes */

  /* type */
  --sans: "Instrument Sans", "Helvetica Neue", Arial, sans-serif;
  --mono-f: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* rhythm — 4/8 base with vertical tiers (Material spacing scale) */
  --s1: 8px;    --s2: 16px;   --s3: 24px;   --s4: 32px;
  --s5: 48px;   --s6: 64px;   --s7: 96px;   --s8: 128px;
  --wrap: 1200px;
  --pad: clamp(24px, 5vw, 56px);
  --section-gap: clamp(128px, 19vh, 232px);
  --radius: 18px;
  --nav-h: 78px;

  color-scheme: dark;
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16.5px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, p, dl, dd, dt { margin: 0; }

::selection { background: rgba(91, 76, 255, 0.5); color: #fff; }

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

::-webkit-scrollbar { width: 11px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: #26262f; border-radius: 8px; border: 3px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: var(--purple); }

.skip-link {
  position: fixed; top: -60px; left: 20px; z-index: 200;
  background: var(--purple); color: #fff;
  padding: 10px 18px; border-radius: 8px; font-weight: 600;
  transition: top 0.2s;
}
.skip-link:focus { top: 16px; }

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

/* no-JS: the burger can't do anything, hide it (single-page anchors remain in content) */
.no-js .nav-burger { display: none !important; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding-left: var(--pad); padding-right: var(--pad); }
.wrap-narrow { max-width: 860px; }
.mono { font-family: var(--mono-f); font-variant-numeric: tabular-nums; }

/* ---------- atmosphere ---------- */
.grain {
  /* inset: 0, not -50%. This is position:FIXED with a tiling texture, so an
     element twice the viewport in each direction paints FOUR TIMES the area
     for a result that is pixel-identical — the tile phase shifts, and the
     texture is random noise at 4.2% opacity. Under mix-blend-mode the
     compositor has to read the backdrop back for every one of those pixels,
     on every frame anything beneath it moves, which on this site is always. */
  position: fixed; inset: 0; z-index: 90; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
  opacity: 0.042;
  mix-blend-mode: overlay;
}
.cursor-glow {
  position: fixed; left: 0; top: 0; z-index: 1; pointer-events: none;
  width: 780px; height: 780px; border-radius: 50%;
  background: radial-gradient(circle, rgba(91, 76, 255, 0.16), rgba(91, 76, 255, 0.05) 40%, transparent 68%);
  mix-blend-mode: screen;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.6s ease;
}
.js .cursor-glow.on { opacity: 1; }
.scroll-progress {
  position: fixed; top: 0; left: 0; z-index: 130;
  height: 2px; width: 100%;
  background: linear-gradient(90deg, var(--purple), var(--pink));
  transform-origin: 0 50%;
  transform: scaleX(var(--sp, 0));
}

/* ---------- reveal system (JS enhances; content visible without JS) ----------
   The hidden state lives ONLY on :not(.in), so once revealed the element's own
   transform rules (tilt, hover lift, door tilt) apply untouched. */
.js .reveal {
  transition: opacity 0.75s cubic-bezier(0.22, 0.6, 0.2, 1), transform 0.75s cubic-bezier(0.22, 0.6, 0.2, 1);
}
/* interactive tiles keep their snappier hover-transform timing after reveal */
.js .proof-tile.reveal,
.js .door.reveal {
  transition: opacity 0.75s cubic-bezier(0.22, 0.6, 0.2, 1), transform 0.4s cubic-bezier(0.3, 0.7, 0.3, 1), border-color 0.35s ease, box-shadow 0.35s ease;
}
.js .reveal:not(.in) {
  opacity: 0;
  transform: translateY(22px);
}
.js .reveal.d1 { transition-delay: 0.08s; }
.js .reveal.d2 { transition-delay: 0.16s; }
.js .reveal.d3 { transition-delay: 0.24s; }

/* .rise: headlines emerge from a mask, not a fade */
.js .rise {
  transition: opacity 0.9s cubic-bezier(0.22, 0.6, 0.2, 1), transform 0.9s cubic-bezier(0.22, 0.6, 0.2, 1), clip-path 0.9s cubic-bezier(0.22, 0.6, 0.2, 1);
}
.js .rise:not(.in) {
  opacity: 0;
  transform: translateY(40px);
  clip-path: inset(0 0 92% 0);
}
.js .rise.in { clip-path: inset(-20% 0 -20% 0); }

/* ---------- type ---------- */
.kicker {
  display: flex; align-items: center; gap: 14px;
  font-size: 12.5px; letter-spacing: 0.22em; font-weight: 500;
  color: var(--faint);
}
.kicker-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--pink);
  box-shadow: 0 0 14px rgba(255, 77, 128, 0.9);
  animation: pulse 2.6s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.hero-h1 {
  font-size: clamp(40px, 5.8vw, 78px);
  line-height: 1.03;
  letter-spacing: -0.031em;
  font-weight: 600;
  margin: 26px 0 28px;
  text-wrap: balance;
}
.h2 {
  font-size: clamp(30px, 4.4vw, 54px);
  line-height: 1.08;
  letter-spacing: -0.026em;
  font-weight: 600;
  text-wrap: balance;
  max-width: 900px;
}
.h2-editorial {
  font-size: clamp(34px, 5.2vw, 66px);
  max-width: 1020px;
}
.ink-pink {
  color: var(--pink);
  text-shadow: 0 0 28px rgba(255, 77, 128, 0.35);
}
.lede {
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.75;
  color: var(--mist);
  max-width: 58ch;
}
.body-lg {
  font-size: clamp(16.5px, 1.4vw, 18.5px);
  line-height: 1.8;
  color: var(--mist);
  max-width: 62ch;
}
.intro { max-width: 68ch; margin-top: var(--s4); }

/* scroll-scrubbed word illumination (chapter 02, pull-quote) */
.js [data-words] .w {
  opacity: 0.12;
  transition: opacity 0.35s ease;
}
.js [data-words] .w.lit { opacity: 1; }

/* ---------- buttons ---------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; gap: 10px;
  border-radius: 100px;
  font-family: var(--sans);
  font-weight: 600; font-size: 15px; line-height: 1;
  padding: 16px 28px;
  border: 1px solid transparent;
  cursor: pointer;
  transform: translate(var(--mtx, 0px), var(--mty, 0px));
  transition: transform 0.22s cubic-bezier(0.3, 0.7, 0.3, 1), box-shadow 0.35s ease, background 0.35s ease, border-color 0.35s ease, color 0.35s ease;
  will-change: transform;
}
.btn .btn-arrow { transition: transform 0.3s cubic-bezier(0.3, 0.7, 0.3, 1); }
.btn:hover .btn-arrow { transform: translateX(5px); }
.btn-primary {
  background: var(--purple);
  color: #fff;
  overflow: hidden;
}
.btn-primary::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.22) 50%, transparent 80%);
  transform: translateX(-130%);
  transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
}
.btn-primary:hover::before { transform: translateX(130%); }
.btn-primary:hover {
  background: var(--purple-bright);
  box-shadow: 0 8px 34px rgba(91, 76, 255, 0.5);
}
.btn-ghost {
  border-color: var(--line-strong);
  background: rgba(255, 255, 255, 0.02);
  color: var(--text);
}
.btn-ghost:hover {
  border-color: var(--purple-soft);
  background: rgba(91, 76, 255, 0.09);
  box-shadow: 0 6px 26px rgba(91, 76, 255, 0.22);
}
.btn-sm { padding: 11px 20px; font-size: 13px; gap: 8px; }

/* ---------- nav ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 120;
}
.nav-inner {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  height: var(--nav-h);
  padding: 0 clamp(20px, 3vw, 36px);
  background: rgba(10, 10, 14, 0.55);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid transparent;
  transition: background 0.4s ease, border-color 0.4s ease;
}
.nav.scrolled .nav-inner {
  background: rgba(10, 10, 14, 0.78);
  border-bottom-color: var(--line);
}
.brand { display: inline-flex; align-items: center; gap: 12px; }
.brand-mark { width: 44px; height: auto; }
.brand-word {
  font-weight: 700; font-size: 17px; letter-spacing: 0.04em;
}
.brand-word em {
  font-style: normal; font-weight: 400; color: var(--mist); letter-spacing: 0.12em;
}
.nav-links { display: flex; gap: clamp(18px, 2.6vw, 38px); }
.nav-links a {
  position: relative;
  font-size: 14.5px; font-weight: 500; color: var(--mist);
  padding: 6px 0;
  transition: color 0.3s ease;
}
.nav-links a::after {
  content: "";
  position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: linear-gradient(90deg, var(--purple), var(--pink));
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.35s cubic-bezier(0.3, 0.7, 0.3, 1);
}
.nav-links a:hover,
.nav-links a:focus-visible { color: var(--text); }
.nav-links a:hover::after,
.nav-links a:focus-visible::after { transform: scaleX(1); }
.nav-cta-wrap { display: flex; align-items: center; gap: 14px; }

.nav-burger {
  display: none;
  width: 42px; height: 42px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  cursor: pointer;
  flex-direction: column; align-items: center; justify-content: center; gap: 6px;
}
.nav-burger span {
  display: block; width: 18px; height: 1.6px;
  background: var(--text);
  transition: transform 0.35s ease, opacity 0.35s ease;
}
.nav-burger.open span:first-child { transform: translateY(3.8px) rotate(45deg); }
.nav-burger.open span:last-child { transform: translateY(-3.8px) rotate(-45deg); }

.mobile-menu {
  position: fixed; inset: 0; z-index: 110;
  background: rgba(8, 8, 12, 0.92);
  backdrop-filter: blur(26px);
  -webkit-backdrop-filter: blur(26px);
  display: flex; flex-direction: column; gap: 40px;
  padding: 100px var(--pad) 60px;
  overflow-y: auto;
  opacity: 0; pointer-events: none;
  visibility: hidden;
  transition: opacity 0.35s ease, visibility 0s linear 0.35s;
}
.mobile-menu.open {
  opacity: 1; pointer-events: auto;
  visibility: visible;
  transition: opacity 0.35s ease;
}
.mobile-links { display: flex; flex-direction: column; gap: 8px; margin-top: auto; }
.mobile-menu .mobile-meta { margin-bottom: auto; }
.mobile-links a {
  display: flex; align-items: baseline; gap: 18px;
  font-size: clamp(26px, 7vw, 34px); font-weight: 600; letter-spacing: -0.02em;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.mobile-links a .mono { font-size: 13px; color: var(--purple-soft); }
.mobile-meta { display: flex; flex-direction: column; gap: 10px; font-size: 14px; color: var(--mist); }

/* ---------- live chapter HUD ---------- */
.chapter-hud {
  position: fixed; left: 26px; bottom: 22px; z-index: 80;
  display: flex; align-items: center; gap: 12px;
  font-size: 11px; letter-spacing: 0.14em;
  color: var(--faint);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  pointer-events: none;
}
.chapter-hud.on { opacity: 1; transform: none; }
.hud-index { color: var(--mist); }
.hud-index em { font-style: normal; color: var(--purple-soft); text-shadow: 0 0 12px rgba(91, 76, 255, 0.7); }
.hud-sep { width: 34px; height: 1px; background: linear-gradient(90deg, var(--purple), transparent); }
.hud-name { letter-spacing: 0.18em; }

/* ---------- chapter rail ---------- */
.rail {
  position: fixed; right: 22px; top: 50%; z-index: 80;
  transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 16px;
}
.rail-tick {
  position: relative;
  display: flex; align-items: center; justify-content: flex-end;
}
.rail-num {
  font-size: 11px; color: var(--mist);
  opacity: 0.8;
  transition: opacity 0.3s ease, color 0.3s ease, text-shadow 0.3s ease;
}
.rail-tick:hover .rail-num { opacity: 1; color: var(--text); }
.rail-tick.active .rail-num {
  opacity: 1; color: var(--purple-soft);
  text-shadow: 0 0 14px rgba(91, 76, 255, 0.8);
}
.rail-tip {
  position: absolute; right: 34px; top: 50%;
  transform: translateY(-50%) translateX(6px);
  white-space: nowrap;
  font-size: 12px; color: var(--mist);
  background: rgba(13, 13, 19, 0.9);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 12px;
  opacity: 0; pointer-events: none;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.rail-tick:hover .rail-tip,
.rail-tick:focus-visible .rail-tip { opacity: 1; transform: translateY(-50%) translateX(0); }
.rail-tick:focus-visible .rail-num { opacity: 1; color: var(--text); }

/* ---------- hero ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: calc(var(--nav-h) + 40px);
  padding-bottom: 110px;
  overflow: hidden;
}
.hero-field { position: absolute; inset: 0; pointer-events: none; }
.blade { position: absolute; will-change: transform; }
.blade-a {
  width: 58vw; height: 58vw; right: -14vw; top: -20vw;
  background: conic-gradient(from 215deg at 55% 45%, transparent 0deg, rgba(91, 76, 255, 0.5) 55deg, rgba(91, 76, 255, 0.08) 130deg, transparent 175deg);
  filter: blur(64px);
  opacity: 0.55;
  animation: drift-a 30s ease-in-out infinite alternate;
}
.blade-b {
  width: 46vw; height: 46vw; left: -16vw; bottom: -26vw;
  background: conic-gradient(from 30deg at 50% 50%, transparent 0deg, rgba(255, 77, 128, 0.38) 60deg, rgba(255, 77, 128, 0.05) 130deg, transparent 180deg);
  filter: blur(70px);
  opacity: 0.5;
  animation: drift-b 36s ease-in-out infinite alternate;
}
.blade-c {
  width: 30vw; height: 30vw; left: 42vw; top: 8vh;
  background: radial-gradient(circle, rgba(91, 76, 255, 0.2), transparent 65%);
  filter: blur(50px);
  animation: drift-c 24s ease-in-out infinite alternate;
}
@keyframes drift-a { from { transform: rotate(0deg) translateY(0); } to { transform: rotate(14deg) translateY(5vh); } }
@keyframes drift-b { from { transform: rotate(0deg); } to { transform: rotate(-16deg) translateX(6vw); } }
@keyframes drift-c { from { transform: translate(0, 0) scale(1); } to { transform: translate(-6vw, 6vh) scale(1.25); } }

/* the number-field: a persistent particle world behind the whole film.
   During the prologue ~2100 digits assemble into the X mark; afterwards
   they disperse into ambient dust that drifts behind every scene. */
.hero-canvas-wrap {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 0;
}
#hero-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
.hero-mark-fallback {
  position: absolute;
  left: 50%; top: 40%;
  transform: translate(-50%, -50%);
  width: min(32vw, 440px); height: auto;
  opacity: 0.8;
  filter: drop-shadow(0 0 60px rgba(91, 76, 255, 0.35));
  z-index: 1;
}
.js .hero-mark-fallback { display: none; }

.hero-grid { position: relative; z-index: 2; width: 100%; }
.hero-copy { max-width: 760px; }
.cta-row { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: 0; }

.proof-row {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s2);
  margin-top: 0;
}
.proof-tile {
  position: relative;
  padding: var(--s3) var(--s3) var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  padding: 24px 24px 20px;
  overflow: hidden;
  transition: transform 0.35s cubic-bezier(0.3, 0.7, 0.3, 1), border-color 0.35s ease, box-shadow 0.35s ease;
}
.proof-tile:hover {
  transform: translateY(-4px);
  border-color: rgba(148, 138, 255, 0.45);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45), 0 0 24px rgba(91, 76, 255, 0.12);
}
.proof-value {
  display: block;
  font-size: clamp(28px, 3vw, 40px);
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}
.proof-label { display: block; font-size: 13.5px; line-height: 1.5; color: var(--mist); }

/* liquid glass: specular top edge on every glass surface */
.proof-tile, .svc-card, .case-card, .founders-panel, .door, .chip-link, .nav-inner, .mobile-menu {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09);
}
.proof-tile, .svc-card, .founders-panel {
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
}


/* spotlight (cursor-tracking inner light + border light on glass cards) */
[data-spot] { position: relative; }
[data-spot]::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%), rgba(148, 138, 255, 0.12), transparent 65%);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
[data-spot]:hover::after { opacity: 1; }
[data-spot]::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%), rgba(178, 170, 255, 0.85), rgba(255, 125, 161, 0.25) 55%, transparent 75%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
[data-spot]:hover::before { opacity: 1; }

.scroll-cue {
  opacity: var(--cueop, 1);
  position: absolute; left: 50%; bottom: 24px; z-index: 2;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  font-size: 10px; letter-spacing: 0.34em; color: var(--faint);
}
.scroll-cue-line {
  width: 1px; height: 44px;
  background: linear-gradient(180deg, var(--purple-soft), transparent);
  animation: cue 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  transform-origin: 0 0;
}
@keyframes cue {
  0% { transform: scaleY(0); opacity: 0; }
  35% { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1) translateY(44px); opacity: 0; }
}

/* ---------- sections / act markers ---------- */
.section { position: relative; padding: var(--section-gap) 0 0; overflow-x: clip; }
.section:last-of-type { padding-bottom: var(--section-gap); }
.section-center { text-align: center; }
.section-center .body-lg { margin-left: auto; margin-right: auto; }
.section-center .h2 { margin-left: auto; margin-right: auto; }

/* ghost chapter numerals — huge outlined digits parallaxing behind content */
.ghost-num {
  position: absolute;
  right: 0; top: 4%;
  z-index: 0;
  font-size: clamp(180px, 30vw, 480px);
  font-weight: 700;
  line-height: 0.8;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(148, 138, 255, 0.09);
  letter-spacing: -0.06em;
  pointer-events: none;
  user-select: none;
  transform: translateY(var(--gy, 0px));
  will-change: transform;
}
.section:nth-of-type(even) .ghost-num { right: auto; left: 0; }
#begin .ghost-num, #doors .ghost-num { -webkit-text-stroke-color: rgba(255, 77, 128, 0.08); }
.section .wrap { position: relative; z-index: 1; }

/* act separators removed — the act cut announces each act instead */

/* ---------- act I : fracture ---------- */
.js .fracture-scene { height: 300vh; position: relative; }
.js .fracture-sticky {
  position: sticky; top: 0;
  height: 100vh;
  display: flex; align-items: center;
  overflow: hidden;
}
.fracture-grid {
  display: grid;
  grid-template-columns: minmax(300px, 440px) 1fr;
  gap: clamp(40px, 6vw, 90px);
  align-items: center;
  width: 100%;
}
.fracture-steps { display: flex; flex-direction: column; gap: 28px; }
.fstep {
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.75;
  color: var(--mist);
  border-left: 2px solid var(--line);
  padding-left: 22px;
  transition: opacity 0.5s ease, border-color 0.5s ease, color 0.5s ease;
}
.js .fstep { opacity: 0.2; }
.js .fstep.active {
  opacity: 1;
  border-color: var(--pink);
  color: var(--text);
}
.fracture-stage {
  position: relative;
  width: min(520px, 100%);
  height: 420px;
  margin-left: auto;
  --p: 0;
}
/* bold glass cards — each names one party. Opaque enough that the dot-aura
   riding behind never touches the text. As the mark forms (--mark) the cards
   fade: their job (naming the three) is done, and the brand they compose
   takes the stage. */
.fcard {
  position: absolute;
  width: 224px;
  padding: 18px 20px 20px;
  border: 1px solid var(--line-strong);
  border-radius: 16px;
  background: rgba(15, 15, 22, 0.9);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  box-shadow: 0 22px 54px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  opacity: calc(1 - 0.92 * var(--mark, 0));
}
.fcard-tag {
  display: block;
  font-size: 11px; letter-spacing: 0.16em; color: var(--text);
  font-weight: 500;
  margin-bottom: 14px;
}
.fcard-frag {
  display: block; height: 6px; border-radius: 3px;
  background: rgba(255, 255, 255, 0.14);
  margin-bottom: 8px;
}
.fcard-frag.w70 { width: 70%; } .fcard-frag.w65 { width: 65%; } .fcard-frag.w60 { width: 60%; }
.fcard-frag.w55 { width: 55%; } .fcard-frag.w45 { width: 45%; } .fcard-frag.w40 { width: 40%; }
.fcard.repelled .fcard-frag { background: rgba(255, 77, 128, 0.4); }

/* scattered at --p 0; as --p rises the three converge onto ONE column
   (all at left 148, evenly stacked, rotations straightened). */
.fcard-a {
  left: 6px; top: 24px;
  transform: translate(calc(142px * var(--p, 0) + var(--dx, 0px)), calc(60px * var(--p, 0) + var(--dy, 0px)))
             rotate(calc(-6deg + 6deg * var(--p, 0) + var(--dr, 0deg)));
}
.fcard-b {
  left: 256px; top: 160px;
  transform: translate(calc(-108px * var(--p, 0) + var(--dx, 0px)), calc(18px * var(--p, 0) + var(--dy, 0px)))
             rotate(calc(4deg - 4deg * var(--p, 0) + var(--dr, 0deg)));
}
.fcard-c {
  left: 300px; top: 300px;
  transform: translate(calc(-152px * var(--p, 0) + var(--dx, 0px)), calc(-24px * var(--p, 0) + var(--dy, 0px)))
             rotate(calc(6deg - 6deg * var(--p, 0) + var(--dr, 0deg)));
}
/* a spine binds the stacked column, then fades as the mark forms */
.fracture-stage::after {
  content: "";
  position: absolute; left: 140px; top: 78px;
  width: 1px; height: 214px;
  background: linear-gradient(180deg, transparent, rgba(148, 138, 255, 0.55), transparent);
  transform: scaleY(var(--p, 0)); transform-origin: 50% 50%;
  opacity: calc(var(--p, 0) * (1 - var(--mark, 0)));
  pointer-events: none;
}

/* the cards are grabbable — and they refuse to be put together */
.js .fcard { cursor: grab; touch-action: pan-y; }
.js .fcard.dragging { cursor: grabbing; z-index: 5; }
.js .fcard.repelled {
  border-color: rgba(255, 77, 128, 0.7);
  box-shadow: 0 22px 54px rgba(0, 0, 0, 0.55), 0 0 34px rgba(255, 77, 128, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
.fcard-hint {
  position: absolute; left: 50%; bottom: -6px;
  transform: translateX(-50%);
  font-size: 10px; letter-spacing: 0.2em;
  color: var(--faint);
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
  white-space: nowrap;
}
.js .fracture-stage:not(.done) .fcard-hint { opacity: 0.75; }
.fcard-hint b { color: var(--pink-soft); font-weight: 400; }

/* live cross-border clocks */
.clocks {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--s1);
  margin-top: var(--s5);
}
/* TWO SHORES, TWO ROWS. The six US zones want ~847px and the narrow column
   they sit in is 748px, so left to flex-wrap the sweep broke after CST and
   dropped EST down beside IST — the US line split, India no longer alone.
   The rows are explicit now, and the US row is allowed to out-run the column
   (column flex + align-items:center overflows it evenly on both sides, so it
   stays centred on the page). max-width keeps it inside the viewport, and
   below that it simply wraps again rather than spilling. */
.clocks:has(.clocks-row) {
  flex-direction: column;
  align-items: center;
  flex-wrap: nowrap;
}
.clocks-row {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--s1);
}
.clocks-us { width: max-content; max-width: 94vw; }
.clock {
  display: flex; align-items: baseline; gap: 10px;
  border: 1px solid var(--line);
  border-radius: 100px;
  background: var(--surface);
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: 9px 18px;
  font-size: 12px; letter-spacing: 0.1em;
  color: var(--faint);
}
.clock-time { color: var(--text); font-size: 13.5px; letter-spacing: 0.04em; }
.clock-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--purple-soft);
  box-shadow: 0 0 10px rgba(148, 138, 255, 0.9);
  animation: pulse 2s ease-in-out infinite;
}
.clock.is-open .clock-dot { background: var(--pink); box-shadow: 0 0 10px rgba(255, 77, 128, 0.9); }

.no-js .fracture-stage { --p: 1; }

/* diagnosis scan: a light sweep across the chapter 06 headline */
.scan-target { position: relative; }
.js .scan-target::after {
  content: "";
  position: absolute; inset: -10% -4%;
  background: linear-gradient(100deg, transparent 42%, rgba(255, 77, 128, 0.16) 50%, transparent 58%);
  transform: translateX(-120%);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .js .scan-target.in::after { animation: scan 1.6s cubic-bezier(0.4, 0.2, 0.2, 1) 0.5s 1 both; }
}
@keyframes scan {
  from { transform: translateX(-120%); }
  to { transform: translateX(120%); }
}

/* ---------- act II : editorial ---------- */
.editorial-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 88px);
  margin-top: var(--s6);
}

/* ---------- act II : services ---------- */
/* THE LEDGER SPINE — seven disciplines as one numbered index, three movements,
   held on a single line. Inherently vertical, so it is the mobile layout too. */
.svc-spine {
  --spine-pad: clamp(30px, 4vw, 56px);
  position: relative;
  margin-top: clamp(40px, 6vh, 74px);
  padding-left: var(--spine-pad);
}
/* the accountable line: a faint static rail with a lit thread that draws down it */
.svc-spine-line {
  position: absolute; left: 7px; top: 6px; bottom: 6px;
  width: 1px;
  background: rgba(148, 138, 255, 0.16);
}
.svc-thread-line {
  display: block; width: 100%; height: 100%;
  background: linear-gradient(180deg, var(--purple), var(--pink));
  box-shadow: 0 0 12px rgba(91, 76, 255, 0.5);
  opacity: 0.7;
  transform: scaleY(var(--tdraw, 1)); transform-origin: 50% 0;
}
@media (prefers-reduced-motion: no-preference) {
  .js .svc-thread-line { --tdraw: 0; }
}

.svc-move + .svc-move { margin-top: clamp(32px, 4.5vh, 60px); }
.svc-move-head { position: relative; margin-bottom: var(--s2); }
.svc-move-name {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px; letter-spacing: 0.22em; text-transform: uppercase;
  font-weight: 500; color: var(--pink-soft);
}
.svc-move-desc { font-size: 13.5px; line-height: 1.6; color: var(--faint); margin-top: 8px; max-width: 60ch; }
.svc-move-head::before {
  content: ""; position: absolute; left: calc(-1 * var(--spine-pad) + 4px); top: 5px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--pink); box-shadow: 0 0 12px rgba(255, 77, 128, 0.7);
}

.svc-card {
  position: relative;
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 clamp(16px, 2vw, 30px);
  padding: clamp(18px, 2.3vh, 26px) clamp(8px, 1.2vw, 18px);
  border-top: 1px solid var(--line);
  transition: background 0.3s ease;
}
.svc-move-head + .svc-card { border-top: 0; }
.svc-num { font-size: 12px; letter-spacing: 0.08em; color: var(--purple-soft); }
.svc-body { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.svc-name {
  font-size: clamp(18px, 1.9vw, 23px); font-weight: 600;
  letter-spacing: -0.012em; color: var(--text);
  transition: color 0.3s ease;
}
.svc-line { font-size: 14px; line-height: 1.55; color: var(--mist); max-width: 56ch; }
.svc-arrow {
  align-self: center;
  font-size: 16px; color: var(--faint);
  transform: translateX(-4px);
  transition: transform 0.3s cubic-bezier(0.3, 0.7, 0.3, 1), color 0.3s ease;
}
/* the node this service holds on the spine */
.svc-card::before {
  content: ""; position: absolute;
  left: calc(-1 * var(--spine-pad) + 4px);
  top: calc(clamp(18px, 2.3vh, 26px) + 9px);
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--bg); border: 1px solid rgba(148, 138, 255, 0.55);
  transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.svc-card:hover, .svc-card:focus-visible {
  background: linear-gradient(90deg, rgba(148, 138, 255, 0.07), transparent 72%);
  outline: none;
}
.svc-card:hover .svc-name, .svc-card:focus-visible .svc-name { color: var(--text); }
.svc-card:hover .svc-arrow, .svc-card:focus-visible .svc-arrow { transform: translateX(2px); color: var(--purple-soft); }
/* hover, keyboard focus, or a pulse arriving from another discipline lights the node */
.svc-card:hover::before, .svc-card:focus-visible::before, .svc-card.ping::before {
  background: var(--pink); border-color: var(--pink);
  box-shadow: 0 0 14px rgba(255, 77, 128, 0.8);
}

@media (max-width: 560px) {
  .svc-spine { --spine-pad: 22px; }
  .svc-card { grid-template-columns: 40px minmax(0, 1fr); gap: 4px 12px; }
  .svc-arrow { grid-column: 2; justify-self: start; align-self: start; transform: none; margin-top: 4px; }
}

/* ---------- act III : case studies ---------- */
.case-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 2vw, 24px);
  margin-top: 54px;
  perspective: 1400px;
}
.case-card {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  padding: 26px 26px 24px;
  overflow: hidden;
  opacity: var(--sop, 1);
  transform: perspective(1000px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) rotate(var(--srot, 0deg)) translateY(var(--sty, 0px));
  transition: border-color 0.4s ease, box-shadow 0.4s ease;
}
/* scroll-scrub entrance: scattered and tilted until they straighten into place */
@media (prefers-reduced-motion: no-preference) {
  .js .case-card:nth-child(1) { --srot: -3.5deg; --sty: 70px; --sop: 0; }
  .js .case-card:nth-child(2) { --srot: 2.5deg; --sty: 110px; --sop: 0; }
  .js .case-card:nth-child(3) { --srot: -2deg; --sty: 150px; --sop: 0; }
}
.case-card:hover {
  border-color: rgba(148, 138, 255, 0.42);
  box-shadow: 0 22px 54px rgba(0, 0, 0, 0.5), 0 0 34px rgba(91, 76, 255, 0.1);
}
.case-kicker {
  font-size: 10.5px; letter-spacing: 0.16em; line-height: 1.7;
  color: var(--faint);
  margin-bottom: 16px;
}
.case-title {
  font-size: clamp(19px, 1.8vw, 23px);
  font-weight: 600; line-height: 1.3; letter-spacing: -0.015em;
  margin-bottom: 26px;
}
.case-stats { display: flex; flex-direction: column; gap: 0; }
.case-stat {
  display: flex; align-items: baseline; gap: var(--s3);
  border-top: 1px solid var(--line);
  padding: var(--s2) 0;
}
.case-stat dt {
  font-size: 24px; font-weight: 500; letter-spacing: -0.02em;
  color: var(--text);
  min-width: 96px;
  white-space: nowrap;
}
.case-unit { font-size: 13px; color: var(--mist); letter-spacing: 0; }
.case-stat dd { font-size: 13px; line-height: 1.55; color: var(--mist); }
.case-sheen {
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, 0.07) 50%, transparent 65%);
  transform: translateX(-130%);
  pointer-events: none;
}
.case-card:hover .case-sheen {
  transform: translateX(130%);
  transition: transform 1.1s cubic-bezier(0.4, 0.2, 0.2, 1);
}

/* ---------- act III : people ---------- */
.people-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(48px, 7vw, 112px);
  align-items: start;
}
.people-copy .body-lg { margin-top: 30px; }
.pull-quote {
  margin-top: 34px;
  font-size: clamp(21px, 2.3vw, 27px);
  line-height: 1.45;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--pink);
  border-left: 2px solid var(--pink);
  padding-left: 24px;
  text-shadow: 0 0 30px rgba(255, 77, 128, 0.25);
}
.founders-panel {
  padding: var(--s4) var(--s4) var(--s2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  overflow: hidden;
}
.founders-head {
  font-size: 11px; letter-spacing: 0.2em; color: var(--faint);
  margin-bottom: 16px;
}

/* ---------- the founders' photograph, cut into three ----------
   One negative, three panes: each holds exactly one third of the frame,
   so flush they are the original picture and nothing is lost. The studio
   backdrop is the page's own black, so the foot of the picture is masked
   away instead of cropped — the three of them stand in the section
   rather than inside a box. */
.fphoto {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: 0 0 var(--s2);
}
.fpane {
  display: block;
  aspect-ratio: 3 / 4;
  /* the strip renders the frame at panel width (~373px), so it never needs
     the full 1800px plate: 1100 covers desktop at 2x, 700 covers a phone */
  background-image: url(../assets/founders-1100.jpg?v=2);
  background-repeat: no-repeat;
  background-size: 300% auto;   /* the three panes span one frame */
  background-position: 0% 0%;
  -webkit-mask-image: linear-gradient(180deg, #000 60%, rgba(0, 0, 0, 0.4) 84%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 60%, rgba(0, 0, 0, 0.4) 84%, transparent 100%);
}
.fpane-2 { background-position: 50% 0%; }
.fpane-3 { background-position: 100% 0%; }
@media (max-width: 980px) {
  .fpane { background-image: url(../assets/founders-700.jpg?v=2); }
}

/* they arrive as three separate people and land as one firm */
@media (prefers-reduced-motion: no-preference) and (min-width: 981px) {
  .js .fpane { transition: transform 1.15s cubic-bezier(0.22, 0.6, 0.2, 1); }
  .js .fphoto:not(.in) .fpane-1 { transform: translate3d(-15px, -9px, 0); }
  .js .fphoto:not(.in) .fpane-2 { transform: translate3d(0, 7px, 0); }
  .js .fphoto:not(.in) .fpane-3 { transform: translate3d(15px, -6px, 0); }
  .js .fphoto.in .fpane { transform: none; }
}
.founder-row {
  display: flex; flex-direction: column; gap: 6px;
  border-top: 1px solid var(--line);
  padding: var(--s3) 0;
  transition: padding-left 0.35s cubic-bezier(0.3, 0.7, 0.3, 1);
}
.founder-row:hover { padding-left: 10px; }
.founder-name { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.founder-role { font-size: 13.5px; color: var(--mist); }
.founder-creds {
  font-size: 11.5px; letter-spacing: 0.06em; color: var(--faint);
  transition: color 0.35s ease;
}
.founder-row:hover .founder-creds { color: var(--purple-soft); }

/* ---------- act IV : doors ---------- */
.doors-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(18px, 2.6vw, 30px);
  margin-top: 30px;
  perspective: 1600px;
}
.door {
  position: relative;
  display: flex; flex-direction: column;
  min-height: 400px;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--surface);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  padding: clamp(28px, 3.4vw, 46px);
  overflow: hidden;
  opacity: var(--sop, 1);
  transform: perspective(1600px) rotateY(calc(var(--swing, 0deg) + var(--dry, 0deg)));
  transition: border-color 0.45s ease, box-shadow 0.45s ease;
}
/* the doors swing shut to face you as you arrive at the threshold */
@media (prefers-reduced-motion: no-preference) {
  .js .door-biz { --swing: 22deg; --sop: 0; }
  .js .door-cpa { --swing: -22deg; --sop: 0; }
}
.door::before {
  content: "";
  position: absolute; inset: 0;
  opacity: 0.3;
  transition: opacity 0.6s ease;
  pointer-events: none;
}
.door-biz::before {
  background:
    radial-gradient(90% 110% at 100% 100%, rgba(91, 76, 255, 0.34), transparent 60%),
    linear-gradient(215deg, rgba(91, 76, 255, 0.12), transparent 45%);
}
.door-cpa::before {
  background:
    radial-gradient(90% 110% at 0% 100%, rgba(255, 77, 128, 0.3), transparent 60%),
    linear-gradient(145deg, rgba(255, 77, 128, 0.1), transparent 45%);
}
.door:hover::before { opacity: 0.85; }
.door-biz:hover { border-color: rgba(148, 138, 255, 0.55); box-shadow: 0 26px 70px rgba(0, 0, 0, 0.55), 0 0 44px rgba(91, 76, 255, 0.2); }
.door-cpa:hover { border-color: rgba(255, 125, 161, 0.5); box-shadow: 0 26px 70px rgba(0, 0, 0, 0.55), 0 0 44px rgba(255, 77, 128, 0.18); }

.door-slit {
  position: absolute; top: 7%; bottom: 7%;
  width: 2px;
  border-radius: 2px;
  transition: width 0.5s cubic-bezier(0.3, 0.7, 0.3, 1), box-shadow 0.5s ease;
  opacity: var(--slitop, 0.5);
}
.door-biz .door-slit {
  right: 0;
  background: linear-gradient(180deg, transparent, var(--purple) 30%, var(--purple) 70%, transparent);
}
.door-cpa .door-slit {
  left: 0;
  background: linear-gradient(180deg, transparent, var(--pink) 30%, var(--pink) 70%, transparent);
}
.door-biz:hover .door-slit { width: 7px; opacity: 1; box-shadow: 0 0 26px rgba(91, 76, 255, 0.8); }
.door-cpa:hover .door-slit { width: 7px; opacity: 1; box-shadow: 0 0 26px rgba(255, 77, 128, 0.75); }

.door-label { font-size: 11px; letter-spacing: 0.2em; color: var(--faint); margin-bottom: auto; }
.door-title {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 600; letter-spacing: -0.02em; line-height: 1.15;
  margin-top: 80px; margin-bottom: 14px;
}
.door-desc { font-size: 15px; line-height: 1.7; color: var(--mist); max-width: 400px; }
.door-cta {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 30px;
  font-size: 12.5px; letter-spacing: 0.08em;
  color: var(--text);
}
.door-biz .door-cta { color: var(--purple-soft); }
.door-cpa .door-cta { color: var(--pink-soft); }
.door .btn-arrow { transition: transform 0.3s cubic-bezier(0.3, 0.7, 0.3, 1); }
.door:hover .btn-arrow { transform: translateX(5px); }

/* ---------- contact ---------- */
.contact { text-align: center; }
.contact-h2 { margin-left: auto; margin-right: auto; }
.contact .body-lg { margin: 22px auto 0; }
.contact-chips {
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2);
  margin-top: var(--s5);
}
.chip-link {
  display: inline-flex; align-items: center;
  font-size: 13.5px;
  padding: 14px 24px;
  border-radius: 100px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--mist);
  transform: translate(var(--mtx, 0px), var(--mty, 0px));
  transition: transform 0.22s cubic-bezier(0.3, 0.7, 0.3, 1), border-color 0.35s ease, color 0.35s ease, box-shadow 0.35s ease;
}
.chip-link:hover {
  border-color: var(--purple-soft);
  color: var(--text);
  box-shadow: 0 8px 30px rgba(91, 76, 255, 0.2);
}
.chip-link-accent {
  border-color: rgba(255, 77, 128, 0.45);
  color: var(--pink-soft);
}
.chip-link-accent:hover {
  border-color: var(--pink);
  color: var(--pink-soft);
  box-shadow: 0 8px 30px rgba(255, 77, 128, 0.22);
}

/* ---------- footer ---------- */
.footer {
  margin-top: var(--section-gap);
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, transparent, rgba(91, 76, 255, 0.045));
  padding: var(--s7) 0 var(--s5);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1.3fr;
  gap: clamp(28px, 4vw, 60px);
}
.footer-brand img { width: 116px; height: auto; opacity: 0.95; }
.footer-col { display: flex; flex-direction: column; gap: 9px; }
.footer-head {
  font-size: 10.5px; letter-spacing: 0.22em; color: var(--faint);
  margin-bottom: 8px;
}
.footer-head-gap { margin-top: 22px; }
.footer-col a {
  font-size: 14px; color: var(--mist);
  width: fit-content;
  transition: color 0.25s ease;
}
.footer-col a:hover { color: var(--text); }
.footer-text { font-size: 13.5px; line-height: 1.7; color: var(--mist); }
.footer-text a { color: var(--mist); }
.footer-text a:hover { color: var(--text); }
.footer-disclaimer {
  margin-top: var(--s7);
  font-size: 12px; line-height: 1.7; color: var(--faint);
  max-width: 760px;
}
.footer-bar {
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  border-top: 1px solid var(--line);
  margin-top: 28px; padding-top: 24px;
  font-size: 10.5px; letter-spacing: 0.14em; color: var(--faint);
}

/* ============================================================
   responsive
   ============================================================ */
@media (max-width: 1150px) {
  .rail { display: none; }
  .chapter-hud { display: none; }
}

@media (max-width: 980px) {
  .nav-links { display: none; }
  .nav-burger { display: flex; }
  .nav-cta-wrap .btn { display: none; }

  /* SAFETY: below 980px the primary links are hidden because the burger owns
     navigation. But the burger is display:none without JS (it can open nothing)
     and .mobile-menu is only ever revealed by a JS-applied .open — so with no JS
     this header would offer no site navigation at all. Fall back to the inline
     link row, wrapped onto its own line, and let the header grow to fit it. */
  .no-js .nav-inner { height: auto; flex-wrap: wrap; row-gap: 10px; padding-top: 12px; padding-bottom: 12px; }
  .no-js .nav-links { display: flex; flex-wrap: wrap; gap: 12px 20px; width: 100%; order: 3; }
  .no-js .nav-links a { font-size: 14px; padding: 4px 0; }

  .hero-mark-fallback { opacity: 0.35; }
  .ghost-num { font-size: clamp(140px, 40vw, 260px); top: 2%; }
  .proof-row { grid-template-columns: 1fr 1fr; }

  /* fracture: static, resolved, stage above steps */
  .js .fracture-scene { height: auto; }
  .js .fracture-sticky { position: static; height: auto; overflow: visible; }
  .fracture-scene { margin-top: 26px; }
  .fracture-grid { grid-template-columns: 1fr; gap: 10px; }
  .fracture-stage { order: -1; margin: 0 auto; height: 380px; width: 100%; max-width: 300px; }
  /* mobile has no scroll scrub — show the resolved state: one stacked line */
  .fcard { width: 100%; opacity: 1; }
  .fcard-a, .fcard-b, .fcard-c { left: 0; right: auto; transform: none; }
  .fcard-a { top: 12px; }
  .fcard-b { top: 138px; }
  .fcard-c { top: 264px; }
  .fracture-stage::after { display: none; }
  .js .fstep { opacity: 1; }

  .editorial-cols { grid-template-columns: 1fr; }
  .svc-groups { grid-template-columns: 1fr; }
  .svc-group-head { min-height: 0; }
  .svc-group:first-child .svc-cards { grid-template-columns: 1fr 1fr; }
  .case-grid { grid-template-columns: 1fr; max-width: 560px; }
  .people-grid { grid-template-columns: 1fr; }
  .doors-grid { grid-template-columns: 1fr; }
  .door { min-height: 320px; }
  .door-title { margin-top: 48px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  .proof-row { grid-template-columns: 1fr 1fr; gap: 10px; }
  .proof-tile { padding: 18px 16px 16px; }
  .svc-group:first-child .svc-cards { grid-template-columns: 1fr; }
  .fracture-stage { height: 390px; }
  .cta-row .btn { width: 100%; justify-content: center; }
  .footer-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   reduced motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .js .reveal:not(.in) { opacity: 1; transform: none; }
  .js .rise:not(.in) { opacity: 1; transform: none; clip-path: none; }
  .js [data-words] .w { opacity: 1; }
  .js .fstep { opacity: 1; }
  .js .fracture-scene { height: auto; }
  .js .fracture-sticky { position: static; height: auto; }
  .cursor-glow { display: none; }
  .blade { animation: none; }
  .scroll-cue { display: none; }
}

/* ============================================================
   THE FILM — scene system
   The viewport is a stage; scroll is the timeline. Pinned scenes
   alternate with reading rests. All vars are driven per-frame by
   the engine; no-JS and reduced-motion get the static play.
   ============================================================ */
.scene { position: relative; }
.scene-stage {
  position: sticky; top: 0;
  height: 100vh; height: 100svh;
  overflow: hidden;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: calc(var(--nav-h) + var(--s5)) var(--pad) var(--s6);
}

/* A scene's height is the distance you scroll to leave it, NOT the room its
   animation needs — the homepage hero assembles on a ~2.7s timer (see js/main.js
   "THE TITLE SEQUENCE") and scroll only disperses the finished mark, so the
   height is pure dwell. At 270vh that dispersal didn't begin until ~112vh in, so
   leaving took three to five wheel gestures with the mark just sitting there.
   150vh lets one scroll clear it while still giving the scatter room to read.

   SCOPED to the homepage via [data-chapter="hero"] (only index.html's prologue
   carries it). Every page reuses the "prologue" scene name — it's what tells the
   engine to build the number-field — so an un-scoped change would silently
   reshape all 13 heroes. The generic 270vh below stays the default for the
   inner-page title scenes, which were not part of this request. */
section[data-scene="prologue"] { height: 270vh; }
section[data-scene="prologue"][data-chapter="hero"] { height: 150vh; }
.scene-title { height: 190vh; }
section[data-scene="ch06"] { height: 440vh; }
section[data-scene="cases"] { height: 520vh; }
section[data-scene="doors"] { height: 280vh; }

/* ---------- stage typography ---------- */
.title-block {
  position: relative; z-index: 2;
  text-align: center;
  max-width: 1140px;
}
.chapter-line {
  font-size: 11px; letter-spacing: 0.18em;
  color: var(--faint);
  margin-bottom: clamp(40px, 7vh, 88px);
}
.stage-h2 {
  font-size: clamp(34px, 5.6vw, 78px);
  line-height: 1.06;
  letter-spacing: -0.028em;
  font-weight: 600;
  text-wrap: balance;
}
.stage-h2-editorial { font-size: clamp(36px, 6vw, 86px); }
.stage-body {
  margin: clamp(24px, 4vh, 40px) auto 0;
  max-width: 640px;
}
@media (prefers-reduced-motion: no-preference) {
  .js .stage-body { opacity: 0; transform: translateY(26px); transition: opacity 0.7s ease, transform 0.7s ease; }
  .js .b2 .stage-body { opacity: 1; transform: none; }
}

/* centered ghost numerals on stages */
.ghost-center {
  position: absolute; left: 50%; top: 50%;
  right: auto;
  transform: translate(-50%, -50%) translateY(var(--gy, 0px));
  font-size: clamp(300px, 52vw, 860px);
  -webkit-text-stroke: 1.5px rgba(148, 138, 255, 0.075);
  z-index: 0;
}
section[data-scene="ch06"] .ghost-center,
section[data-scene="doors"] .ghost-center { -webkit-text-stroke-color: rgba(255, 77, 128, 0.06); }

/* ---------- prologue ---------- */
.prologue-stage::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(52% 42% at 50% 26%, rgba(91, 76, 255, 0.13), transparent 68%),
    radial-gradient(44% 38% at 66% 72%, rgba(255, 77, 128, 0.07), transparent 62%);
  pointer-events: none;
}
.prologue-content {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  width: 100%;
  max-width: 1180px;
}
.kicker-center {
  position: absolute;
  top: calc(var(--nav-h) + clamp(24px, 5vh, 56px));
  left: 50%; transform: translateX(-50%);
  justify-content: center;
  margin-bottom: 0;
  white-space: nowrap;
  z-index: 3;
}
@media (max-width: 640px) {
  .kicker-center { font-size: 10px; letter-spacing: 0.16em; white-space: normal; text-align: center; width: 86%; }
  .kicker-center .kicker-dot { display: none; }
}
/* the registered company name — a quiet identity line above the headline.
   Rides the same BEAT-2 reveal as the H1 (--h1op) so it arrives with the line
   rather than hanging over the mark while it is still assembling; falls back to
   fully visible for no-JS and reduced motion. */
.hero-legal {
  font-size: clamp(10px, 0.92vw, 12px);
  letter-spacing: 0.16em;
  color: var(--faint);
  text-align: center;
  margin: 0 0 clamp(16px, 2.4vh, 26px);
}
@media (prefers-reduced-motion: no-preference) {
  .js .prologue-content .hero-legal {
    opacity: var(--h1op, 0);
    transition: opacity 0.1s linear;
  }
}
@media (max-width: 640px) {
  .hero-legal { font-size: 10px; letter-spacing: 0.1em; max-width: 92%; margin-left: auto; margin-right: auto; }
}
.prologue-content .hero-h1 {
  font-size: clamp(40px, 6.2vw, 96px);
  margin: 0;
  max-width: 1080px;
  transform: translateY(var(--h1y, 0px)) scale(var(--h1s, 1));
}
/* BEAT 1 is the mark alone. The line arrives on BEAT 2. */
@media (prefers-reduced-motion: no-preference) {
  .js .prologue-content .hero-h1 {
    opacity: var(--h1op, 0);
    transform: translateY(calc(var(--h1y, 0px) + (1 - var(--h1op, 0)) * 34px)) scale(var(--h1s, 1));
    transition: opacity 0.1s linear;
  }
}
.prologue-rest {
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(32px, 5vh, 56px);
  margin-top: clamp(40px, 6vh, 72px);
  width: 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .js .prologue-rest { opacity: var(--restop, 0); transform: translateY(var(--resty, 36px)); }
}
.lede-center { max-width: 700px; margin: 0 auto; }
.cta-row-center { justify-content: center; margin-top: 0; }
.prologue-rest .proof-row { margin-top: 4px; width: 100%; max-width: 1100px; }
.prologue-rest .proof-tile { text-align: left; }

/* ---------- case theater ---------- */
.case-stage { justify-content: flex-start; }
.case-stage-head {
  position: relative; z-index: 2;
  text-align: center;
  margin-top: clamp(6px, 3vh, 30px);
  opacity: var(--headop, 1);
  transform: translateY(calc((1 - var(--headop, 1)) * -14px));
  max-width: 1000px;
}
.case-h2 { font-size: clamp(28px, 4vw, 56px); }
.case-slide {
  /* centred in the USABLE area, not the raw stage: the nav padding at the top
     is heavier than the bottom, so a true 50% would ride up under the nav and
     clip the tallest card. The +30px lands the card's middle in the visible
     middle on every viewport height. */
  position: absolute; left: 50%; top: calc(50% + 30px);
  width: min(720px, 92vw);
  padding: clamp(24px, 3vw, 38px);
  transform: translate(-50%, -50%) perspective(1000px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) rotate(var(--srot, 0deg)) translateY(var(--sty, 0px));
  z-index: 3;
}
@media (prefers-reduced-motion: no-preference) {
  .js section[data-scene="cases"] .case-slide { --sop: 0; --sty: 90px; }
}
.case-slide .case-title { font-size: clamp(21px, 2.5vw, 31px); margin-bottom: 28px; }
.case-slide .case-kicker { font-size: 11px; }
.case-slide .case-stat dt { font-size: clamp(24px, 2.4vw, 32px); min-width: 128px; }
.case-slide .case-stat dd { font-size: 14px; }
.case-progress {
  position: absolute; bottom: 26px; left: 50%; z-index: 2;
  transform: translateX(-50%);
  font-size: 12px; letter-spacing: 0.2em;
  color: var(--faint);
}
.case-progress em { font-style: normal; color: var(--purple-soft); }

/* ---------- doors scene ---------- */
.doors-stage { gap: clamp(24px, 4vh, 44px); }
.doors-head { position: relative; z-index: 2; text-align: center; }
.doors-head .chapter-line { margin-bottom: 0; }
.doors-stage .doors-grid { width: min(1160px, 100%); margin-top: 0; position: relative; z-index: 2; }
.door-biz { transform-origin: 100% 50%; }
.door-cpa { transform-origin: 0% 50%; }
.door .door-label, .door .door-title, .door .door-desc, .door .door-cta { opacity: var(--dop, 1); }
@media (prefers-reduced-motion: no-preference) and (min-width: 981px) {
  .js section[data-scene="doors"] .door { --dsx: 0.04; --dop: 0; --sop: 0.9; }
}

/* ---------- fracture section (own sticky theater) ---------- */
.fracture-section { position: relative; }

/* ---------- statics: no-JS and reduced motion get the whole play ---------- */
/* SAFETY — THE FIT GUARD.
   .scene-stage is `position:sticky; height:100svh; overflow:hidden` with no inner
   scroll, so a scene whose content is taller than the viewport silently clips it
   at EVERY scroll position — the stage never travels far enough to reveal the
   rest. Measured on a 390x844 phone this hid two of the seven approved diagnostic
   questions on the homepage, and the closing 18,004.25 tie-out row that the whole
   reconciliation exists to land. measure() adds .unfit to any scene that cannot
   fit its own stage, and the scene then falls back to the flat layout the no-JS
   path below already ships and has been verified readable.
   A lost animation is always better than unreadable client copy.
   The overrides are !important because the scene choreo writes inline transforms
   on these same elements every frame and would otherwise win. */
.js .scene.unfit { height: auto !important; }
.js .scene.unfit .scene-stage {
  position: static !important; height: auto !important;
  overflow: visible !important; padding-top: var(--section-gap);
}
.js .scene.unfit .case-slide {
  position: static !important; transform: none !important; opacity: 1 !important;
  width: 100%; max-width: 720px; margin: 22px auto 0;
}
.js .scene.unfit .case-stage-head { opacity: 1 !important; }
.js .scene.unfit .ghost-center { display: none; }

.no-js .scene { height: auto !important; }
.no-js .scene-stage { position: static; height: auto; overflow: visible; padding-top: var(--section-gap); }
.no-js .case-slide { position: static; transform: none; width: 100%; max-width: 720px; margin: 22px auto 0; }
.no-js .case-stage-head { opacity: 1; }
.no-js .ghost-center { display: none; }
.no-js .prologue-rest { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .scene { height: auto !important; }
  .scene-stage { position: static; height: auto; overflow: visible; padding-top: var(--section-gap); }
  .case-slide { position: static; transform: none; width: 100%; max-width: 720px; margin: 22px auto 0; opacity: 1; }
  .case-stage-head { opacity: 1; }
  .ghost-center { display: none; }
  .prologue-rest { opacity: 1; transform: none; }
  .door { --dsx: 1; --dop: 1; --sop: 1; --swing: 0deg; }
}

/* ---------- responsive scene tuning ---------- */
@media (max-width: 980px) {
  section[data-scene="prologue"] { height: 170vh; }
  .scene-title { height: 150vh; }
  section[data-scene="ch06"] { height: 240vh; }
  section[data-scene="cases"] { height: 400vh; }
  /* doors: static flow on mobile (two tall panels don't fit one viewport) */
  section[data-scene="doors"] { height: auto; }
  section[data-scene="doors"] .scene-stage { position: static; height: auto; overflow: visible; padding-top: var(--section-gap); }
  section[data-scene="doors"] .door { --dsx: 1; --dop: 1; --sop: 1; --swing: 0deg; }
  section[data-scene="doors"] .ghost-center { display: none; }
  .case-slide { top: 58%; }
  .stage-h2 { font-size: clamp(30px, 8vw, 44px); }
  .stage-h2-editorial { font-size: clamp(32px, 8.6vw, 46px); }
  .prologue-content .hero-h1 { font-size: clamp(36px, 9.4vw, 52px); }
  .prologue-rest .proof-row { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   COLD OPEN — the film starts before the page does.
   Chrome holds back while the number-field finds the mark.
   Any scroll input cancels it instantly.
   ============================================================ */
.js.cold .nav-inner,
.js.cold .rail,
.js.cold .chapter-hud,
.js.cold .scroll-progress,
.js.cold .prologue-content .kicker,
.js.cold .scroll-cue {
  opacity: 0;
}
.js .nav-inner,
.js .rail,
.js .prologue-content .kicker,
.js .scroll-cue {
  transition: opacity 0.9s ease 0.15s;
}
.js.cold .prologue-rest { opacity: 0 !important; }

/* ============================================================
   ACT TEMPERATURE — the chrome warms from purple to pink as the
   film moves from problem (Act I) to threshold (Act IV).
   ============================================================ */
:root { --act: 0; }
.scroll-progress {
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--purple), var(--pink) calc(var(--act) * 100%)),
    var(--pink));
}
.hud-index em {
  color: color-mix(in srgb, var(--purple-soft), var(--pink-soft) calc(var(--act) * 100%));
}
.hud-sep {
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--purple), var(--pink) calc(var(--act) * 100%)),
    transparent);
}
.rail-tick.active .rail-num {
  color: color-mix(in srgb, var(--purple-soft), var(--pink-soft) calc(var(--act) * 100%));
}

/* ============================================================
   THE SWEEP — chapter 06's radar is an instrument the scroll turns.
   As the beam passes each bearing it finds one of the firm's real
   diagnostic questions. Static fallback: all seven, plainly listed.
   ============================================================ */
.diag {
  margin: clamp(40px, 6vh, 72px) auto 0;
  max-width: 760px;
  text-align: left;
}
.diag-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px;
  font-size: 10.5px; letter-spacing: 0.22em;
  color: var(--faint);
  border-bottom: 1px solid var(--line);
  padding-bottom: 10px; margin-bottom: 6px;
}
.diag-count em { font-style: normal; color: var(--purple-soft); }
.findings { list-style: none; margin: 0; padding: 0; }
/* base = a readable row (the no-JS / reduced-motion / mobile fallback) */
.finding {
  display: grid;
  grid-template-columns: 54px 1fr;
  gap: var(--s2);
  align-items: baseline;
  padding: 13px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.f-tag { font-size: 11px; letter-spacing: 0.14em; color: var(--pink-soft); transition: color 0.4s ease; }
.f-q {
  font-size: 15px; line-height: 1.55;
  color: var(--mist);
  transition: color 0.5s ease, opacity 0.5s ease;
}

/* desktop + motion: the seven questions become a DECK shown TWO at a time. Each
   scroll beat brings the next PAIR of glass cards forward; the previous pairs
   recede into a soft stack behind — so the current two questions are big and
   readable while the sweep stays visible, and the whole thing paces at four
   beats instead of seven. .hit/.settled and --depth are set per pair by the
   radar scene (js/main.js ch06). */
@media (prefers-reduced-motion: no-preference) and (min-width: 981px) {
  .js .diag { max-width: 720px; }
  .js .findings { position: relative; min-height: clamp(200px, 30vh, 268px); margin-top: 12px; }
  .js .fpair {
    position: absolute; left: 0; right: 0; bottom: 0;
    display: grid; grid-template-columns: 1fr 1fr;
    gap: clamp(14px, 1.6vw, 22px);
    opacity: 0;
    transform: translateY(28px) scale(0.96);
    transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.3, 0.7, 0.3, 1);
    z-index: 1;
  }
  .js .fpair-solo { grid-template-columns: minmax(0, 62%); justify-content: center; }
  .js .fpair .finding {
    display: flex; flex-direction: column; gap: 12px;
    padding: clamp(18px, 2vw, 26px) clamp(20px, 2.2vw, 28px);
    border: 1px solid var(--line-strong); border-radius: 18px;
    background: rgba(15, 15, 22, 0.74);
    backdrop-filter: blur(17px) saturate(160%);
    -webkit-backdrop-filter: blur(17px) saturate(160%);
    box-shadow: 0 24px 56px rgba(0, 0, 0, 0.52), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  }
  .js .fpair .f-tag { color: var(--faint); font-size: 11px; }
  .js .fpair .f-q { font-size: clamp(15px, 1.45vw, 18px); line-height: 1.5; color: var(--text); }
  /* the pair at the front of the deck */
  .js .fpair.hit {
    opacity: 1;
    transform: translateY(calc(var(--depth, 0) * -16px)) scale(calc(1 - var(--depth, 0) * 0.05));
    z-index: calc(10 - var(--depth, 0));
  }
  .js .fpair.hit .f-tag { color: var(--pink-soft); }
  /* pairs that have settled behind it, dimming with depth (>=4 -> hidden) */
  .js .fpair.hit.settled { opacity: calc(1 - var(--depth, 0) * 0.3); }
  .js .fpair.hit.settled .f-tag { color: var(--purple-soft); }
  .js .fpair.hit.settled .f-q { color: var(--mist); }
}
@media (max-width: 980px) {
  .finding { grid-template-columns: 40px 1fr; gap: 10px; }
  .f-q { font-size: 13.5px; }
}

/* ============================================================
   THE RECONCILIATION — case 01. Book and bank arrive apart and
   tie out row by row as the beat plays. The card's own "100%"
   is the number the instrument lands on.
   ============================================================ */
.recon {
  margin-top: 20px;
  border-top: 1px solid var(--line);
  padding-top: 14px;
  display: flex; flex-direction: column; gap: 6px;
}
.recon-head {
  display: flex; justify-content: space-between;
  font-size: 9.5px; letter-spacing: 0.24em; color: var(--faint);
  margin-bottom: 4px;
}
.recon-row {
  display: grid; grid-template-columns: 1fr 26px 1fr;
  align-items: center;
  font-size: 12px; color: var(--mist);
}
.recon-row b { font-weight: 400; }
.recon-row b:last-child { text-align: right; }
.recon-row i {
  justify-self: center;
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  transition: background 0.4s ease, box-shadow 0.4s ease;
}
@media (prefers-reduced-motion: no-preference) {
  .js .recon-row { transform: translateX(var(--rx0, 0px)); opacity: var(--rop, 1); transition: transform 0.5s cubic-bezier(0.22,0.6,0.2,1), opacity 0.4s ease; }
  .js .recon-row b:last-child { transform: translateX(var(--rx1, 0px)); transition: transform 0.5s cubic-bezier(0.22,0.6,0.2,1); display: block; }
}
.recon-row.tied b { color: var(--text); }
.recon-row.tied i { background: var(--purple); box-shadow: 0 0 10px rgba(91, 76, 255, 0.85); }

/* ============================================================
   NEXUS 50 — case 03. Fifty states; the eight the deck names
   illuminate as the firm's footprint is mapped.
   ============================================================ */
/* stats beside the map, so case 3 is no taller than its siblings */
.case-split {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(24px, 3vw, 44px);
  align-items: center;
  margin-top: 8px;
}
.case-split .case-stats { align-self: center; }

/* THE NEXUS MAP — eight named states pinned on the US, dropping in and lighting
   as the case is read; a thread traces the spreading nexus. */
.usmap { padding-left: clamp(0px, 1vw, 12px); }
.usmap-cap {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 9.5px; letter-spacing: 0.16em; color: var(--faint);
  margin-bottom: 14px;
}
.usmap-cap-b em { color: var(--pink-soft); font-style: normal; }
.usmap-plot { position: relative; width: 100%; aspect-ratio: 100 / 62; }
.usmap-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.usmap-outline {
  fill: rgba(148, 138, 255, 0.03);
  stroke: rgba(148, 138, 255, 0.22);
  stroke-width: 1; vector-effect: non-scaling-stroke; stroke-linejoin: round;
}
.usmap-thread {
  fill: none; stroke: var(--pink); stroke-width: 1.4;
  vector-effect: non-scaling-stroke; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--drawn, 1));
  opacity: 0.6; filter: drop-shadow(0 0 4px rgba(255, 77, 128, 0.4));
}
.map-pin { position: absolute; transform: translate(-50%, -50%); z-index: 2; }
.pin-dot {
  display: block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--pink); opacity: 0;
  transform: translateY(-10px) scale(0.5);
  transition: opacity 0.4s ease, transform 0.45s cubic-bezier(0.34, 1.5, 0.5, 1), box-shadow 0.4s ease;
}
.pin-lbl {
  position: absolute; font-size: 9px; letter-spacing: 0.08em;
  color: var(--faint); opacity: 0; white-space: nowrap;
  transition: opacity 0.4s ease 0.1s, color 0.4s ease;
}
.lbl-t .pin-lbl { left: 50%; transform: translateX(-50%); bottom: 13px; }
.lbl-b .pin-lbl { left: 50%; transform: translateX(-50%); top: 13px; }
.lbl-l .pin-lbl { right: 13px; top: -6px; }
.lbl-r .pin-lbl { left: 13px; top: -6px; }
.map-pin.lit .pin-dot {
  opacity: 1; transform: translateY(0) scale(1);
  box-shadow: 0 0 15px rgba(255, 77, 128, 0.85), 0 0 4px rgba(255, 77, 128, 0.9);
}
.map-pin.lit .pin-lbl { opacity: 1; color: var(--text); }
@media (max-width: 640px) {
  .recon-row { font-size: 11px; }
  .case-split { grid-template-columns: 1fr; gap: 20px; }
  .usmap { padding-left: 0; }
  .usmap-plot { width: min(100%, 420px); margin: 0 auto; }
  .usmap-cap { font-size: 8.5px; }
  .pin-lbl { font-size: 8px; }
}

/* ---------- new devices: reduced motion + no-JS static states ---------- */
@media (prefers-reduced-motion: reduce) {
  .finding .f-q { opacity: 1; color: var(--mist); }
  .recon-row { transform: none; opacity: 1; }
  /* the dot said tied and the figures did not: .recon-row.tied b is the
     only rule that brightens them and .tied is added by JS, so a static
     reader saw a lit tie-out dot beside a still-dim number. Both static
     states now resolve the whole row, not half of it. */
  .recon-row i { background: var(--purple); }
  .recon-row b { color: var(--text); }
  .map-pin .pin-dot { opacity: 1; transform: none; box-shadow: 0 0 12px rgba(255,77,128,0.7); }
  .map-pin .pin-lbl { opacity: 1; color: var(--text); }
  .usmap-thread { stroke-dashoffset: 0; }
  .clock-dot { animation: none; }
  .js .fcard { cursor: default; }
  .fcard-hint { display: none; }
}
.no-js .finding .f-q { opacity: 1; }

/* The sweep is a desktop reading device. The beam recedes a finding to 0.26 before
   it is found and 0.5 once it has settled, which reads correctly while the radar is
   visibly turning beside it. On a phone that pairing is gone — the scene unpins when
   its content will not fit — and a "settled" finding is then just approved copy at
   half weight with nothing on screen to explain why. All seven stay legible instead.
   Written at .js specificity because the rule it has to beat is .js-scoped; a bare
   .finding selector would silently lose the cascade. */
@media (max-width: 980px) {
  .js .finding .f-q,
  .js .finding.settled .f-q { opacity: 1; color: var(--mist); }
  .js .finding.hit .f-q { opacity: 1; color: var(--text); }
}
.no-js .recon-row { transform: none; opacity: 1; }
.no-js .recon-row b { color: var(--text); }
.no-js .recon-row i { background: var(--purple); }
.no-js .map-pin .pin-dot { opacity: 1; transform: none; box-shadow: 0 0 12px rgba(255,77,128,0.7); }
.no-js .map-pin .pin-lbl { opacity: 1; color: var(--text); }
.no-js .usmap-thread { stroke-dashoffset: 0; }
.no-js .fcard-hint { display: none; }

/* ============================================================
   THE SEAM — two shores, offset, that the scroll shears into
   alignment. Until they meet, you are the thing holding them
   together. Uses the same live clocks as the contact scene.
   ============================================================ */
section[data-scene="seam"] { height: 260vh; }
@media (max-width: 980px) { section[data-scene="seam"] { height: 210vh; } }

.seam-h2 { max-width: 20ch; }
/* THE BRIDGE — every US timezone answering to one Indian clock. Wires connect
   as the scroll joins the two sides. */
.seam-bridge {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: auto minmax(64px, 180px) auto;
  align-items: center;
  margin: clamp(38px, 5.5vh, 72px) auto 0;
  width: fit-content; max-width: 100%;
}
.seam-col { display: flex; flex-direction: column; }
.seam-col-label {
  font-size: 9px; letter-spacing: 0.24em; color: var(--faint);
  margin-bottom: 12px;
}
.seam-col-ist .seam-col-label { text-align: right; }
.seam-zones { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: clamp(6px, 1.1vh, 11px); }
.seam-zone { display: grid; grid-template-columns: 30px auto; align-items: baseline; gap: 12px; }
.tz-abbr { font-size: 10px; letter-spacing: 0.14em; color: var(--purple-soft); font-weight: 500; }
.seam-tz { font-style: normal; font-size: 14px; letter-spacing: 0.03em; color: var(--mist); }
.seam-col-ist { align-items: flex-end; }
.seam-zone-lead { grid-template-columns: auto auto; gap: 14px; }
.seam-zone-lead .tz-abbr { color: var(--pink-soft); font-size: 11px; }
.seam-zone-lead .seam-tz { color: var(--text); font-size: 20px; letter-spacing: 0.02em; }
.seam-wires { width: 100%; height: 100%; min-height: 150px; align-self: stretch; overflow: visible; }
.seam-wire {
  fill: none;
  stroke: var(--purple-soft);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  /* faint when the shores are apart, lit and full as they join */
  opacity: calc(0.16 + 0.7 * var(--join, 1));
}
/* the wire that lands on IST carries the pink, so the convergence reads */
.seam-wire:nth-child(3), .seam-wire:nth-child(4) { stroke: var(--pink); }
.seam-stage.joined .seam-zone-lead .seam-tz { text-shadow: 0 0 20px rgba(255, 77, 128, 0.4); }

@media (prefers-reduced-motion: reduce) { .seam-bridge { --join: 1; } }
.no-js .seam-bridge { --join: 1; }

@media (max-width: 560px) {
  .seam-bridge { grid-template-columns: auto minmax(40px, 1fr) auto; width: 100%; }
  .seam-wires { min-height: 130px; }
  .seam-tz { font-size: 13px; }
  .seam-zone-lead .seam-tz { font-size: 17px; }
}

/* ============================================================
   AUDIT MODE — type XQUBE. The site shows its workpapers:
   every surface becomes a 1px wireframe, every figure gets a
   tie-out tick, and the number-field becomes a ledger.
   ============================================================ */
body.audit .proof-tile,
body.audit .svc-card,
body.audit .case-card,
body.audit .founders-panel,
body.audit .door,
body.audit .fcard,
body.audit .chip-link,
body.audit .shore,

body.audit .nav-inner {
  background: transparent !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border-color: rgba(148, 138, 255, 0.55) !important;
  box-shadow: none !important;
}
body.audit .proof-tile::after,
body.audit .svc-card::after,
body.audit .case-card::after,
body.audit .door::after {
  content: "";
  position: absolute; inset: 6px;
  border: 1px dashed rgba(148, 138, 255, 0.28);
  border-radius: 4px;
  opacity: 1 !important;
  background: none !important;
  pointer-events: none;
}
body.audit .grain,
body.audit .cursor-glow { opacity: 0 !important; }
body.audit [data-count],
body.audit .case-stat dt,
body.audit .proof-value {
  position: relative;
}
body.audit [data-count]::after,
body.audit .case-stat dt::after {
  content: "✓";
  position: absolute; top: -0.4em; right: -0.9em;
  font-size: 0.42em;
  color: var(--pink);
}
body.audit .audit-badge { opacity: 1; transform: none; }
.audit-badge {
  position: fixed; left: 26px; top: calc(var(--nav-h) + 16px); z-index: 126;
  font-family: var(--mono-f);
  font-size: 10px; letter-spacing: 0.24em;
  color: var(--purple-soft);
  border: 1px solid rgba(148, 138, 255, 0.5);
  border-radius: 3px;
  padding: 6px 12px;
  background: rgba(10, 10, 14, 0.9);
  opacity: 0; transform: translateY(-6px);
  transition: opacity 0.4s ease, transform 0.4s ease;
  pointer-events: none;
}
/* the one hint that the mode exists: a tick under the mark, once */
.brand.hinted .brand-mark { position: relative; }
.brand.hinted::after {
  content: "";
  position: absolute; left: 0; bottom: -4px;
  width: 44px; height: 1px;
  background: var(--purple);
  animation: hint-tick 3s ease-in-out 1 forwards;
}
@keyframes hint-tick {
  0%, 100% { opacity: 0; }
  20%, 70% { opacity: 0.9; }
}

/* ============================================================
   MOBILE PROLOGUE — a full hero cannot fit inside one pinned
   phone viewport, and clipping it is worse than scrolling it.
   On small screens the titles still play, but the hero flows.
   ============================================================ */
@media (max-width: 980px) {
  section[data-scene="prologue"] { height: auto; }
  section[data-scene="prologue"] .scene-stage {
    position: static;
    height: auto;
    min-height: 100svh;
    overflow: visible;
    padding: calc(var(--nav-h) + var(--s6)) var(--pad) var(--s7);
    justify-content: flex-start;
  }
  /* the kicker rejoins the flow so it can never sit on the headline */
  .kicker-center {
    position: static;
    transform: none;
    width: auto;
    margin: 0 auto var(--s4);
  }
  /* the mark keeps clear of the copy instead of sitting under it */
  section[data-scene="prologue"] .scene-stage .prologue-content { padding-top: 34vh; }
  .prologue-rest { gap: var(--s5); margin-top: var(--s5); }
  section[data-scene="prologue"] .scroll-cue { display: none; }
}
@media (max-width: 640px) {
  .prologue-rest .proof-row { grid-template-columns: 1fr; }
}

/* ============================================================
   THE HERO, UNCRAMPED
   The opening screen carries four things only: label, line,
   intro, action. Everything else got its own room. Type is
   loosened — a 96px headline needs more leading than a caption,
   not less — and the rhythm between the four is generous.
   ============================================================ */
section[data-scene="prologue"] .scene-stage {
  padding-top: calc(var(--nav-h) + var(--s7));
  padding-bottom: var(--s7);
}
.prologue-content .hero-h1 {
  line-height: 1.075;
  letter-spacing: -0.024em;
  max-width: 15ch;                 /* three deliberate lines, not a wall */
  margin: 0 auto;
}
.prologue-rest {
  gap: var(--s6);                  /* intro and action never touch */
  margin-top: clamp(40px, 7vh, 88px);
}
.lede-center {
  max-width: 54ch;
  line-height: 1.8;
}
.cta-row-center { gap: var(--s3); }
.kicker-center { top: calc(var(--nav-h) + clamp(32px, 6vh, 72px)); }

/* the scroll cue needs air under the buttons, not a collision */
section[data-scene="prologue"] .scroll-cue { bottom: var(--s4); }

/* ============================================================
   PROOF BAND — the evidence, given its own room one scroll down.
   ============================================================ */
.proof-band { padding-top: clamp(96px, 16vh, 190px); }
.proof-eyebrow {
  font-size: 11px; letter-spacing: 0.26em;
  color: var(--faint);
  padding-bottom: var(--s3);
  margin-bottom: var(--s5);
  border-bottom: 1px solid var(--line);
}
.proof-band .proof-row { gap: var(--s3); }
.proof-band .proof-tile { padding: var(--s5) var(--s4) var(--s4); }
.proof-band .proof-value {
  font-size: clamp(34px, 3.8vw, 52px);
  margin-bottom: var(--s2);
}
.proof-band .proof-label { font-size: 14px; line-height: 1.6; max-width: 26ch; }

@media (max-width: 980px) {
  .proof-band .proof-row { grid-template-columns: 1fr 1fr; }
  section[data-scene="prologue"] .scene-stage {
    padding-top: calc(var(--nav-h) + var(--s6));
    padding-bottom: var(--s7);
  }
  .prologue-content .hero-h1 { max-width: 100%; }
}
@media (max-width: 640px) {
  .proof-band .proof-row { grid-template-columns: 1fr; }
}

/* ============================================================
   HERO RHYTHM, FINAL — the kicker rejoins the flow at every
   width. Absolute positioning was letting it land on the
   headline; in-flow it can never collide, at any type size.
   ============================================================ */
.kicker-center {
  position: static !important;
  transform: none !important;
  width: auto;
  white-space: normal;
  margin: 0 auto var(--s4);
}
section[data-scene="prologue"] .scene-stage {
  padding-top: calc(var(--nav-h) + var(--s5));
  padding-bottom: var(--s7);
  justify-content: center;
}
.prologue-content .hero-h1 {
  font-size: clamp(38px, 5.4vw, 82px);
  max-width: 16ch;
}
.prologue-rest { margin-top: clamp(36px, 6vh, 72px); gap: clamp(32px, 5vh, 56px); }
section[data-scene="prologue"] .scroll-cue { bottom: var(--s3); }

/* short desktop windows: drop the cue rather than crowd the buttons */
@media (min-width: 981px) and (max-height: 820px) {
  section[data-scene="prologue"] .scroll-cue { display: none; }
  .prologue-content .hero-h1 { font-size: clamp(36px, 4.6vw, 66px); }
  .prologue-rest { margin-top: var(--s5); gap: var(--s4); }
}

/* the label must sit clear of the line, not on its shoulder */
.kicker-center { margin: 0 auto clamp(30px, 5vh, 60px) !important; }
section[data-scene="prologue"] .scene-stage { padding-top: calc(var(--nav-h) + var(--s6)); }

/* a worded proof point sets on one line, in rhythm with the numerals */
.proof-band .proof-value { white-space: nowrap; }
.proof-band .proof-value-text { font-size: clamp(26px, 2.5vw, 34px); }

/* ============================================================
   THE PROOF FIGURES — the mark was made of numbers, so the beat
   after the titles is those numbers declaring themselves. The
   world writes each figure, giant, behind the tile that claims it.
   ============================================================ */
section[data-scene="figures"] { height: 330vh; }
@media (max-width: 980px) { section[data-scene="figures"] { height: auto; } }

.figures-stage { justify-content: center; }
.figures-stage .wrap { position: relative; z-index: 2; width: 100%; }
.proof-scene .proof-eyebrow {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 11px; letter-spacing: 0.26em;
  color: var(--faint);
  padding-bottom: var(--s3);
  margin-bottom: var(--s5);
  border-bottom: 1px solid var(--line);
}
.fig-count em { font-style: normal; color: var(--purple-soft); }
.proof-scene .proof-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s3); }
.proof-scene .proof-tile {
  padding: var(--s5) var(--s4) var(--s4);
  opacity: var(--tp, 1);
  transform: translateY(var(--ty, 0px));
}
.proof-scene .proof-value { white-space: nowrap; font-size: clamp(34px, 3.8vw, 52px); margin-bottom: var(--s2); }
.proof-scene .proof-value-text { font-size: clamp(26px, 2.5vw, 34px); }
.proof-scene .proof-label { font-size: 14px; line-height: 1.6; max-width: 26ch; }

/* the tile whose figure the world is currently writing */
.proof-scene .proof-tile.claiming {
  border-color: rgba(148, 138, 255, 0.6);
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.5), 0 0 34px rgba(91, 76, 255, 0.2);
}
.proof-scene .proof-tile.claiming .proof-value {
  color: #fff;
  text-shadow: 0 0 26px rgba(148, 138, 255, 0.55);
}
.proof-scene .proof-tile.claimed { border-color: rgba(255, 255, 255, 0.14); }

@media (prefers-reduced-motion: reduce), (max-width: 980px) {
  section[data-scene="figures"] .scene-stage {
    position: static; height: auto; overflow: visible;
    padding-top: var(--section-gap); padding-bottom: 0;
  }
  .proof-scene .proof-tile { opacity: 1 !important; transform: none !important; }
}
@media (max-width: 980px) { .proof-scene .proof-row { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .proof-scene .proof-row { grid-template-columns: 1fr; } }

/* chapter title in a reading rest (no scene stage around it) */
.chapter-line-rest {
  margin-bottom: clamp(32px, 5vh, 56px);
  text-align: left;
}

/* ============================================================
   THE SERVICE BAR — on the services pages the header carries all
   seven disciplines. It stays out of the way at the top of the
   page, then slides out of the header once the reader is into
   the piece, so a sibling service is always one click away.
   ============================================================ */
.svcbar {
  position: relative;
  max-height: 0;
  overflow: hidden;
  background: rgba(10, 10, 14, 0.82);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid transparent;
  transition: max-height 0.5s cubic-bezier(0.22, 0.6, 0.2, 1),
              border-color 0.4s ease, opacity 0.35s ease;
  opacity: 0;
}
.nav.svc-open .svcbar {
  max-height: 72px;
  opacity: 1;
  border-bottom-color: var(--line);
}
.svcbar-inner {
  display: flex; align-items: center; gap: var(--s1);
  padding: 12px clamp(20px, 3vw, 36px);
  overflow-x: auto;
  scrollbar-width: none;
}
.svcbar-inner::-webkit-scrollbar { display: none; }
.svcbar-label {
  flex: 0 0 auto;
  font-size: 9.5px; letter-spacing: 0.22em;
  color: var(--faint);
  padding-right: var(--s2);
  margin-right: var(--s1);
  border-right: 1px solid var(--line);
  align-self: stretch;
  display: flex; align-items: center;
  white-space: nowrap;
}
.svcbar-link {
  flex: 0 0 auto;
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 7px 13px;
  border: 1px solid transparent;
  border-radius: 100px;
  white-space: nowrap;
  transition: background 0.28s ease, border-color 0.28s ease, color 0.28s ease;
}
.svcbar-num {
  font-size: 10px; letter-spacing: 0.08em;
  color: var(--faint);
  transition: color 0.28s ease;
}
.svcbar-name {
  font-size: 13px; font-weight: 500;
  color: var(--mist);
  transition: color 0.28s ease;
}
.svcbar-link:hover {
  background: rgba(91, 76, 255, 0.1);
  border-color: rgba(148, 138, 255, 0.42);
}
.svcbar-link:hover .svcbar-name { color: var(--text); }
.svcbar-link:hover .svcbar-num { color: var(--purple-soft); }
.svcbar-link.is-current {
  background: rgba(91, 76, 255, 0.14);
  border-color: rgba(148, 138, 255, 0.55);
}
.svcbar-link.is-current .svcbar-name { color: #fff; }
.svcbar-link.is-current .svcbar-num { color: var(--pink-soft); }

/* fade the edges so a scrolled-off service reads as "there is more" */
.svcbar::after {
  content: "";
  position: absolute; right: 0; top: 0; bottom: 0; width: 56px;
  background: linear-gradient(90deg, transparent, rgba(10, 10, 14, 0.9));
  pointer-events: none;
}

@media (max-width: 980px) {
  .nav.svc-open .svcbar { max-height: 64px; }
  .svcbar-inner { padding: 10px var(--pad); }
  .svcbar-label { display: none; }
  .svcbar-name { font-size: 12.5px; }
}

/* without JS the bar is simply always open — the links must never be lost */
.no-js .svcbar { max-height: 72px; opacity: 1; border-bottom-color: var(--line); }
@media (prefers-reduced-motion: reduce) {
  .svcbar { transition: none; }
}

/* the Services link reads as a menu trigger while its bar is open */
.nav.svc-open .nav-links a[data-svc-trigger] { color: var(--text); }
.nav.svc-open .nav-links a[data-svc-trigger]::after { transform: scaleX(1); }
/* keep a hoverable bridge between the link and the bar so the pointer
   never crosses dead space on its way down */
.nav-links a[data-svc-trigger] { position: relative; }
.nav-links a[data-svc-trigger]::before {
  content: "";
  position: absolute; left: -10px; right: -10px; top: 100%; height: 22px;
}

/* ============================================================
   MOBILE MENU — the seven services sit under Services, indented
   so the hierarchy is obvious without a tap-to-expand step.
   ============================================================ */
.mobile-svc {
  display: flex; flex-direction: column;
  margin: 2px 0 10px 0;
  padding-left: 18px;
  border-left: 1px solid var(--line);
}
.mobile-links .mobile-svc a {
  display: flex; align-items: baseline; gap: 12px;
  font-size: 15px;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: var(--mist);
  padding: 9px 0;
  border-bottom: 0;
}
.mobile-links .mobile-svc a .mono {
  font-size: 10px;
  color: var(--faint);
  min-width: 34px;
}
.mobile-links .mobile-svc a:hover,
.mobile-links .mobile-svc a:focus-visible { color: var(--text); }
.mobile-links .mobile-svc a.is-current { color: #fff; }
.mobile-links .mobile-svc a.is-current .mono { color: var(--pink-soft); }

/* the parent Services row loses its divider so the group reads as one block */
.mobile-links a[href="services.html"] { border-bottom: 0; }

/* ============================================================
   GLASS, COSTED FOR A PHONE
   backdrop-filter is the most expensive thing on this site: the compositor
   re-blurs everything behind the element on every frame it moves, and these
   cards move constantly because they live inside a scrolling film. On a
   handset that is the difference between 60fps and visible tearing.

   This block sits at the END of the file on purpose. Every one of these
   components declares its own backdrop-filter further up (.case-card at 894,
   .founders-panel at 971, .door at 1045 ...), so an override placed beside
   the glass definitions loses to them on source order — measured: only
   .proof-tile actually flattened, the rest kept their blur.

   The look survives the loss. --surface is only 3.5% white, so removing the
   blur would leave nothing visible; --glass-flat is the stand-in, sitting
   where the frosted card sat against this page's black. The 1px border and
   the specular top edge were always doing most of the work.
   ============================================================ */
@media (max-width: 980px) {
  /* the grain's blend is the expensive half: overlay forces a backdrop
     read-back across the whole viewport whenever anything under it moves.
     At 4.2% opacity on a phone screen the texture is imperceptible either
     way, so the blend goes and the noise stays as plain film. */
  .grain { mix-blend-mode: normal; opacity: 0.03; }
  .proof-tile,
  .svc-card,
  .case-card,
  .founders-panel,
  .door,
  .fcard,
  .clock,
  .chip-link {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--glass-flat);
  }
  /* already 92% opaque, so the 26px blur behind it bought almost nothing and
     cost a full-screen composite every time the menu opened */
  .mobile-menu {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(8, 8, 12, 0.975);
  }
  /* the nav and its service bar keep a frost: they are small, fixed, and sit
     over moving copy where legibility genuinely needs the separation. A
     shorter radius composites far more cheaply than the full 14-18px. */
  .nav-inner, .svcbar {
    backdrop-filter: blur(10px) saturate(140%);
    -webkit-backdrop-filter: blur(10px) saturate(140%);
  }
}

/* ============================================================
   THE SEVEN QUESTIONS, ON A PHONE
   Desktop gets a deck: pairs of glass cards that arrive two per beat and
   settle behind one another in an absolutely-stacked pile. A phone has no
   room for a pile — but it can have the same moment, because the same
   scene drives it. MEASURED on a 390px viewport: the radar scene already
   runs there and walks .hit 0 -> 1 -> 2 -> 3 -> 4 with the counter going
   00 -> 02 -> 04 -> 06 -> 07, exactly as on desktop. Only the styling was
   desktop-only, so the questions rendered as a plain list.

   So: same cards, same pairs, same pacing — stacked DOWN the page instead
   of behind each other, which also reads better on a narrow screen.

   Scoped to .js and to no-preference on purpose. If the engine never comes
   up the load handler strips .js and the base readable list survives; a
   reduced-motion reader keeps that list too. Approved copy is never left
   hidden behind a class that might not arrive.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) and (max-width: 980px) {
  .js .findings { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
  .js .fpair {
    display: grid; grid-template-columns: 1fr; gap: 12px;
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.5s ease, transform 0.55s cubic-bezier(0.3, 0.7, 0.3, 1);
  }
  .js .fpair.hit { opacity: 1; transform: none; }
  .js .fpair .finding {
    display: flex; flex-direction: column; gap: 8px;
    padding: 15px 16px;
    border: 1px solid var(--line-strong);
    border-bottom: 1px solid var(--line-strong);
    border-radius: 16px;
    background: var(--glass-flat);
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  }
  .js .fpair .f-tag { color: var(--faint); font-size: 10.5px; }
  .js .fpair.hit .f-tag { color: var(--pink-soft); }
  .js .fpair .f-q { color: var(--text); font-size: 14.5px; line-height: 1.5; }
}

/* ============================================================
   AN UNPINNED SCENE HAS NO BEAT TO WITHHOLD COPY FOR
   .stage-body is held at opacity 0 until its scene's choreography adds .b2
   at 45% progress. On a pinned stage that is a beat: the reader is held
   still and the line arrives. Once the fit guard unpins a scene on a phone
   the stage scrolls WITH the page, so the same rule means the reader walks
   past an empty gap where approved copy should be and only sees it after
   scrolling nearly half the section.

   Anything the guard has unpinned therefore shows its copy outright. This
   can only ever make approved copy MORE visible, never less.
   ============================================================ */
.js .scene.unfit .stage-body { opacity: 1 !important; transform: none !important; }
