/* ============================================================================
   Tempo VC Deck — design system + per-slide layouts
   "Quiet Authority": refined minimalism × editorial-luxury-tech.
   ============================================================================ */

/* -------- 1. Tokens ------------------------------------------------------- */
:root {
  --bg: #08090A;
  --bg-elev: #0E0F11;
  --bg-elev-2: #16181C;
  --border: #1F2024;
  --border-soft: #14161A;
  --border-strong: #2A2C32;

  --text: #F4F5F8;
  --text-soft: #C9CCD3;
  --text-muted: #8A8F98;
  --text-dim: #5C6068;
  --text-faint: #3A3D44;

  --accent: #2547EB;
  --accent-soft: #5E6AD2;
  --accent-bright: #6E7BE6;
  --accent-glow: rgba(94, 106, 210, 0.35);

  --success: #4ADE80;
  --warn: #F59E0B;
  --danger: #EF4444;

  --font-display: 'Geist', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body:    'Geist', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --font-serif:   'Instrument Serif', 'Times New Roman', serif;

  --ease:        cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in:     cubic-bezier(0.6, 0, 0.36, 1);
  --transition:  380ms var(--ease);

  /* Type scale */
  --t-11:  clamp(10px, 0.7cqw,  11px);
  --t-12:  clamp(11px, 0.8cqw,  12px);
  --t-13:  clamp(12px, 0.9cqw,  13px);
  --t-15:  clamp(13px, 1.0cqw,  15px);
  --t-17:  clamp(14px, 1.15cqw, 17px);
  --t-20:  clamp(16px, 1.4cqw,  20px);
  --t-24:  clamp(18px, 1.7cqw,  24px);
  --t-32:  clamp(22px, 2.3cqw,  32px);
  --t-40:  clamp(28px, 2.9cqw,  40px);
  --t-56:  clamp(36px, 4.0cqw,  56px);
  --t-72:  clamp(44px, 5.2cqw,  72px);
  --t-96:  clamp(56px, 6.8cqw,  96px);
  --t-128: clamp(72px, 9.0cqw, 128px);

  --pad: clamp(40px, 5cqw, 88px);
}

/* -------- 2. Reset + base ------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--t-15);
  line-height: 1.55;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv11", "ss03";
  font-optical-sizing: auto;
}

img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }
ul, ol { padding: 0; margin: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: var(--text); }

/* -------- 3. Ambient layers --------------------------------------------- */
/* Aurora previously held a corner-darkening vignette (rgba black 0.45 at the
   100% gradient stop), which combined with the dark --bg base made corners
   read as "missing" or empty. Now an empty layer kept for stacking-order
   compatibility — corners stay uniform with the rest of the canvas. */
/* Ambient layers cover the full viewport (slide canvas AND letterbox)
   so the letterbox bars carry the same grain texture as the slide. The
   deck and stage are kept transparent above so these show through. */
.aurora {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 0;
}

/* Grain uses screen blend so noise stays visible across dark areas. */
.grain {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 1;
  opacity: 0.04;
  mix-blend-mode: screen;
}

/* Continuous ambient caustics — a slow, blurred, grayscale shader driven by
   ambient-caustics.js. Sits with the other ambient layers, behind the
   deck. Only visible while slide 7 is the active slide. */
.ambient-caustics {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  mix-blend-mode: screen;
  /* Fade-out (when leaving slide 7) is immediate-ish so it doesn't linger. */
  transition: opacity 400ms ease 0ms;
}
/* Fade-in starts at the same instant as the flip (1500ms) and ramps for 5s,
   so the caustics quietly build through the rotation and well past Tempo
   landing. The long ramp is what makes the fade actually perceptible at
   this very low peak opacity. The transition definition on the *target*
   state governs the change; leaving slide-7 reverts to the base transition
   above (no delay, quick fade-out). */
body:has(.slide.is-active.animate.slide-org-7) .ambient-caustics {
  opacity: 0.018;
  transition: opacity 5000ms linear 1500ms;
}

/* -------- 4. Slide host -------------------------------------------------- */
/* PDF-style fixed canvas at 1920×1080 (16:9 FHD). All slide content is
   laid out against this canonical box and then GPU-scaled uniformly to
   fit the viewer's window. Letterbox bars (top+bottom or left+right)
   absorb any aspect mismatch. No reflow, ever — like a PDF in a reader. */
#deck {
  position: relative;
  width: 100vw;
  height: 100vh;
  z-index: 2;
  overflow: hidden;
  /* Transparent so the viewport-level ambient layers (aurora wash, grain
     noise, caustics shader) show through into the letterbox area as well
     as the slide canvas. body owns the var(--bg) base color. */
}

.stage {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1920px;
  height: 1080px;
  transform: translate(-50%, -50%) scale(var(--deck-scale, 1));
  transform-origin: center center;
  /* container-type: size makes cqw/cqh inside resolve against this fixed
     1920×1080 layout box (transforms don't affect query container size).
     Result: every length inside the stage computes to the same px on
     every viewer. */
  container-type: size;
  container-name: stage;
  overflow: hidden;
}

.slide {
  position: absolute; inset: 0;
  padding: var(--pad);
  display: flex;
  flex-direction: column;
  opacity: 0;
  pointer-events: none;
  transform: translateY(14px);
  transition:
    opacity 360ms var(--ease),
    transform 360ms var(--ease);
}
.slide.is-active {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
  transition-delay: 80ms;
}

/* Performance: CSS animations don't auto-pause when a slide is offscreen, so
   the org-chart pulses, slot-machine reveals, send-button glows etc. would
   otherwise keep burning GPU on every one of the 23 inactive slides. Pause
   everything inside an inactive slide; the active slide animates normally.
   Keyframed transforms/opacities resume from the same frame on re-activation,
   which matches the visual we want anyway. */
.slide:not(.is-active),
.slide:not(.is-active) * {
  animation-play-state: paused !important;
}

/* -------- 5. Chrome ------------------------------------------------------ */
/* Brand logo sits ON the slide canvas (top-right of the stage), not in
   the viewport corner — keeps the letterbox area clean. Mobile rules
   below override to position:fixed so it stays anchored to the device
   corner where there's no stage. */
.brand {
  position: absolute;
  top: clamp(20px, 2.4cqw, 36px);
  right: clamp(20px, 2.4cqw, 36px);
  z-index: 10;
  display: flex; align-items: center;
  transition: opacity 160ms ease-out;
}
body:has(.slide-cover.is-active) .brand { display: none; }
.brand-logo {
  height: clamp(32px, 3.6cqw, 48px);
  width: auto;
  opacity: 0.75;
  transition: opacity 160ms ease-out;
}
.brand:hover .brand-logo { opacity: 1; }

.footer-meta {
  position: fixed;
  bottom: clamp(20px, 2.4vw, 36px);
  left: clamp(20px, 2.4vw, 36px);
  z-index: 10;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-faint);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.nav {
  position: fixed;
  bottom: clamp(20px, 2.4vw, 36px);
  right: clamp(20px, 2.4vw, 36px);
  z-index: 10;
  display: flex; align-items: center; gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.16em;
}

.nav-btn {
  background: transparent; border: 1px solid transparent;
  color: var(--text-muted);
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 160ms ease-out, background 160ms ease-out, border-color 160ms ease-out;
}
.nav-btn:hover {
  color: var(--text);
  background: rgba(255,255,255,0.03);
  border-color: var(--border);
}
.nav-btn:disabled { opacity: 0.3; cursor: default; }
.nav-btn:disabled:hover { background: transparent; border-color: transparent; }

.counter {
  font-variant-numeric: tabular-nums;
  padding: 0 6px;
  user-select: none;
  cursor: pointer;
}
.counter-current { color: var(--text); }
.counter-sep { color: var(--text-faint); margin: 0 2px; }
.counter.is-editing { cursor: text; }
.counter-input {
  /* Inherit so it visually replaces .counter-current with no shift */
  font: inherit;
  font-variant-numeric: tabular-nums;
  color: var(--accent-bright);
  background: transparent;
  border: none;
  outline: none;
  padding: 0;
  margin: 0;
  width: 2.4ch;
  text-align: center;
  caret-color: var(--accent-bright);
}
.counter-input:focus { outline: none; }

.progress {
  position: fixed; bottom: 0; left: 0; right: 0;
  height: 1px;
  background: var(--border-soft);
  z-index: 10;
}
.progress-fill {
  height: 100%;
  width: 0;
  background: var(--accent-soft);
  transition: width 420ms var(--ease);
}

/* Help overlay */
.help {
  position: fixed; inset: 0;
  background: rgba(8, 9, 10, 0.86);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  z-index: 100;
  display: none;
  align-items: center; justify-content: center;
}
.help.is-visible { display: flex; }
.help-card {
  border: 1px solid var(--border);
  background: var(--bg-elev);
  padding: 32px 36px;
  border-radius: 12px;
  min-width: 360px;
  box-shadow: 0 24px 80px rgba(0,0,0,0.5);
}
.help-title { margin-bottom: 20px; color: var(--text); }
.help-list { display: grid; gap: 10px; margin: 0; }
.help-row {
  display: grid; grid-template-columns: 1fr auto; gap: 24px;
  font-family: var(--font-mono);
  font-size: 12px;
}
.help-row dt { color: var(--text-muted); }
.help-row dd { color: var(--text); margin: 0; }

/* -------- 6. Reusable building blocks ----------------------------------- */
.kicker {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.kicker-strong { color: var(--text-soft); }

.serif { font-family: var(--font-serif); font-style: italic; font-weight: 400; letter-spacing: -0.005em; }
.mono  { font-family: var(--font-mono); }
/* "Supervisor" is the central concept of the deck — anywhere it appears
   in prose it takes the lavender accent. SVG text in the org charts
   uses fill directly. */
.kw-supervisor { color: var(--accent-bright); }
text.kw-supervisor { fill: var(--accent-bright); }

.headline {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.04;
  color: var(--text);
}

/* Reusable inline citation superscript. Drop in next to any claim that
   maps to a numbered entry in the appendix Sources slide. Grayscale by
   design — matches crisis-stat-ref and us-stat-ref so the footnote tier
   reads as one consistent system across the deck. */
.cite-ref {
  font-family: var(--font-mono);
  font-size: 0.42em;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--text-soft);
  vertical-align: super;
  line-height: 1;
  margin-left: 2px;
}

.lede {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-20);
  line-height: 1.45;
  color: var(--text-soft);
  max-width: 56ch;
  letter-spacing: -0.005em;
}

.body-muted {
  color: var(--text-muted);
  font-size: var(--t-17);
  line-height: 1.55;
  max-width: 60ch;
}

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

/* Reveal animations (auto-staggered for direct children with .reveal) */
.slide .reveal {
  opacity: 0;
  transform: translateY(10px);
}
.slide.is-active .reveal {
  animation: reveal 700ms var(--ease) both;
  animation-delay: calc(180ms + var(--reveal-i, 0) * 70ms);
}
@keyframes reveal {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Slide-page break for print */
@media print {
  body { overflow: visible; }
  .aurora, .grain, .ambient-caustics, .nav, .progress, .help, .footer-meta, .brand { display: none !important; }
  #deck { height: auto; }
  .slide {
    position: relative !important;
    inset: auto !important;
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
    page-break-after: always;
    width: 100vw;
    height: 100vh;
  }
}

/* ============================================================================
   PER-SLIDE LAYOUTS
   ============================================================================ */

/* -------- Slide 01: Cover ----------------------------------------------- */
.slide-cover {
  padding: 0;
  align-items: stretch;
  justify-content: stretch;
  overflow: hidden;
}
.cover-bg {
  position: absolute; inset: 0;
  /* No opaque fill — the body's var(--bg) plus the viewport-level grain
     overlay show through, matching the rest of the deck (and the
     letterbox) instead of painting a flatter color over the slide. */
  z-index: 0;
  overflow: hidden;
}
/* A single hairline rule across the canvas — Linear's product chrome */
.cover-rule {
  position: absolute;
  top: 78%; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,255,255,0.04) 14%,
    rgba(255,255,255,0.09) 50%,
    rgba(255,255,255,0.04) 86%,
    transparent 100%);
  opacity: 0;
  animation: rule-draw 1400ms var(--ease) 600ms both;
}
@keyframes rule-draw {
  0%   { opacity: 0; transform: scaleX(0.2); }
  100% { opacity: 1; transform: scaleX(1); }
}

/* Rings illustration — overlapping hairline ellipses around a central axis */
.cover-rings {
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.cover-rings svg,
.cover-rings-img {
  width: 100%;
  max-width: 620px;
  height: auto;
  opacity: 0;
  animation: rings-fade 1800ms var(--ease) 400ms forwards;
}
@keyframes rings-fade {
  from { opacity: 0; transform: scale(0.985); }
  to   { opacity: 1; transform: scale(1); }
}
.rings-group line.rings-axis-h,
.rings-group path.rings-axis-h {
  stroke: rgba(244,245,248,0.18);
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  fill: none;
}
.rings-group line.rings-axis-v {
  stroke: rgba(244,245,248,0.55);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.rings-ring {
  stroke: rgba(244,245,248,0.45);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  fill: none;
}
.rings-ring-7 { stroke-opacity: 0.30; }
.rings-ring-8 { stroke-opacity: 0.20; }
.rings-ring-1 { stroke-opacity: 0.62; }
.cover-grid {
  position: relative;
  z-index: 2;
  width: 100%; height: 100%;
  padding: var(--pad);
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  grid-template-areas:
    "mark     rings"
    "headline rings";
  align-items: center;
  align-content: center;
  gap: clamp(24px, 3cqw, 64px);
}
.cover-mark     { grid-area: mark; }
.cover-rings    { grid-area: rings; }
.cover-headline { grid-area: headline; }
.cover-mark {
  display: flex; align-items: center;
  margin-bottom: clamp(48px, 7cqw, 96px);
}
/* Mobile / narrow viewports: stack vertically with the rings sandwiched
   between the Tempo logo and the headline, per request. */
@media (max-width: 768px) and (orientation: portrait) {
  .cover-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "mark"
      "rings"
      "headline";
    row-gap: clamp(20px, 5vw, 48px);
  }
  .cover-mark { margin-bottom: 0; justify-content: center; }
  .cover-rings { justify-self: center; }
  .cover-rings-img { max-width: min(360px, 70vw); }
  .cover-headline { text-align: center; max-width: none; }
}
.cover-logo {
  height: clamp(48px, 5cqw, 72px);
  width: auto;
}
.cover-headline {
  font-family: var(--font-display);
  font-size: clamp(40px, 6.6cqw, 104px);
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 0.96;
  color: var(--text);
  max-width: 14ch;
}
.cover-headline .line-1 {
  display: block;
  color: var(--text);
}
.cover-headline .line-2 {
  display: block;
  margin-top: 0.06em;
  color: var(--text-soft);
  font-weight: 300;
}
.cover-headline em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  color: var(--accent-bright);
  padding-right: 0.06em;
}
.cover-meta {
  margin-top: clamp(48px, 7cqw, 88px);
  display: flex; align-items: center; gap: 14px;
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.cover-meta-dot {
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--accent-bright);
  box-shadow: none;
}

/* Picker variant has no rings image — drop the grid entirely so the
   headline can sit dead-center on the slide. Logo floats absolutely in
   the top-left corner so it doesn't push the headline off-center. */
.slide-cover:has(.cover-headline-picker) .cover-grid {
  display: flex;
  align-items: center;
  justify-content: center;
}
.slide-cover:has(.cover-headline-picker) .cover-mark {
  position: absolute;
  top: var(--pad);
  left: var(--pad);
  margin: 0;
  z-index: 2;
}

/* -------- Cover headline: iOS-style 3D drum picker -------- */
/* Items are positioned around an invisible cylinder via rotateX +
   translateZ. The drum rotates as a single rigid body (slot-machine
   style) to bring each industry through the focal slot. 18° per slot
   (20 slots / 360°) matches the iOS UIPickerView default. Drum spins
   through 2 full revolutions before settling on Hotels, which then
   animates to purple to mark the focal pick. */
.cover-headline-picker {
  display: block;
  max-width: none;
  line-height: 1.0;
  white-space: nowrap;
  text-align: center;
  /* Picker variant takes the full slide width since the rings image was
     removed — grid override below puts headline in both columns. Slightly
     smaller than the default cover headline so the full sentence breathes. */
  font-size: clamp(40px, 5.8cqw, 88px);
}
.cover-headline-picker .hl-prefix {
  display: inline;
  color: var(--text);
}
.cover-headline-picker .hl-suffix {
  display: inline;
  color: var(--text);
}
.cover-headline-picker .hl-picker {
  position: relative;
  display: inline-block;
  vertical-align: middle;
  margin: 0 0.2em;
  height: 4.5em;
  width: 6.5em;
  /* Perspective creates the cylindrical foreshortening — lower = more
     pronounced fish-eye / tilt on off-center items. */
  perspective: 800px;
  perspective-origin: 50% 50%;
  /* Tiered mask: focal fully opaque, ±18° neighbors at ~50%, ±36° items
     ghosted at ~15% — five-item iOS picker reveal. */
  -webkit-mask-image: linear-gradient(180deg,
      transparent 0%,
      rgba(0,0,0,0.15) 12%,
      rgba(0,0,0,0.5)  28%,
      #000             45%,
      #000             55%,
      rgba(0,0,0,0.5)  72%,
      rgba(0,0,0,0.15) 88%,
      transparent 100%);
          mask-image: linear-gradient(180deg,
      transparent 0%,
      rgba(0,0,0,0.15) 12%,
      rgba(0,0,0,0.5)  28%,
      #000             45%,
      #000             55%,
      rgba(0,0,0,0.5)  72%,
      rgba(0,0,0,0.15) 88%,
      transparent 100%);
}
.cover-headline-picker .hl-picker-drum {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* Drum-origin is pushed back by R = 3.16em so that an item with
     rotateX(0)+translateZ(R) lands at z=0 (picker plane → natural size,
     no perspective magnification). Rest rotation is -126° = Hotels. */
  transform: translateZ(-3.16em) rotateX(-126deg);
  will-change: transform;
}
.cover-headline-picker .hl-picker-item {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  margin-top: -0.5em;
  height: 1em;
  line-height: 1em;
  text-align: center;
  color: var(--text-soft);
  font-weight: 300;
  white-space: nowrap;
  /* Place item on cylinder: rotate to its slot angle, then push out by R.
     R ≈ slot_height / (2·sin(slot_angle/2)) = 1em / (2·sin(9°)) ≈ 3.16em. */
  transform: rotateX(var(--a)) translateZ(3.16em);
  backface-visibility: hidden;
}
/* Hotels starts dim so it looks like every other item during the spin.
   After the drum settles, the focal-color-in keyframe animates it to
   the brand accent — the "locked in" moment of the slot machine. */
.cover-headline-picker .hl-picker-focal {
  color: var(--text-soft);
}
/* Slot-machine spin: 2 full revolutions + 126° to land Hotels at the
   focal slot. Uses the same cubic-bezier as slide 4's crisis-stat slot
   animation for matching deceleration feel. */
@keyframes drum-spin {
  from { transform: translateZ(-3.16em) rotateX(0deg); }
  to   { transform: translateZ(-3.16em) rotateX(-846deg); }
}
.slide-cover.is-active.animate .hl-picker-drum {
  animation: drum-spin 2600ms cubic-bezier(0.18, 0.82, 0.22, 1) 200ms both;
}
/* Color lock-in fires after the drum settles (200ms delay + 2600ms spin
   + 50ms breath). */
@keyframes focal-color-in {
  from { color: var(--text-soft); }
  to   { color: var(--accent-bright); }
}
.slide-cover.is-active.animate .hl-picker-focal {
  animation: focal-color-in 500ms ease-out 2850ms both;
}
@media (prefers-reduced-motion: reduce) {
  .slide-cover.is-active.animate .hl-picker-drum {
    animation: none;
  }
  .cover-headline-picker .hl-picker-focal {
    color: var(--accent-bright);
  }
}

/* -------- Slide 11 (hub-and-spoke) + Slide 12 (Tempo mesh) -----------
   Identical outer layout so the diagram lands at the same x/y on both
   slides — A/B comparison stays apples-to-apples. */
.slide-hub-spoke,
.slide-tempo-mesh {
  justify-content: flex-start;
  align-items: stretch;
  gap: 0;
}
/* ====================================================================
   SLIDES 11 + 12 · ACTIVITY + NETWORK
   --------------------------------------------------------------------
   Linear-style aesthetic. Two clean containers side by side: a stat /
   task feed on the left, the network diagram on the right. No app
   chrome, no decorative grid lines — the data is the design.
   ==================================================================== */
.hub-spoke-split {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin: clamp(20px, 2.8cqh, 44px) auto 0;
  min-height: 0;
  width: clamp(1000px, 86cqw, 1400px);
  max-width: 92cqw;
}

/* Body: two clean panels — activity (left), network (right). The chat
   bubble that kicks off the sequence overlays the canvas itself, near
   the housekeeper node, rather than living in a third panel. */
.hub-spoke-body {
  flex: 1;
  display: grid;
  grid-template-columns: clamp(260px, 20cqw, 320px) minmax(0, 1fr);
  gap: clamp(16px, 1.4cqw, 24px);
  min-height: 0;
}

/* Panels — transparent so the diagram and task list breathe against the
   deck background. No fills, no chrome — just structure. */
.hub-spoke-panel {
  display: flex;
  flex-direction: column;
  padding: 0;
  min-height: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
}
.hub-spoke-panel--side {
  gap: clamp(14px, 1.4cqh, 22px);
}
.hub-spoke-panel--canvas {
  position: relative;
}

/* Network canvas — just a clean inner area for the diagram. No grid
   pattern, no inner border, no crosshair. */
.hub-spoke-canvas {
  position: relative;
  flex: 1;
  width: 100%;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  overflow: visible;
}

.hub-spoke-stage {
  min-height: 0;
}
.hub-spoke-figure {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  max-height: 100%;
  display: block;
  overflow: visible;
}

/* Spokes connecting hub → outer nodes. Same quiet token used by the
   org-chart links (slide 5/6/7) so this diagram reads as part of the
   same visual family — not brighter or louder than its neighbours. */
.hub-spoke-spokes line {
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: 1;
}
/* Mesh slide has 15 edges in a small area — soften so the lattice
   reads as background structure, not foreground noise. */
.hub-spoke-spokes.mesh-edges line {
  opacity: 0.72;
}

/* Radial connectors between each outer role and its inner agent on
   slide 12. Same hairline as the spokes. */
.hub-spoke-radial-lines line {
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: 1;
}

/* Inner agent circles — same hairline stroke as the outer roles for
   a quiet, unified look. The Tempo logo inside is what marks them as
   the computing layer. */
.hub-spoke-node.is-agent circle {
  fill: var(--bg-elev);
  stroke: var(--border-strong);
  stroke-width: 1;
}


/* Outer nodes. Elevated background fill + the same hairline stroke as
   the org-chart node rectangles. */
.hub-spoke-node circle {
  fill: var(--bg-elev);
  stroke: var(--border-strong);
  stroke-width: 1;
}

/* Corona: blurred white disc behind each node. Hidden by default; when
   the pulse arrives, JS adds .is-flashing → keyframe pops the opacity
   in fast, holds briefly, then fades out slowly to feel like a ripple
   following the dot off the node. */
.hub-spoke-coronas circle {
  fill: #FFFFFF;
  opacity: 0;
  filter: blur(14px);
  pointer-events: none;
}
.hub-spoke-coronas circle.is-flashing {
  animation: corona-flash 750ms ease-out forwards;
}
@keyframes corona-flash {
  0%   { opacity: 0; }
  10%  { opacity: 0.65; }  /* pop (≈75ms) */
  22%  { opacity: 0.65; }  /* brief hold while dot is at node */
  100% { opacity: 0; }     /* slow fade as the dot leaves */
}

/* Center supervisor: lavender stroke so the hub carries more weight
   than its satellites. Solid body so the corona bleeds out only as a
   halo. Stroke matches the slide-7 `.is-target` accent treatment. */
.hub-spoke-supervisor {
  fill: var(--bg-elev);
  stroke: var(--accent-soft);
  stroke-width: 1.2;
}

/* Node labels — sit INSIDE their circles. Small mono caps, white for
   systems, lavender for people/supervisor. */
.hub-spoke-labels text {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  fill: var(--text-soft);
}
.hub-spoke-label-people { fill: var(--text-soft) !important; }
.hub-spoke-label-supervisor {
  fill: var(--accent-bright) !important;
  font-size: 12px !important;
  letter-spacing: 0.14em !important;
}

/* Pulse: hidden until JS adds .is-live, then glows in the accent color
   while it travels. */
.hub-spoke-pulse {
  fill: var(--accent-bright);
  opacity: 0;
  filter: drop-shadow(0 0 6px rgba(110, 123, 230, 0.85));
  transition: opacity 180ms ease-out;
}
.hub-spoke-pulse.is-live {
  opacity: 1;
}

/* Mesh slide reuses the soft white "light pulse" recipe from the Use of
   Funds roadmap line — a small white core wrapped in a multi-layer white
   drop-shadow bloom — instead of the purple accent ball used on the
   hub-and-spoke slide. Core is shrunk via CSS `r` so the bloom carries
   the visual weight rather than a fat solid dot. */
.slide-tempo-mesh .hub-spoke-pulse {
  r: 3;
  fill: #FFFFFF;
  filter:
    blur(1.2px)
    drop-shadow(0 0 3px rgba(255, 255, 255, 0.95))
    drop-shadow(0 0 8px rgba(255, 255, 255, 0.6))
    drop-shadow(0 0 18px rgba(255, 255, 255, 0.32));
}

/* Activity panel column (the .hub-spoke-readouts wrapper). */
.hub-spoke-readouts {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Stat row — two columns of label/value, no inner card chrome.
   The parent panel already provides the container. */
.hub-spoke-stat-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 1.6cqw, 24px);
  padding-bottom: clamp(16px, 1.6cqh, 24px);
  border-bottom: 1px solid rgba(244, 245, 248, 0.06);
}
.hub-spoke-readout {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}
.hub-spoke-readout-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.hub-spoke-readout-value {
  font-family: var(--font-display);
  font-size: clamp(24px, 2.4cqw, 34px);
  font-weight: 300;
  letter-spacing: -0.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* Task modal: lives below the stat row inside the side panel. */
.hub-spoke-task-modal {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

/* Daily-steps header — its own bar. Mono caps so it reads like a
   task-list section title, not body copy. */
.cmd-task-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: clamp(8px, 0.9cqh, 12px) clamp(10px, 1cqw, 14px);
  background: rgba(244, 245, 248, 0.04);
  border: 1px solid rgba(244, 245, 248, 0.08);
  border-radius: 6px;
  margin-bottom: clamp(10px, 1cqh, 14px);
}
.cmd-task-header-label {
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.9cqw, 12px);
  font-weight: 500;
  color: var(--text-soft);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Task feed — a real task list, not a fading activity stream. Mono
   so it reads as work items being checked off. */
.cmd-task-list {
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 0.5cqh, 8px);
  margin: 0;
  padding: 0;
  list-style: none;
  min-height: 0;
}
.cmd-task-item {
  position: relative;
  padding-left: 22px;
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.95cqw, 13px);
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--text-soft);
  opacity: 0;
  transform: translateY(-3px);
  animation: cmd-task-in 260ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.cmd-task-item::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid var(--accent-bright);
  opacity: 0.4;
  box-sizing: border-box;
}
.cmd-task-item.is-active {
  color: var(--text);
}
.cmd-task-item.is-active::before {
  background: var(--accent-bright);
  border-color: var(--accent-bright);
  opacity: 1;
  box-shadow: 0 0 0 4px rgba(110, 123, 230, 0.16);
  animation: cmd-task-pulse 1.6s ease-in-out infinite;
}
.cmd-task-item.is-done {
  color: var(--text);
  opacity: 1;
}
.cmd-task-item.is-done::before {
  width: 11px;
  height: 11px;
  left: 3px;
  top: 0.5em;
  border: none;
  border-radius: 0;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%234ADE80' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2 6.5l3 3 6-6.5'/></svg>") center / contain no-repeat;
  opacity: 1;
  box-shadow: none;
  animation: none;
}
/* Dropped-ball state — red X. Used on slide 11 to show that the
   hub-and-spoke flow loses a few tasks along the way. */
.cmd-task-item.is-failed {
  color: var(--text-soft);
  opacity: 0.85;
}
.cmd-task-item.is-failed::before {
  width: 11px;
  height: 11px;
  left: 3px;
  top: 0.5em;
  border: none;
  border-radius: 0;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23EF4444' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M3 3l6 6M9 3l-6 6'/></svg>") center / contain no-repeat;
  opacity: 1;
  box-shadow: none;
  animation: none;
}
@keyframes cmd-task-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes cmd-task-pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(110, 123, 230, 0.16); }
  50%      { box-shadow: 0 0 0 7px rgba(110, 123, 230, 0.06); }
}

/* Inciting modal — a quiet text tray. Just the housekeeper's question
   in quotes; no avatar, no header, no shadow. Stays in the same visual
   family as the diagram: elevated fill + border-strong hairline. */
.hub-spoke-msg {
  padding: 10px 14px 11px;
  border-radius: 6px;
  border: 1px solid var(--border-strong);
  background: var(--bg-elev);
}

/* Floating placement — fixed position behind the SVG via z-index. The
   box extends from inside the housekeeper circle (hidden behind it)
   out past the corona on the right. A large left padding pushes the
   text content into the visible area past the corona. */
.hub-spoke-msg--floating {
  position: absolute;
  top: clamp(180px, 19cqh, 230px);
  /* Anchor by the LEFT — left edge sits inside the housekeeper circle
     (hidden behind it), the rest of the box and the text extend out
     to the right past the corona. */
  left: clamp(680px, 38cqw, 760px);
  width: clamp(320px, 21cqw, 420px);
  padding: 10px clamp(14px, 1cqw, 18px) 11px clamp(85px, 5.75cqw, 120px);
  white-space: nowrap;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 240ms ease-out;
}
.hub-spoke-msg--floating.is-visible {
  opacity: 1;
}

/* Mesh slide moved the housekeeper role circle up to (576.5, 175) on
   the outer ring (was 190 on slide 11). Drop top a notch to re-centre
   the floating box on that new circle. */
.slide-tempo-mesh .hub-spoke-msg--floating {
  top: clamp(155px, 16.1cqh, 200px);
}

.hub-spoke-msg .cmd-text {
  font-family: var(--font-display);
  font-size: clamp(13px, 0.95cqw, 15px);
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--text);
  font-style: italic;
  min-height: 1.4em;
  display: inline-block;
}
/* Typewriter caret — thin lavender bar blinking at the end of the
   message while text streams in. */
.hub-spoke-msg .cmd-text.is-typing::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin-left: 2px;
  background: var(--accent-bright);
  vertical-align: text-bottom;
  animation: hub-spoke-caret 700ms steps(2, end) infinite;
}
@keyframes hub-spoke-caret {
  0%, 50%   { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* Alert variant of the @mention chip — used for the inciting ping.
   Slightly warmer, more refined than the base cmd-mention. */
.cmd-mention--alert {
  background: rgba(232, 178, 102, 0.16);
  color: #F4CE9C;
  padding: 3px 9px 3px 8px;
  border-radius: 999px;
  font-weight: 500;
  letter-spacing: 0.005em;
  font-size: 0.85em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cmd-mention--alert::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #F4CE9C;
  box-shadow: 0 0 8px rgba(244, 206, 156, 0.6);
}

/* -------- Slide 02: Team — title top-left, dossier cards below ------- */
/* Layout matches every other slide (flex column, content top-aligned).
   The title wrapper stretches naturally; the team grid has its own
   880px max-width so it stays centered below the full-width title. */
.slide-team {
  justify-content: flex-start;
  align-items: stretch;
  gap: clamp(28px, 3cqw, 44px);
}
.team-headline {
  max-width: 50ch;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-24);
  color: var(--text);
  letter-spacing: -0.02em;
  line-height: 1.3;
  margin: 6px 0 0;
}
.team-headline .em {
  font-family: inherit;
  font-style: normal;
  color: var(--accent-bright);
  font-weight: inherit;
}

.team-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 5cqw, 96px);
  align-content: center;
  justify-items: center;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  flex: 1;
  /* Default min-height:auto prevents flex-shrink from shrinking the grid
     below its card content, so .clientHeight always equals card height
     and the JS scale fit can't read available space. min-height:0 lets
     the grid honestly report the remaining slide space. */
  min-height: 0;
}

/* Editorial-magazine layout — no card chrome, photos do the talking */
.founder-card {
  position: relative;
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 1.8cqw, 24px);
  width: 100%;
  /* Card holds text at a comfortable reading width; if the resulting card
     stack is taller than the viewport allows, main.js scales .team-grid
     uniformly (transform:scale) so photo + text + gaps all shrink together
     and the bullets never reflow narrower than the photo. */
  max-width: 480px;
}

.founder-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 5px 10px 5px 8px;
  border: 1px solid rgba(244,245,248,0.08);
  border-radius: 999px;
  background: rgba(0,0,0,0.18);
}
.founder-status-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: #4ADE80;
  box-shadow: 0 0 0 3px rgba(74,222,128,0.12);
}

.founder-photo-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg-elev-2);
}
.founder-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: contrast(1.04) saturate(0.95);
  display: block;
}

.founder-id {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.founder-name {
  font-family: var(--font-display);
  font-size: clamp(26px, 2.4cqw, 32px);
  font-weight: 500;
  letter-spacing: -0.025em;
  color: var(--text);
  margin: 0;
  line-height: 1.04;
}

.founder-role {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  font-weight: 500;
  color: var(--text-soft);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.founder-role-note {
  text-transform: none;
  letter-spacing: 0.02em;
  font-weight: 500;
  color: var(--text-soft);
  opacity: 1;
  margin-left: 6px;
  font-size: 0.92em;
}

.founder-bio {
  font-family: var(--font-display);
  font-size: var(--t-13);
  color: var(--text-soft);
  line-height: 1.45;
  margin: 6px 0 0;
  letter-spacing: -0.005em;
  max-width: 36ch;
}

/* --- Stats row (Linear cycle-stat register) --- */
.founder-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 1.6cqw, 24px);
  padding-bottom: clamp(14px, 1.4cqw, 18px);
  border-bottom: 1px solid rgba(244,245,248,0.06);
}
.founder-stat {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.founder-stat-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.founder-stat-value {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.founder-stat-value .num {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(22px, 2.4cqw, 30px);
  letter-spacing: -0.035em;
  color: var(--text);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.founder-stat-value .unit {
  font-family: var(--font-display);
  font-size: var(--t-13);
  color: var(--text-muted);
  letter-spacing: -0.005em;
}

/* --- "Previously at" section with company chips --- */
.founder-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.founder-section-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.founder-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.founder-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 11px;
  border: 1px solid rgba(244,245,248,0.10);
  background: var(--bg-elev-2);
  border-radius: 6px;
  font-family: var(--font-display);
  font-size: var(--t-13);
  color: var(--text-soft);
  letter-spacing: -0.005em;
  font-weight: 500;
  line-height: 1.2;
}
.founder-chip-emph {
  background: rgba(94,106,210,0.16);
  color: #C0C8EE;
  border-color: rgba(94,106,210,0.28);
}
.founder-chip-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.04em;
  padding-left: 6px;
}

/* Quick-read bullets — dim baseline, brand names pop white. Hairline above
   replaces the dropped card border, keeping the editorial divider. */
.founder-bullets {
  list-style: none;
  margin: 0;
  padding: clamp(14px, 1.4cqw, 20px) 0 0;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.founder-bullets li {
  position: relative;
  padding-left: 18px;
  font-size: clamp(15px, 1.25cqw, 19px);
  color: var(--text-muted);
  line-height: 1.5;
  /* Avoid orphan single-word last lines (e.g. "Related", "Music",
     "restaurants") so brand/keyword endings stay with their phrase. */
  text-wrap: pretty;
}
.founder-bullets li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 9px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-soft);
}
.founder-bullets strong {
  color: var(--text);
  font-weight: 500;
}

/* Affiliation logos — companies first, schools after. Quiet hairline
   above to separate from the bullets, monochrome treatment so the
   logos read as a unified row rather than a stack of brand colors. */
.founder-logos {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.2cqw, 36px);
  /* margin-top: auto pushes the logo row to the bottom of each card so
     both founders' logos sit on the same horizontal regardless of how
     many bullet lines wrap above. */
  margin-top: auto;
  padding-top: clamp(14px, 1.4cqw, 20px);
  border-top: 1px solid var(--border);
}
.founder-logo {
  height: clamp(24px, 2cqw, 32px);
  width: auto;
  max-width: clamp(140px, 12cqw, 200px);
  object-fit: contain;
}
/* Per-logo height bumps to normalize optical weight. Each source file
   bakes in different glyph-to-frame padding, so a single height makes
   the wordmarks render at different sizes. Numbers below target a
   consistent cap-height across the row. */
.founder-logo[alt="Yale"] {
  height: clamp(34px, 2.8cqw, 46px);
  filter: brightness(0) invert(1);
}
.founder-logo[alt="UC Berkeley"] {
  filter: brightness(0) invert(1);
}
.founder-logo[alt="Harvard"] {
  height: clamp(40px, 3.4cqw, 54px);
}
.founder-logo[alt="NFM"] {
  height: clamp(22px, 1.8cqw, 30px);
}

/* -------- Slide 03: Vision --------------------------------------------- */
.slide-vision {
  align-items: center;
  justify-content: center;
  text-align: center;
}
.vision-headline {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(32px, 4.4cqw, 68px);
  letter-spacing: -0.025em;
  line-height: 1.08;
  color: var(--text);
  max-width: 46ch;
  text-wrap: balance;
}
.vision-line-1,
.vision-line-2 {
  display: block;
}
.vision-line-2 {
  margin-top: 1em;
}
.vision-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.05em;
  letter-spacing: -0.01em;
  color: var(--accent-bright);
}
.vision-headline .accent-num {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.08em;
  color: var(--accent-bright);
  padding-right: 0.04em;
}

/* -------- Slide 14: Close (future-state vision) ------------------------ */
.slide-close {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(28px, 3cqw, 48px);
}
.close-kicker { color: var(--accent-bright); }
.close-headline {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(38px, 5.2cqw, 76px);
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--text);
  margin: 0;
  max-width: 24ch;
}
.close-headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.04em;
  letter-spacing: -0.01em;
}
.close-headline .accent-num {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.08em;
  color: var(--accent-bright);
  padding-right: 0.04em;
}
.close-tag {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(22px, 2.4cqw, 32px);
  color: var(--text-soft);
  margin: 0;
  line-height: 1.3;
}
.vision-kicker {
  margin-bottom: clamp(40px, 5cqw, 64px);
}

/* -------- Slide 04: Traction — Linear Cycle dashboard register --------- */
.slide-traction {
  justify-content: flex-start;
  overflow: hidden;
}
.traction-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-40);
  letter-spacing: -0.025em;
  line-height: 1.06;
  max-width: 24ch;
  color: var(--text);
  margin-top: 8px;
}
/* Two-column split: pilot impact | pipeline trajectory.
   Vertical hairline runs between them, big mono numbers drive the eye. */
.traction-split {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6cqw, 112px);
  align-content: center;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  flex: 1;
}
.traction-split::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 8%;
  bottom: 8%;
  width: 1px;
  background: var(--border);
}

.traction-side {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 2.6cqw, 40px);
}

.traction-side-head {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: clamp(14px, 1.4cqw, 18px);
  border-bottom: 1px solid var(--border-soft);
}

.traction-mark {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-bright);
}

.traction-name {
  font-family: var(--font-display);
  font-size: var(--t-24);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0;
  line-height: 1.04;
}

.traction-sub {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.traction-stat {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.traction-num {
  font-family: var(--font-mono);
  font-size: clamp(40px, 4.4cqw, 56px);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.03em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.traction-label {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.traction-tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid rgba(94, 106, 210, 0.30);
  background: rgba(94, 106, 210, 0.10);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #C0C8EE;
  align-self: flex-start;
}
.traction-tag-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-bright);
  flex-shrink: 0;
}

/* Hero proof point — serif italic on the job title being made obsolete.
   Flex 1 + center so the hero block matches the chart column's vertical span. */
.traction-hero {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
}
.traction-hero-text {
  font-family: var(--font-display);
  font-size: clamp(34px, 3.6cqw, 48px);
  font-weight: 400;
  letter-spacing: -0.025em;
  line-height: 1.06;
  color: var(--text);
}
.traction-hero-text .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.005em;
}
.traction-hero-meta {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* Supporting numbers under the hero — smaller, side-by-side. */
.traction-supporting {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 2cqw, 32px);
  padding-top: clamp(14px, 1.4cqw, 20px);
  border-top: 1px solid var(--border-soft);
}
.traction-num-sm {
  font-size: clamp(26px, 2.6cqw, 36px);
}

/* 4-month dual-metric chart: indigo bars (properties) + yellow line (ARR).
   Same visual idiom as the original — chunky bars below, smooth trajectory
   overlay on top, hatched future-pipeline zone to the right. */
.traction-chart {
  flex: 1;
  display: flex;
  align-items: center;
  width: 100%;
}
.traction-chart svg {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 1;
  max-height: clamp(200px, 26cqh, 280px);
  display: block;
  overflow: visible;
}
.tr-axis {
  stroke: rgba(244, 245, 248, 0.18);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  fill: none;
}
.tr-divider {
  stroke: rgba(244, 245, 248, 0.14);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  fill: none;
}
.tr-bar {
  fill: rgba(94, 106, 210, 0.36);
}
.tr-bar-current {
  fill: var(--accent);
  filter: drop-shadow(0 0 14px rgba(94, 106, 210, 0.45));
}
.tr-line {
  fill: none;
  stroke: #F5C455;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.tr-marker         { fill: #F5C455; }
.tr-marker-current { fill: #F5C455; }
.tr-marker-glow    { fill: #F5C455; opacity: 0.20; }
.tr-num {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px;
  fill: #F5C455;
  letter-spacing: -0.02em;
  font-weight: 500;
}
.tr-num-strong {
  fill: #FFEAA0;
  font-size: 13px;
}
.tr-month {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 11px;
  fill: var(--text-soft);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.tr-month-strong {
  fill: var(--text);
}
.tr-prop {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 10px;
  fill: var(--text-dim);
  letter-spacing: 0.06em;
}
.tr-prop-strong {
  fill: var(--text-soft);
  font-weight: 500;
}
.tr-pipeline {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 10px;
  fill: rgba(244, 245, 248, 0.32);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Projected zone — bars get a lighter fill + dashed outline; line goes dashed. */
.tr-bar-proj {
  fill: rgba(94, 106, 210, 0.18);
  stroke: rgba(94, 106, 210, 0.42);
  stroke-width: 1;
  stroke-dasharray: 2 2.5;
  vector-effect: non-scaling-stroke;
}
.tr-bar-end {
  fill: rgba(94, 106, 210, 0.45);
  stroke: rgba(94, 106, 210, 0.85);
  stroke-dasharray: none;
  filter: drop-shadow(0 0 12px rgba(94, 106, 210, 0.35));
}
.tr-line-proj {
  stroke: #F5C455;
  stroke-dasharray: 4 4;
  opacity: 0.85;
}
.tr-marker-proj {
  fill: var(--bg);
  stroke: #F5C455;
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
}
.tr-marker-end {
  fill: #F5C455;
  filter: drop-shadow(0 0 6px rgba(245, 196, 85, 0.6));
}
.tr-zone-label {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 10px;
  fill: rgba(244, 245, 248, 0.36);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tr-zone-label-proj {
  fill: rgba(245, 196, 85, 0.55);
}

.traction-projections {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.4cqw, 20px);
  padding-top: clamp(14px, 1.4cqw, 20px);
  border-top: 1px solid var(--border-soft);
}
.cycle-tab.is-active .cycle-tab-count { color: var(--text-soft); }

/* -------- Slides 07-08: Traction v2 split — proof + pipeline ----------- */
/* Slide 07 (proof): the W Hollywood photo carries the slide. The right
   column is intentionally sparse — a kicker, the W mark, a claim, two
   stats — so the eye lands on the photo first and reads top-down on the
   right second. Whitespace is the design. */
.slide-traction-proof .proof-split {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(40px, 5cqw, 80px);
  margin-top: clamp(24px, 3cqh, 40px);
  padding-bottom: clamp(8px, 1.2cqh, 18px);
  flex: 1;
  min-height: 0;
  align-items: stretch;
}

/* Hero photo: rounded card filling the left column, with a subtle bottom
   gradient for a touch of cinematic depth. No competing content here. */
.slide-traction-proof .proof-media {
  position: relative;
  margin: 0;
  border-radius: 12px;
  overflow: hidden;
  min-width: 0;
  min-height: 0;
  background: var(--bg-elev);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04) inset,
    0 24px 60px -28px rgba(0, 0, 0, 0.55);
}
.slide-traction-proof .proof-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
.slide-traction-proof .proof-media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(8, 9, 10, 0) 60%, rgba(8, 9, 10, 0.32) 100%);
}

/* Right column: vertical centering, generous breathing room between
   each beat (kicker → mark → claim → stats). */
.proof-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(20px, 2.6cqh, 36px);
  min-width: 0;
  padding-right: clamp(8px, 1.2cqw, 24px);
}
.proof-text .v2-section-label {
  margin-bottom: 0;
}
.proof-logo {
  display: block;
  align-self: flex-start;
  height: clamp(28px, 3.4cqh, 42px);
  width: auto;
  filter: brightness(0) invert(1);
  opacity: 0.92;
  margin-top: clamp(-4px, -0.4cqh, 0px);
}

/* Claim is the punchline. Slightly lighter weight + serif italic accent
   keeps it editorial rather than salesy. */
.proof-claim {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(30px, 3.4cqw, 46px);
  letter-spacing: -0.022em;
  line-height: 1.12;
  color: var(--text);
  margin: 0;
  max-width: 18ch;
}
.proof-claim .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.005em;
}

/* Body sits under the claim as elaboration — what "eliminated" actually
   means in practice. Soft, narrow, gives the eye a graceful step-down
   from the claim before it lands on the proof numbers. */
.proof-body {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(14px, 1.05cqw, 17px);
  line-height: 1.55;
  color: var(--text-soft);
  max-width: 38ch;
  margin: 0;
}

/* Two stats, each smaller and quieter than before — they support the
   claim, they don't compete with it. A hairline vertical divider between
   them adds editorial structure without adding visual weight. */
/* Three stats in a row: number on top, short label below. No container,
   no pills — just clean stacked numerals letting the type carry it. */
.proof-stats {
  display: flex;
  align-items: flex-start;
  gap: clamp(32px, 3.6cqw, 52px);
  margin-top: 0;
}
.proof-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(6px, 0.7cqw, 10px);
}
.proof-stat-divider { display: none; }
/* Mirrors slide-04 crisis stats — display font, signed number, accent
   color when the metric moved in a good direction. */
.proof-num {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(28px, 3.1cqw, 44px);
  letter-spacing: -0.04em;
  line-height: 1;
  color: #FFFFFF;
  white-space: nowrap;
}
/* Unit suffix that follows a number (e.g. "min" after "−12") — smaller
   so the digit reads as the headline figure, with the unit as annotation. */
.proof-num-unit {
  font-size: 0.65em;
  font-weight: 400;
  letter-spacing: 0;
  margin-left: 0.05em;
}
.proof-stat.is-down .proof-num,
.proof-stat.is-down .proof-lbl-arrow { color: var(--accent-bright); }
.proof-stat.is-up   .proof-num,
.proof-stat.is-up   .proof-lbl-arrow { color: #FFFFFF; }
.proof-lbl {
  font-family: var(--font-display);
  font-size: clamp(14px, 1.2cqw, 18px);
  font-weight: 400;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--text);
  margin: 0;
  line-height: 1.2;
  display: flex;
  align-items: center;
  gap: 0.35em;
}
.proof-lbl-arrow {
  width: 0.95em;
  height: 0.95em;
  flex: none;
  color: currentColor;
}

/* Card wrapping the hero trio, the secondary stats footer, and the case
   study body — bordered container so the receipts + narrative read as
   one visual unit, with hairline dividers between the three sections.
   Stretches to the right column's full width so the W Hollywood receipts
   and the opportunity card below it read as a matched pair. */
.proof-stats-card {
  width: 100%;
  max-width: 100%;
  margin-top: clamp(8px, 1cqh, 16px);
  padding: clamp(18px, 2cqw, 28px) clamp(20px, 2.4cqw, 32px);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.015);
}
.proof-stats-card .proof-stats {
  margin-top: 0;
}
/* Logo sits inside the card as a brand-mark header. When followed by
   stats, the stats get the same hairline divider we use for the other
   sections — keeps the card visually segmented. */
.proof-stats-card > .proof-logo {
  margin-top: 0;
  margin-bottom: 0;
}
.proof-stats-card > .proof-logo + .proof-stats {
  margin-top: clamp(14px, 1.6cqh, 22px);
  padding-top: clamp(12px, 1.4cqh, 18px);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
/* Body inside the card: hairline divider on top, no width constraint so
   it wraps to the card's natural width (set by the stat row). */
.proof-stats-card .proof-body {
  margin-top: clamp(14px, 1.6cqh, 22px);
  padding-top: clamp(12px, 1.4cqh, 18px);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  max-width: none;
}
/* Secondary stats below the hero trio: a single mono line with a hairline
   divider above, so the supporting numbers (deploy speed, ROI) are visible
   without competing with the three title-mapped hero stats. */
.proof-stats-footer {
  margin-top: clamp(14px, 1.6cqh, 22px);
  padding-top: clamp(12px, 1.4cqh, 18px);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.95cqw, 13px);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.proof-stats-footer strong {
  font-weight: 500;
  color: #FFFFFF;
}
.proof-stats-footer-dot {
  color: var(--text-dim);
  margin: 0 0.4em;
}

/* Opportunity card — same shell as the W Hotels card so the two read as
   a matched pair. The hero number reuses .proof-num as-is (Geist 300)
   and only the color shifts to accent-bright via .is-down. */
/* Title slot where the brand logo sits on the W card. Matches the
   .crisis-label type spec (the "Wages" label on the previous slide) so
   the two slides share a visual register. Height tracks the W logo's
   clamp so the two card headers line up. */
.proof-logo--text {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 1.9cqw, 28px);
  letter-spacing: -0.02em;
  line-height: 1.05;
  text-transform: none;
  color: var(--text);
  height: clamp(28px, 3.4cqh, 42px);
  display: inline-flex;
  align-items: center;
  filter: none;
  opacity: 1;
}
/* Pill marquee — slides the duplicated track left at a constant speed so
   the row scrolls itself. Hidden overflow + edge mask matches the visual
   language of other infinite rows in the deck. */
.opp-pills {
  margin-top: clamp(14px, 1.6cqh, 22px);
  padding-top: clamp(12px, 1.4cqh, 18px);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}
.opp-pills-track {
  display: flex;
  width: max-content;
  animation: opp-pills-marquee 28s linear infinite;
}
@keyframes opp-pills-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .opp-pills-track { animation: none; }
}
.opp-pill {
  flex: none;
  margin-right: clamp(6px, 0.6cqw, 10px);
  padding: clamp(5px, 0.55cqh, 8px) clamp(11px, 1cqw, 14px);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 99px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(12px, 0.95cqw, 14px);
  letter-spacing: -0.005em;
  line-height: 1.2;
  color: var(--text);
  white-space: nowrap;
}

/* Slide 08 (pipeline): chart on top, marquee on bottom — both full width
   so they breathe more than they did when stacked alongside the proof card. */
.slide-traction-pipeline .pipeline-stack {
  display: flex;
  flex-direction: column;
  gap: clamp(56px, 7cqh, 100px);
  margin-top: clamp(20px, 2.6cqh, 32px);
  flex: 1;
  min-height: 0;
}
.pipeline-block {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.4cqh, 18px);
  min-height: 0;
  min-width: 0;
}
.pipeline-block--chart { flex: 3; }
/* Marquee block takes the remaining vertical space; the header (text)
   sits at its top, the marquee logos float centered in what's left so
   they end up at the midpoint between the text and the slide's nav. */
.pipeline-block--marquee {
  flex: 1;
  gap: 0;
  justify-content: flex-start;
}
.pipeline-block--marquee .pipeline-block-head {
  flex: 0 0 auto;
}
.pipeline-block--marquee .v2-marquee {
  flex: 0 0 auto;
  margin-top: clamp(18px, 2.4cqh, 32px);
  margin-bottom: clamp(8px, 1cqh, 16px);
}
.pipeline-block-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: clamp(8px, 1cqh, 14px);
  border-bottom: 1px solid var(--border);
}
/* Plain variant: a single all-white line + a small mono assumption note,
   used for the pipeline section so the marquee carries the weight. */
.pipeline-block-head--plain {
  border-bottom: none;
  padding-bottom: 0;
}
.pipeline-fine {
  margin-top: clamp(6px, 0.8cqh, 12px);
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.04em;
  color: var(--text-dim);
}
/* Matches the slide headline (.traction-v2-headline--single) exactly so
   the two display lines on this slide read as a matched pair. */
.pipeline-headline-plain {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(18px, 1.75cqw, 28px);
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: #FFFFFF;
}

/* Pipeline section header: single line at the default pipeline-headline
   size, with "$58m Pipeline" bolded in lavender. Divider below it
   separates the header from the logo marquee. */
.pipeline-block--marquee .pipeline-block-head--plain {
  border-bottom: 1px solid var(--border);
  padding-bottom: clamp(10px, 1.2cqh, 16px);
}
.pipeline-headline-plain strong {
  font-weight: 500;
  color: var(--accent-bright);
}

/* Twin growth charts: ARR on the left, properties on the right. The actual
   bars + axes are rendered by ApexCharts into .v2-chart-canvas; this layer
   just provides the title strip and the flex container that gives the
   library a bounded height to draw into. */
.v2-chart-pair {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 3cqw, 48px);
  /* Narrower charts make the growth lines/bars read like a hockey
     stick — wide charts flatten the slope visually. */
  max-width: clamp(800px, 80cqw, 1200px);
  width: 100%;
  margin: 0 auto;
}
.v2-chart-card {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}
.v2-chart-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(14px, 1.05cqw, 17px);
  letter-spacing: -0.005em;
  color: var(--text-soft);
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 0 0 clamp(4px, 0.6cqh, 10px);
}
.v2-chart-title-meta {
  font-family: var(--font-mono);
  font-size: clamp(14px, 1.05cqw, 17px);
  letter-spacing: 0.04em;
  color: #FFFFFF;
  text-transform: uppercase;
}
.v2-chart-title-sep {
  color: var(--text-dim);
  margin: 0 2px;
}
.v2-chart-title-meta-unit {
  color: var(--text-soft);
  opacity: 0.65;
}
.v2-chart-canvas {
  flex: 1;
  min-height: 0;
  min-width: 0;
}

/* Traction bar charts (slide 04c). Solid accent bars = contracted; striped
   bars = out-for-signature (pending close). Two bars per chart, second bar
   stacked with the striped portion on top. */
.tb-svg {
  width: 100%;
  height: 100%;
  display: block;
}
.tb-grid {
  stroke: var(--border);
  stroke-width: 1;
  stroke-dasharray: 2 4;
  opacity: 0.6;
}
.tb-axis {
  stroke: var(--border-strong);
  stroke-width: 1;
}
.tb-bar { fill: var(--accent-bright); }
.tb-bar-striped {
  stroke: var(--accent-bright);
  stroke-width: 1;
}
.tb-val {
  fill: #FFFFFF;
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 500;
  letter-spacing: 0.02em;
}
.tb-cat {
  fill: var(--text-soft);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Apex render tweaks — kill its default white tooltip flash, smooth grid. */
.apexcharts-tooltip { display: none !important; }
.apexcharts-gridline { stroke-opacity: 0.6; }
.apexcharts-text tspan { font-family: var(--font-mono) !important; }

/* -------- Slide 08: Traction v2 — validated playbook ------------------ */
/* Story sequence: hero (real role on indefinite leave + ROI proof) →
   signed contracts (momentum) → C-suite pipeline (scale of demand). */
.slide-traction-v2 {
  display: flex;
  flex-direction: column;
}
.traction-v2-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-40);
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--text);
  margin-top: 8px;
}
.traction-v2-headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.005em;
}
/* Single-line variant: keep the title on one row even when it's long.
   Font size scales with viewport so the line fits without wrapping. */
.traction-v2-headline--single {
  max-width: none;
  white-space: nowrap;
  font-size: clamp(16px, 1.55cqw, 24px);
  letter-spacing: -0.015em;
}

/* Two-column split below the headline. Left = proof + signed momentum,
   right = growth curve + the pipeline visualized as logos. */
.v2-split {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: clamp(20px, 2.4cqw, 36px);
  margin-top: clamp(18px, 2.2cqh, 28px);
  flex: 1;
  min-height: 0;
}
.v2-left,
.v2-right {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2cqh, 26px);
  min-height: 0;
  min-width: 0;
}

/* Hero: the W Hollywood proof point. Bordered card with a faint accent
   bias so it reads as the slide's anchor before the eye drops to contracts. */
.v2-hero {
  border: 1px solid var(--border);
  border-radius: 14px;
  background:
    linear-gradient(180deg, rgba(94, 106, 210, 0.06) 0%, rgba(94, 106, 210, 0) 60%),
    var(--bg-elev);
  padding: clamp(18px, 2cqw, 28px) clamp(20px, 2.2cqw, 32px);
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.4cqh, 20px);
}
.v2-hero-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.v2-hero-tag { color: var(--accent-bright); }
.v2-hero-tag-sep { color: var(--text-dim); }
.v2-hero-prop { color: var(--text-soft); }
.v2-hero-claim {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(24px, 2.6cqw, 36px);
  letter-spacing: -0.02em;
  line-height: 1.14;
  color: var(--text);
}
.v2-hero-claim .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}
.v2-hero-stats {
  display: flex;
  gap: clamp(28px, 3.6cqw, 56px);
  align-items: baseline;
  margin-top: clamp(2px, 0.4cqh, 8px);
}
.v2-hero-stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.v2-hero-num {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(40px, 4.4cqw, 64px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: #FFFFFF;
}
.v2-hero-lbl {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* Case-study variant: hero now lives alone in the left column, so it has
   room for a short narrative body between the claim and the stat row.
   Stats pinned to the bottom so the card breathes evenly with the right
   column even when the chart + logos stack is taller than the prose. */
.v2-hero--case {
  flex: 1;
}
.v2-hero--case .v2-hero-stats {
  padding-top: clamp(4px, 0.6cqh, 10px);
  padding-bottom: clamp(4px, 0.6cqh, 10px);
}
.v2-hero-logo {
  display: block;
  align-self: flex-start;
  height: clamp(28px, 3.4cqh, 44px);
  width: auto;
  filter: brightness(0) invert(1);
  opacity: 0.95;
  margin-bottom: clamp(4px, 0.6cqh, 10px);
}

/* Hero banner photo: a cropped strip of the property between the W Hotels
   logo and the rest of the case-study text. Anchors the card visually
   without crowding out the proof-point copy below. */
.v2-hero-banner {
  margin: 0;
  border-radius: 10px;
  overflow: hidden;
  height: clamp(180px, 30cqh, 280px);
  background: var(--bg-elev);
}
.v2-hero-banner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
.v2-hero-body {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(14px, 1.05cqw, 16px);
  line-height: 1.55;
  color: var(--text-soft);
  max-width: 44ch;
  margin: 0;
}

.v2-col {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.4cqh, 18px);
  min-height: 0;
  min-width: 0;
}
.v2-col--chart,
.v2-col--logos { flex: 1; }
.v2-col-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: clamp(8px, 1cqh, 14px);
  border-bottom: 1px solid var(--border);
}
.v2-col-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(16px, 1.4cqw, 20px);
  letter-spacing: -0.01em;
  color: var(--text);
}
.v2-col-sub {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

/* Signed contracts list — month / property / ARR. */
.v2-contracts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1cqh, 12px);
}
.v2-contract {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  align-items: baseline;
  gap: clamp(12px, 1.2cqw, 18px);
  padding: clamp(10px, 1.2cqh, 14px) clamp(14px, 1.4cqw, 20px);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.v2-contract-mo {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.v2-contract-name {
  font-family: var(--font-display);
  font-size: clamp(14px, 1.2cqw, 17px);
  color: var(--text);
}
.v2-contract-detail {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  margin-left: 4px;
}
.v2-contract-arr {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(18px, 1.6cqw, 22px);
  letter-spacing: -0.02em;
  color: var(--accent-bright);
}

/* Q1 growth chart — three bars (Jan, Feb, Mar) showing ARR ramp across
   the months tied to our signed contracts. Sits above the logo wall. */
.v2-chart {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: stretch;
  padding: clamp(8px, 1cqh, 14px) clamp(8px, 1cqw, 14px) 0;
}
.v2-chart svg {
  width: 100%;
  height: 100%;
}
.v2-q1-month {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  fill: var(--text-soft);
}
.v2-q1-props {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  fill: var(--text-dim);
}

/* Section labels — small accent-tinted kickers at the top of each of the
   three sections (proof, growth, pipeline). Consistent voice across the
   slide so the eye reads three discrete chapters. */
.v2-section-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-bottom: clamp(6px, 0.8cqh, 12px);
}

/* Pipeline headline above the marquee — single declarative line replacing
   the old column-header / sub-header pair. */
.v2-pipeline-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(15px, 1.25cqw, 19px);
  letter-spacing: -0.01em;
  color: var(--text);
}
.v2-pipeline-num {
  color: var(--accent-bright);
  font-weight: 500;
}
.v2-pipeline-via {
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 0.78em;
  letter-spacing: 0.04em;
  margin-left: 4px;
}
.v2-pipeline-fine {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

/* Scrolling logo marquee — set in motion to make the wall of brand names
   feel alive, with edges fading to the slide background. The track holds
   the list duplicated so translateX(-50%) loops seamlessly. */
.v2-marquee {
  flex: 1;
  min-height: 0;
  min-width: 0;
  width: 100%;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(14px, 1.8cqh, 22px);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 8%, #000 92%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 8%, #000 92%, transparent 100%);
}
.v2-marquee-track {
  display: flex;
  align-items: center;
  gap: clamp(40px, 4.4cqw, 68px);
  width: max-content;
  flex-shrink: 0;
  animation: v2-marquee-scroll 30s linear infinite;
  will-change: transform;
}
/* Bottom track scrolls slower and starts mid-cycle so the rows feel like
   independent layers rather than marching in lockstep. */
.v2-marquee-track--offset {
  animation-duration: 50s;
  animation-delay: -25s;
}
.v2-marquee-track img {
  display: block;
  height: clamp(22px, 2.6cqh, 30px);
  width: auto;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: 0.82;
}

/* Single-row variant: full-bleed slide gives us the room to lay every brand
   out on one line. Tuned smaller and slower than the two-row brick layout.
   We use margin-right (not flex `gap`) so each logo carries its own trailing
   space — that way the doubled track has identical-width halves and
   translateX(-50%) lines up exactly, no half-gap drift between cycles. */
.v2-marquee--single { flex-direction: row; gap: 0; }
.v2-marquee--single .v2-marquee-track {
  gap: 0;
  /* Track holds 4× the 11-logo set (44 imgs); -50% translates by 2× the set.
     Doubling the duration vs the 2× track keeps the visual scroll pace. */
  animation-duration: 140s;
}
.v2-marquee--single .v2-marquee-track img {
  height: clamp(24px, 3cqh, 38px);
  margin-right: clamp(52px, 5.4cqw, 88px);
}
@keyframes v2-marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .v2-marquee-track { animation: none; }
}

/* -------- Slide 05: Unique Insight — day-log + Tempo capability badges -- */
.slide-product {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 3cqw, 44px);
  justify-content: flex-start;
}

.day-log {
  width: min(1200px, 100%);
  align-self: center;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.day-log-meta {
  display: grid;
  grid-template-columns: 80px minmax(0, 1fr) 24px minmax(0, 1fr);
  gap: clamp(16px, 1.6cqw, 28px);
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: var(--t-13);
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-soft);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.day-log-meta-label { grid-column: 2 / 3; }
.day-log-meta-how  { grid-column: 4 / 5; }
.day-log-meta-tempo { color: var(--text); }
.day-log-meta-range { color: var(--text-dim); }
.day-log-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.day-log-row {
  display: grid;
  grid-template-columns: 80px minmax(0, 1fr) 24px minmax(0, 1fr);
  gap: clamp(16px, 1.6cqw, 28px);
  align-items: baseline;
  padding: clamp(16px, 1.6cqw, 22px) 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--t-17);
  line-height: 1.35;
}
.day-log-row .t {
  font-family: var(--font-mono);
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  font-size: var(--t-13);
}
.day-log-row .m {
  color: var(--text);
  font-weight: 400;
}
.day-log-row .arrow {
  color: var(--text-soft);
  font-family: var(--font-mono);
  text-align: center;
}
.day-log-row .how {
  color: var(--text-soft);
  font-weight: 400;
}

/* Tempo capability badges — one per row, color-coded by capability. */
.day-log-tempo {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
  border: 1px solid;
  align-self: center;
}
.day-log-tempo.browser {
  background: rgba(94, 106, 210, 0.12);
  color: #C0C8EE;
  border-color: rgba(94, 106, 210, 0.30);
}
.day-log-tempo.orchestration {
  background: rgba(74, 222, 128, 0.10);
  color: #B5E8C5;
  border-color: rgba(74, 222, 128, 0.26);
}
.day-log-tempo.routing {
  background: rgba(245, 196, 85, 0.10);
  color: #F0DCA0;
  border-color: rgba(245, 196, 85, 0.26);
}
.day-log-tempo.awareness {
  background: rgba(196, 154, 246, 0.12);
  color: #DEC8F5;
  border-color: rgba(196, 154, 246, 0.28);
}

/* -------- Slide 06 + 07: Org Chart ------------------------------------- */
/* Title row spans both columns (matches slide 8's title-on-top pattern);
   row 2 is the 2-col grid: copy on the left, org chart on the right. */
.slide-org {
  display: grid;
  grid-template-columns: 0.7fr 1.3fr;
  grid-template-rows: auto 1fr;
  column-gap: clamp(40px, 5cqw, 80px);
  row-gap: clamp(20px, 2.5cqw, 32px);
  align-items: center;
}
.slide-org > .slide-head { grid-column: 1 / -1; align-self: end; }
/* When the side copy is absent (slides 6 + 7), pin the title to the top and
   vertically center the chart within the remaining space. The flex variant
   overrides align-items so the title stretches to full width (otherwise the
   parent's grid `align-items: center` would horizontally centre each item). */
.slide-org:not(:has(.org-copy)) {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  /* Inherits row-gap from .slide-org, which adds asymmetric space above
     the auto-margined chart. Zero it out so the auto margins truly centre. */
  row-gap: 0;
}
.slide-org:not(:has(.org-copy)) > .slide-head {
  margin-bottom: 0;
  align-self: stretch;
}
.slide-org:not(:has(.org-copy)) > .org-chart {
  max-width: min(880px, 100%);
  align-self: center;
  margin: auto 0;
}
/* Long-form headline that needs to wrap (e.g., slide 7). Overrides the
   unified `white-space: nowrap` rule via higher specificity. */
.slide-head .headline.headline-wrap {
  white-space: normal;
  max-width: 64ch;
  line-height: 1.12;
  text-wrap: balance;
}

/* Slide-head headlines get a generic editorial-italic em accent. */
.slide-head .headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.01em;
}
.org-copy { display: flex; flex-direction: column; gap: 20px; max-width: 38ch; }
.org-copy .stats {
  display: grid; gap: 14px;
  margin-top: 16px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}
.org-copy .stat-row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--font-mono);
  font-size: var(--t-12);
  letter-spacing: 0.05em;
  color: var(--text-dim);
}
.org-copy .stat-row .v { color: var(--text); }

.org-chart { width: 100%; height: auto; overflow: visible; }
.org-node rect {
  fill: var(--bg-elev);
  stroke: var(--border-strong);
  stroke-width: 1;
  rx: 22; ry: 22;
}
.org-node text {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  fill: var(--text-soft);
  letter-spacing: 0.02em;
}
.org-node.is-target rect {
  fill: var(--accent);
  stroke: var(--accent-soft);
  filter: none;
  animation: pulse-glow 2.4s ease-in-out infinite;
}
.org-node.is-target text { fill: #FFFFFF; }
@keyframes pulse-glow {
  0%, 100% { filter: none; }
  50%      { filter: drop-shadow(0 0 22px rgba(94, 106, 210, 0.6)); }
}
/* Tempo bar — same blue palette as the supervisor tier. Static drop-
   shadow (no animation) — the travelling pulse strokes already provide
   "alive" movement, and animating filter forced a full repaint per frame. */
.org-node.is-tempo rect {
  stroke: rgba(255, 255, 255, 0.18);
  stroke-width: 1;
  filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.7));
}
.org-link { stroke: var(--border-strong); stroke-width: 1; fill: none; }

/* Pulse overlay (slide 7) — subtle white pulse showing information flow.
   Velocity ~250 units/sec across all paths so dash size + speed stay consistent. */
.pulse-stroke {
  fill: none;
  stroke: #FFFFFF;
  stroke-width: 4;
  stroke-dasharray: 10 1500;
  stroke-dashoffset: 60;
  /* Two-layer drop-shadow only — dropped the upstream blur and one drop-
     shadow stop. 5 simultaneous paths × 4 filter passes was the slide's
     biggest perf hot loop; this halves the GPU work while keeping the
     tight-inner + ambient-corona character. */
  filter:
    drop-shadow(0 0 5px rgba(255, 255, 255, 1))
    drop-shadow(0 0 18px rgba(255, 255, 255, 0.55));
  pointer-events: none;
  opacity: 0;
}
.pulse-s1   { animation: pulse-s1 5s linear infinite; }
.pulse-s3   { animation: pulse-s3 5s linear infinite; }
.pulse-s4-1 { animation: pulse-s4-1 5s linear infinite; }
.pulse-s4-2 { animation: pulse-s4-2 5s linear infinite; }
.pulse-s4-3 { animation: pulse-s4-3 5s linear infinite; }

/* All pulse keyframes share this shape:
   - 0%: dash positioned at path start (offset = 10), opacity 0
   - fade-in: opacity 0 → 1 with no offset motion
   - travel: offset slides to -(path+10), revealing the dash crossing the path
   - fade-out: opacity 1 → 0 with the dash held at the end position (no glitch)
   - return: between fade-out and 100%, offset slides back to 10 invisibly
   - 100%: matches 0% (offset 10, opacity 0) — clean cycle wrap. */

/* Stage 1: Director → Tempo top (path 84) */
@keyframes pulse-s1 {
  0%        { stroke-dashoffset: 10;  opacity: 0; }
  0.5%      { stroke-dashoffset: 10;  opacity: 1; }
  7.7%      { stroke-dashoffset: -94; opacity: 1; }
  8.2%      { stroke-dashoffset: -94; opacity: 0; }
  100%      { stroke-dashoffset: 10;  opacity: 0; }
}
/* Stage 3: Pill pulses, two halves meeting at center bottom (path 790) */
@keyframes pulse-s3 {
  0%, 7.7%  { stroke-dashoffset: 10;   opacity: 0; }
  8.2%      { stroke-dashoffset: 10;   opacity: 1; }
  70.6%     { stroke-dashoffset: -800; opacity: 1; }
  71.1%     { stroke-dashoffset: -800; opacity: 0; }
  100%      { stroke-dashoffset: 10;   opacity: 0; }
}
/* Cascade tier 1: outermost staff (x=77.5 / 742.5) — fires when pill crosses (~43.3%) */
@keyframes pulse-s4-1 {
  0%, 42.8% { stroke-dashoffset: 10;  opacity: 0; }
  43.3%     { stroke-dashoffset: 10;  opacity: 1; }
  50%       { stroke-dashoffset: -94; opacity: 1; }
  50.5%     { stroke-dashoffset: -94; opacity: 0; }
  100%      { stroke-dashoffset: 10;  opacity: 0; }
}
/* Cascade tier 2: middle staff (x=210.5 / 609.5) — fires at ~53.7% */
@keyframes pulse-s4-2 {
  0%, 53.2% { stroke-dashoffset: 10;  opacity: 0; }
  53.7%     { stroke-dashoffset: 10;  opacity: 1; }
  60.4%     { stroke-dashoffset: -94; opacity: 1; }
  60.9%     { stroke-dashoffset: -94; opacity: 0; }
  100%      { stroke-dashoffset: 10;  opacity: 0; }
}
/* Cascade tier 3: inner staff (x=343.5 / 476.5) — fires at ~64% */
@keyframes pulse-s4-3 {
  0%, 63.5% { stroke-dashoffset: 10;  opacity: 0; }
  64%       { stroke-dashoffset: 10;  opacity: 1; }
  70.7%     { stroke-dashoffset: -94; opacity: 1; }
  71.2%     { stroke-dashoffset: -94; opacity: 0; }
  100%      { stroke-dashoffset: 10;  opacity: 0; }
}

/* -------- Slide 07: Converge-flip-and-reveal sequence -----------------------
   The slide opens in slide-6 layout and walks through a "flip the card to
   reveal Tempo" reveal. Static elements (Director, frontline, lines, pulses)
   live in the SVG. The five deprecated cards and the Tempo bar are rendered
   as HTML divs in an absolutely-positioned overlay — Chromium's SVG renderer
   doesn't reliably propagate CSS 3D perspective into SVG inner elements, but
   it does for HTML descendants. The HTML cards rotate with real perspective
   foreshortening (closer edge larger, far edge smaller).

     stage 0 (0–300ms):     reveal continues + brief recognition (slide-6
                            layout)
     stage 1 (300–900ms):   old connecting lines fade out
     stage 2 (800–1700ms):  four outer cards glide in a clockwise wave — left
                            supervisor → top-left AGM → top-right AGM → right
                            supervisor (100ms stagger, 600ms per card; each
                            card launches while the previous is mid-flight).
                            Centre supervisor anchors and fades text in place.
     stage 3 (1500–3500ms): synchronised 3D flip — deprecated stage rotates
                            -180° (poker-chip front), Tempo card rotates from
                            +180° to 0° (poker-chip back). Opacity steps at
                            the 50% edge-on moment so only one face is ever
                            rendered. 2000ms — snappy. Director slides down
                            in parallel (1500–2500ms, see below) so the top
                            of the chart re-paginates while the bar lands.
     stage 4 (3500–4500ms): AFTER the rotation lands — the new connecting
                            lines extend together: the trunk (Director→bar)
                            and all six legs (bar→each frontline node) appear
                            in unison once the bar is in place. Director is
                            already in position (shifted during stage 3) so
                            the trunk draws into a settled top node.
     stage 5 (4500ms+):     information-flow pulses begin (2.5s cycle)
*/


/* Industries tier (slide-org-7): horizontal pill row that sits visually
   "above" the SVG departments tier. Same pill geometry + color tokens as
   the SVG nodes so the eye reads it as a continuous hierarchy. The
   active pill (Hotels) carries the accent treatment matching the active
   department (Housekeeping) inside the chart. */
/* Wrapper that contains industries-tier + chart so they center as a
   single unit between the slide-head and the slide bottom. */
.slide-org-7 .org-tier-stack {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  /* Auto top + bottom margins center the wrapper vertically in the
     space between the slide-head's bottom and the slide's padding-
     bottom — i.e., from "below the title" to "bottom of slide". */
  margin: auto 0;
  /* The chart SVG viewBox has ~32 units of empty padding below the
     frontline rects, which pushes the visible content's centre ~17px
     above the wrapper's geometric centre. Translate down by that offset
     so visible content (industries top → frontline bottom) — not the
     wrapper bounds — centers between the title bottom and slide bottom. */
  transform: translateY(1.6cqh);
}
.slide-org-7 .industries-tier {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  margin: 0;
}
/* Connector SVG sits flush against the bottom of the pills (margin-top:0)
   and overlaps the chart's empty top viewBox region (negative margin-
   bottom) so its bottom edge lands exactly on the Housekeeping rect top.
   For the canonical 1920×1080 stage:
     • Hotels pill bottom Y ≈ 328
     • Housekeeping rect top Y ≈ 425
     • Required SVG visual height ≈ 97px
     • Chart's viewBox top empty space ≈ 21px (y=-90 to y=-70)
   So height=97px and margin-bottom=-21px lets the SVG end at Housekeeping. */
.slide-org-7 .industries-connector {
  width: 100%;
  height: clamp(80px, 9cqh, 100px);
  display: block;
  pointer-events: none;
  margin-top: 0;
  margin-bottom: clamp(-26px, -2cqh, -18px);
  overflow: visible;
}
.slide-org-7 .industries-connector path {
  stroke: var(--border-strong);
  stroke-width: 1;
  fill: none;
  stroke-linecap: round;
}
/* Industry pills span WIDER than the SVG org chart below — gives the
   "industries are bigger context" feel; the chart represents one of them
   in detail. Generous max-width plus space-between distributes the 6
   pills across the slide. */
.slide-org-7 .industries-list {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  max-width: clamp(820px, 66cqw, 1200px);
  margin: 0 auto;
  flex-wrap: nowrap;
}
.slide-org-7 .industry-node {
  background: var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: 9999px;
  padding: 7px 16px;
  font-family: var(--font-display);
  font-size: clamp(11px, 0.9cqw, 13px);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-soft);
  opacity: 0.38;
  white-space: nowrap;
}
.slide-org-7 .industry-node.is-active {
  opacity: 1;
  background: var(--accent);
  border-color: var(--accent-soft);
  color: #FFFFFF;
  /* Same pulse-glow rhythm as the SVG's active department, so the eye
     understands this is the "we're here" highlight. */
  animation: pulse-glow 2.4s ease-in-out infinite;
}

/* Outer 3D wrapper: owns perspective and aspect-ratio so the HTML cards align
   with the SVG viewBox coordinates regardless of viewport size. Aspect
   matches the SVG's 820×470 viewBox (which spans y=-90..380 to include the
   departments tier shared with slide 6). */
.slide-org-7 .org-chart-3d {
  position: relative;
  max-width: min(880px, 100%);
  align-self: center;
  /* Inside .org-tier-stack the wrapper handles vertical centering, so
     the chart no longer needs auto vertical margins. The chart sits
     immediately below the industries-tier (the connector SVG bridges
     the gap with a negative bottom margin). */
  margin: 0 auto;
  width: 100%;
  aspect-ratio: 820 / 470;
  perspective: 500px;
  perspective-origin: 50% 50%;
}
.slide-org-7 .org-chart-3d > .org-chart-7 {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
  /* Lifted above the HTML overlay so the pulse paths along the bottom
     edge of the Tempo bar (y=224) aren't hidden by the card's fill. */
  z-index: 2;
}

/* HTML overlay shares the SVG coordinate space (percentages of stage
   width/height map to viewBox units) and sits BELOW the SVG so the
   pulse traces around the Tempo bar remain visible end-to-end. */
.slide-org-7 .org-chart-cards {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform-style: preserve-3d;
  z-index: 1;
}

/* The dep-stage wraps all 5 cards and rotates as a unit, around the bar
   centre. (50%, 65.53%) corresponds to viewBox (410, 218) — bar centre —
   in the 820×470 (y=-90..380) viewBox. */
.slide-org-7 .dep-stage {
  position: absolute;
  inset: 0;
  transform-origin: 50% 65.53%;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform, opacity;
}

/* Each deprecated card. Sized as % of stage so it tracks the SVG viewBox. */
.slide-org-7 .dep-card {
  position: absolute;
  width: 15.8537%;       /* 130 / 820 */
  height: 7.6596%;       /* 36 / 470  */
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  border: 1px solid var(--accent-soft);
  border-radius: 9999px;
  color: #FFFFFF;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
  /* Reuse the existing pulse-glow keyframes from slide 6 */
  animation: pulse-glow 2.4s ease-in-out infinite;
  will-change: transform, opacity;
}
.slide-org-7 .dep-card > span {
  display: block;
  transform: translateZ(0); /* keep text crisp inside a 3D context */
}

/* Per-card slide-6 starting positions (left/top in % of stage). The
   `--converge-x/y` vars define the translation that brings each card to the
   bar centre, expressed in percentages of the card's OWN size so they remain
   consistent regardless of how the chart is scaled. */
.slide-org-7 .dep-card.dep-ad-l  { left: 26.2195%; top: 42.5532%; --converge-x:  100%;    --converge-y: 250%; }
.slide-org-7 .dep-card.dep-ad-r  { left: 57.9268%; top: 42.5532%; --converge-x: -100%;    --converge-y: 250%; }
.slide-org-7 .dep-card.dep-sup-l { left: 11.5854%; top: 61.7021%; --converge-x:  192.31%; --converge-y: 0;    }
.slide-org-7 .dep-card.dep-sup-c { left: 42.0732%; top: 61.7021%; --converge-x:  0;       --converge-y: 0;    }
.slide-org-7 .dep-card.dep-sup-r { left: 72.5610%; top: 61.7021%; --converge-x: -192.31%; --converge-y: 0;    }

/* Tempo bar — back face of the flip. Geometrically full bar width, but starts
   rendered at scaleX(0.169) ≈ dep card width (130/770) and scales up to 1
   simultaneously with the rotation. Result: continuous growth from blue-card
   size into full Tempo bar, no size jump at the edge-on handoff.
   Transform order: rotateY THEN scaleX so scale applies in element-local
   space — clean foreshortening, no shear. */
.slide-org-7 .tempo-card {
  position: absolute;
  left: 3.0488%;         /* 25 / 820 */
  top: 61.7021%;         /* (200 - (-90)) / 470 */
  width: 93.9024%;       /* 770 / 820 */
  height: 7.6596%;       /* 36 / 470  */
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: 9999px;
  transform-origin: 50% 50%;
  transform: rotateY(180deg) scaleX(0.169);
  opacity: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform, opacity;
}
.slide-org-7 .tempo-card-logo {
  height: 50%;
  width: auto;
  opacity: 0;
}

/* Once the bar lands face-on, kick on the always-pulsing glow that signals
   the "magic Tempo layer" — same cadence as the original SVG version. */
@keyframes tempo-card-glow {
  0%, 100% { box-shadow: 0 0 6px rgba(255, 255, 255, 0.25); }
  50%      { box-shadow: 0 0 16px rgba(255, 255, 255, 0.7); }
}

/* Director begins at slide-6 position; shifts down 60px in stage 4. */
.slide-org-7 .org-node-director { transform: translateY(0); }

/* New connecting lines start fully dashed-off (invisible) and zero opacity. */
.slide-org-7 .org-link-new {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  opacity: 0;
}

/* Pulse overlay starts hidden — re-enabled with delay below. */
.slide-org-7 .pulse-stroke { animation: none; }

/* Active-state choreography. */
/* All 12 old links — Director→AGM (2), AGM→Sup (4), Sup→Frontline (6) — fade
   out together so the chart resets cleanly before the new wiring draws in. */
.slide.is-active.animate.slide-org-7 .org-link-old {
  animation: link-fade-out 600ms cubic-bezier(0.33, 1, 0.68, 1) 300ms forwards;
}
/* Each deprecated card glides to the bar centre via translate, in clockwise
   order around the dial: left supervisor → top-left AGM → top-right AGM →
   right supervisor (100ms stagger). The wave overlaps so each card launches
   while the previous is still in flight. The centre supervisor sits on the
   bar centre already, so its translate is a no-op; it just fades text
   alongside the first mover. The 3D flip rotation is applied to the parent
   .dep-stage so all 5 cards rotate as a unit around the same axis. */
.slide.is-active.animate.slide-org-7 .dep-card.dep-sup-l { animation: card-converge 900ms cubic-bezier(0.16, 1, 0.3, 1) 800ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-ad-l  { animation: card-converge 900ms cubic-bezier(0.16, 1, 0.3, 1) 900ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-ad-r  { animation: card-converge 900ms cubic-bezier(0.16, 1, 0.3, 1) 1000ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-sup-r { animation: card-converge 900ms cubic-bezier(0.16, 1, 0.3, 1) 1100ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-sup-c { animation: card-converge 900ms cubic-bezier(0.16, 1, 0.3, 1) 800ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-sup-l > span { animation: text-fade-out 400ms ease-out 800ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-ad-l  > span { animation: text-fade-out 400ms ease-out 900ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-ad-r  > span { animation: text-fade-out 400ms ease-out 1000ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-sup-r > span { animation: text-fade-out 400ms ease-out 1100ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-card.dep-sup-c > span { animation: text-fade-out 400ms ease-out 800ms forwards; }
.slide.is-active.animate.slide-org-7 .dep-stage {
  animation:
    flip-out-rotate  2000ms cubic-bezier(0.65, 0, 0.35, 1) 1500ms forwards,
    flip-out-opacity 2000ms step-end                       1500ms forwards;
}
/* Tempo card: rotates from back to face-on with real 3D foreshortening, snaps
   visible at the edge-on midpoint so it cleanly takes over from the dep face.
   Once the bar lands face-on, the always-pulsing glow kicks in to signal the
   "magic Tempo layer" — synced to the 2.5s travelling-pulse cycle. */
.slide.is-active.animate.slide-org-7 .tempo-card {
  animation:
    tempo-reveal-rotate  2000ms cubic-bezier(0.65, 0, 0.35, 1) 1500ms forwards,
    tempo-reveal-opacity 2000ms step-end                       1500ms forwards;
}
/* Glow is now a pseudo-element with a STATIC peak box-shadow; we animate
   only its opacity (compositor-only) instead of animating box-shadow on
   the card itself (paint-trigger). Same visible cadence, ~no per-frame
   paint cost. */
.slide-org-7 .tempo-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: 0 0 16px rgba(255, 255, 255, 0.7);
  opacity: 0;
}
.slide.is-active.animate.slide-org-7 .tempo-card::after {
  animation: tempo-card-glow-opacity 2.5s ease-in-out 3500ms infinite;
}
@keyframes tempo-card-glow-opacity {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 1; }
}
.slide.is-active.animate.slide-org-7 .tempo-card-logo {
  animation: logo-fade-in 600ms ease-out 2900ms forwards;
}
/* Director re-positions IN PARALLEL with the rotation, paced to match the
   flip's full 2000ms duration AND its ease curve so the top node and the bar
   arrive at their resting state at the same perceived moment. The flip uses
   ease-in-out (slow ends, fast middle); a strong ease-out on the director
   would make it arrive too early and just sit there. */
.slide.is-active.animate.slide-org-7 .org-node-director {
  animation: director-shift 2000ms cubic-bezier(0.65, 0, 0.35, 1) 1500ms forwards;
}
/* New connecting lines extend AFTER the rotation lands — director is already
   in place from stage 3, bar is face-on, then all 7 lines (trunk Director→bar
   plus 6 legs bar→each frontline node) reach out together in unison. */
.slide.is-active.animate.slide-org-7 .org-link-new {
  animation: link-draw 1000ms cubic-bezier(0.33, 1, 0.68, 1) 3500ms forwards;
}
/* Travelling info-flow pulses — point of light extending along each line.
   2.5s cycle (2x faster than the original 5s) so the data-flow story reads
   more energetically. All five pulse keyframes share the same total cycle so
   the cascade timing percentages stay valid. */
.slide.is-active.animate.slide-org-7 .pulse-s1   { animation: pulse-s1   2.5s linear 4500ms infinite; }
.slide.is-active.animate.slide-org-7 .pulse-s3   { animation: pulse-s3   2.5s linear 4500ms infinite; }
.slide.is-active.animate.slide-org-7 .pulse-s4-1 { animation: pulse-s4-1 2.5s linear 4500ms infinite; }
.slide.is-active.animate.slide-org-7 .pulse-s4-2 { animation: pulse-s4-2 2.5s linear 4500ms infinite; }
.slide.is-active.animate.slide-org-7 .pulse-s4-3 { animation: pulse-s4-3 2.5s linear 4500ms infinite; }

@keyframes link-fade-out {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}
/* Glide each deprecated card to the bar centre. Translation is in % of the
   card's own size so it scales with the chart. */
@keyframes card-converge {
  0%   { transform: translate(0, 0); }
  100% { transform: translate(var(--converge-x, 0), var(--converge-y, 0)); }
}
/* Per-segment easing tuned so the rotation flies THROUGH edge-on without a
   perceived pause:
   - 0–50% (visible front face): ease-in — slow start, accelerating into the
     edge-on handoff so dep rotates quickly into invisibility
   - 50–100% (back face, invisible): doesn't matter visually
   This pairs with tempo-reveal-rotate's ease-out on its second segment, which
   accelerates Tempo OUT of edge-on. Both halves move fast through 50%. */
@keyframes flip-out-rotate {
  0%   { transform: rotateY(0deg);    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); }
  50%  { transform: rotateY(-90deg);  animation-timing-function: linear; }
  100% { transform: rotateY(-180deg); }
}
@keyframes flip-out-opacity {
  0%   { opacity: 1; }
  50%  { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes text-fade-out {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}
/* Three-stop keyframe so scale only grows during the SECOND half of the
   rotation. From 0–50% the back face rotates in but stays at blue-card
   size (scaleX 0.169) so it lands at the same size the blue pill vanished
   at. From 50–100% it rotates the rest of the way AND scales up to full bar
   simultaneously. Per-keyframe animation-timing-function: the 50% keyframe
   uses ease-out-quint for the second segment so rotation accelerates past
   edge-on (no perceived pause) and decelerates into face-on. */
@keyframes tempo-reveal-rotate {
  /* The bar also drifts up by 12px during the rotation so that, after the
     director shifts down 36px, the three vertical gaps (departments→director,
     director→Tempo, Tempo→frontline) all land equal at ~96 SVG units. */
  0%   { transform: translateY(0)     rotateY(180deg) scaleX(0.169); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  50%  { transform: translateY(-6px)  rotateY(90deg)  scaleX(0.169); animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); }
  100% { transform: translateY(-12px) rotateY(0deg)   scaleX(1);     }
}
@keyframes tempo-reveal-opacity {
  0%   { opacity: 0; }
  50%  { opacity: 1; }
  100% { opacity: 1; }
}
@keyframes logo-fade-in {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes director-shift {
  /* 36px (was 60px) — paired with the Tempo bar's -12px drift so all three
     vertical gaps in the rewired chart end up equal. */
  0%   { transform: translateY(0); }
  100% { transform: translateY(36px); }
}
@keyframes link-draw {
  0%   { stroke-dashoffset: 100; opacity: 1; }
  100% { stroke-dashoffset: 0;   opacity: 1; }
}

.org-arrow {
  stroke: var(--text-muted);
  stroke-width: 1.25;
  fill: none;
  stroke-linecap: round;
}

/* -------- Slide 08: Product Flow — Linear command-plate register ------ */
.slide-flow {
  align-items: stretch;
  justify-content: flex-start;
}
.slide-flow .kicker { align-self: flex-start; }
.flow-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-40);
  letter-spacing: -0.025em;
  line-height: 1.08;
  max-width: 28ch;
  color: var(--text);
  margin-top: 8px;
}
/* This slide's title runs longer than the others — allow wrapping. */
.slide-flow .flow-headline {
  white-space: normal;
  max-width: 64ch;
  line-height: 1.1;
}
.slide-flow .flow-headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.005em;
}
.flow-stage {
  position: relative;
  flex: 1;
  width: min(1100px, 100%);
  margin: clamp(12px, 1.6cqw, 20px) auto 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  /* No gap here — rows use margin-top instead so hidden rows collapse cleanly. */
  /* End the stage's box above the absolutely-positioned running-totals
     meter — was padding-bottom, but with overflow-y: auto that padding
     stays inside the scroll viewport so older rows scrolled into view
     would visually overlap the meter. margin-bottom shrinks the box
     itself so the meter sits in clean space below it. */
  margin-bottom: clamp(120px, 22cqh, 220px);
  padding-bottom: clamp(8px, 1cqh, 16px);
  /* Older rows are scrollable: when the stack exceeds the stage height,
     the user can scroll up to re-read rows that have been pushed above
     the viewport. The ::before spacer pins rows to the bottom when they
     fit (replacing `justify-content: flex-end`, which has an old Webkit
     bug where overflow content above is unreachable). */
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  /* Hide the scrollbar but keep the element scrollable. */
  scrollbar-width: none;
  /* Top fade — rows scrolled past the visible area dissolve into the
     page bg instead of butting up against the headline with a hard line. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,0.2) 4%, black 16%, black 100%);
          mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,0.2) 4%, black 16%, black 100%);
}
.flow-stage::-webkit-scrollbar { display: none; }
.flow-stage::before {
  content: '';
  flex: 1 1 auto;
  min-height: 0;
}
.flow-row + .flow-row {
  margin-top: clamp(10px, 1.2cqw, 18px);
}

/* Row: full cmd-plate (left) → branch SVG → rich task stack (right) */
.flow-row {
  display: grid;
  grid-template-columns: 1fr clamp(72px, 8cqw, 110px) 1fr;
  align-items: center;
  gap: clamp(10px, 1.2cqw, 18px);
  /* Keep their natural size — never let flexbox squeeze the modals when
     space runs out. Older rows just overflow upward into the mask fade. */
  flex-shrink: 0;
}

/* Override the original cmd-plate centered/max-width when used inside flow-row.
   Tighter padding so 4 plates can fit vertically. */
.flow-row .cmd-plate {
  max-width: none;
  align-self: center;
  width: 100%;
  padding: 10px 10px 8px 12px;
}
.flow-row .cmd-row {
  font-size: var(--t-13);
  padding: 0 4px 8px;
  line-height: 1.4;
}
.flow-row .cmd-actions { padding-top: 6px; }
.flow-row .cmd-icon { width: 22px; height: 22px; }
.flow-row .cmd-icon svg { width: 12px; height: 12px; }
.flow-row .cmd-send { padding: 0 3px 0 7px; height: 22px; }
.flow-row .cmd-send svg { width: 12px; height: 12px; }
.flow-row .cmd-send-chevron svg { width: 10px; height: 10px; }

/* Branch SVG fills the middle column, stretches to row height. */
.flow-branch {
  width: 100%;
  height: 100%;
  align-self: stretch;
  min-height: 80px;
}
.flow-branch path {
  fill: none;
  stroke: rgba(244, 245, 248, 0.20);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Task stack — rich cmd-task cards from the original committed pass,
   stacked vertically with tightened padding so 2-3 fit per row. */
.flow-tasks {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.flow-tasks .cmd-task {
  padding: 7px 12px 8px;
  gap: 3px;
}
.flow-tasks .cmd-task-header {
  padding-bottom: 0;
  border-bottom: 0;
}
.flow-tasks .cmd-task-msg {
  font-size: var(--t-13);
  line-height: 1.32;
}
.flow-tasks .cmd-task-meta {
  font-size: 9px;
}

/* -----------------------------------------------------------------------
   Sequence animation — rows reveal one at a time as the user clicks send.
   States:  hidden → awaiting (plate fades in, send pulses) →
            dispatching (branch draws, tasks fade in) → complete (static)
   ---------------------------------------------------------------------- */
/* Rows stay in the flex layout at all states — hidden ones collapse their
   height, margin, and opacity so the next row reveals with a smooth slide-up
   rather than a layout jump. */
.flow-row {
  transition:
    max-height 480ms cubic-bezier(0.4, 0, 0.2, 1),
    margin-top 480ms cubic-bezier(0.4, 0, 0.2, 1),
    opacity 600ms ease-out;
  overflow: hidden;
}
.flow-row[data-state="hidden"] {
  max-height: 0;
  opacity: 0;
  pointer-events: none;
}
.flow-row[data-state="hidden"] + .flow-row,
.flow-row + .flow-row[data-state="hidden"] {
  margin-top: 0;
}
.flow-row[data-state="awaiting"],
.flow-row[data-state="dispatching"],
.flow-row[data-state="complete"] {
  max-height: 360px;
}
/* Prior rows recede when a newer row takes over: opacity drops so the
   eye stays on the active row but the history is still legible. JS
   adds `.is-dimmed` to rows[0..i-1] the moment the user hits send on
   row i. */
.flow-row.is-dimmed {
  opacity: 0.32;
  transition: opacity 600ms ease-out;
}
.flow-row.is-dimmed .cmd-plate,
.flow-row.is-dimmed .flow-tasks { filter: saturate(0.6); }

/* Awaiting: plate visible, send button pulsing. Branch + tasks not yet shown. */
.flow-row[data-state="awaiting"] .cmd-plate {
  opacity: 0;
  animation: flow-plate-in 480ms ease-out forwards;
}
.flow-row[data-state="awaiting"] .flow-branch,
.flow-row[data-state="awaiting"] .flow-tasks {
  opacity: 0;
  pointer-events: none;
}
.flow-row[data-state="awaiting"] .cmd-send {
  position: relative;
  animation: flow-send-pulse 1.5s ease-in-out infinite;
}

/* Dispatching: pulse off, branch path draws in, tasks stagger-fade in. */
.flow-row[data-state="dispatching"] .cmd-plate { opacity: 1; }
.flow-row[data-state="dispatching"] .cmd-send {
  animation: none;
  box-shadow: none;
}
.flow-row[data-state="dispatching"] .flow-branch {
  opacity: 1;
  transition: opacity 200ms ease-out;
}
.flow-row[data-state="dispatching"] .flow-branch path {
  stroke-dasharray: 400;
  stroke-dashoffset: 400;
  animation: flow-branch-draw 600ms ease-out forwards;
}
.flow-row[data-state="dispatching"] .flow-tasks {
  opacity: 1;
}
.flow-row[data-state="dispatching"] .flow-tasks .cmd-task {
  opacity: 0;
  transform: translateX(-12px);
  animation: flow-task-in 380ms ease-out forwards;
}
.flow-row[data-state="dispatching"] .flow-tasks .cmd-task:nth-child(1) { animation-delay: 380ms; }
.flow-row[data-state="dispatching"] .flow-tasks .cmd-task:nth-child(2) { animation-delay: 560ms; }
.flow-row[data-state="dispatching"] .flow-tasks .cmd-task:nth-child(3) { animation-delay: 740ms; }

/* Complete: everything visible, no animation. */
.flow-row[data-state="complete"] .cmd-plate { opacity: 1; }
.flow-row[data-state="complete"] .cmd-send {
  animation: none;
  box-shadow: none;
}
.flow-row[data-state="complete"] .flow-branch { opacity: 1; }
.flow-row[data-state="complete"] .flow-branch path {
  stroke-dasharray: none;
  stroke-dashoffset: 0;
}
.flow-row[data-state="complete"] .flow-tasks { opacity: 1; }
.flow-row[data-state="complete"] .flow-tasks .cmd-task {
  opacity: 1;
  transform: none;
}

@keyframes flow-plate-in {
  to { opacity: 1; }
}
@keyframes flow-send-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(94, 106, 210, 0.55); }
  50%      { box-shadow: 0 0 0 14px rgba(94, 106, 210, 0); }
}
@keyframes flow-branch-draw {
  to { stroke-dashoffset: 0; }
}
@keyframes flow-task-in {
  to { opacity: 1; transform: translateX(0); }
}

/* Command plate — recreates Linear's chat-input UI */
.cmd-plate {
  align-self: center;
  width: 100%;
  max-width: 560px;
  background: var(--bg-elev);
  border: 1px solid rgba(244,245,248,0.10);
  border-radius: 14px;
  padding: 16px 16px 12px;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.04) inset,
    0 12px 40px rgba(0,0,0,0.28);
}
.cmd-row {
  display: flex; align-items: baseline; gap: 8px;
  padding: 4px 6px 14px;
  font-family: var(--font-display);
  font-size: var(--t-17);
  color: var(--text);
  flex-wrap: wrap;
  line-height: 1.45;
}
.cmd-mention {
  display: inline-flex;
  align-items: center;
  padding: 1px 7px 2px;
  background: rgba(94,106,210,0.18);
  color: #B0BBEC;
  border-radius: 4px;
  font-weight: 500;
  font-size: 0.94em;
  letter-spacing: -0.005em;
}
.cmd-text { color: var(--text-soft); }
.cmd-actions {
  display: flex; align-items: center; justify-content: space-between;
  padding-top: 10px;
  border-top: 1px solid rgba(244,245,248,0.06);
}
.cmd-icons { display: flex; align-items: center; gap: 2px; }
.cmd-icon {
  width: 30px; height: 30px;
  background: transparent; border: none;
  color: var(--text-muted);
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
  cursor: pointer;
  transition: background 160ms ease-out, color 160ms ease-out;
}
.cmd-icon:hover { background: rgba(255,255,255,0.04); color: var(--text); }
.cmd-icon svg { width: 14px; height: 14px; }
.cmd-send {
  display: inline-flex; align-items: center;
  background: var(--accent-soft);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 0 4px 0 10px; height: 28px;
  cursor: pointer;
  transition: background 160ms ease-out;
}
.cmd-send:hover { background: var(--accent-bright); }
.cmd-send svg { width: 14px; height: 14px; }
.cmd-send-chevron {
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: 4px;
  padding-left: 6px;
  border-left: 1px solid rgba(255,255,255,0.18);
  height: 16px;
}
.cmd-send-chevron svg { width: 12px; height: 12px; }

/* Hairline branch from plate to task cards */
.cmd-branch {
  width: 100%;
  height: clamp(36px, 6cqh, 56px);
  margin: 0 auto;
  display: block;
  align-self: center;
  max-width: 720px;
}
.cmd-branch path {
  fill: none;
  stroke: rgba(244,245,248,0.18);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Dispatched task cards — Linear "issue card" register */
.cmd-outputs {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
  width: 100%;
  max-width: 820px;
  margin: 0 auto;
}
.cmd-task {
  background: var(--bg-elev);
  border: 1px solid rgba(244,245,248,0.08);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 8px;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.04) inset,
    0 12px 40px rgba(0,0,0,0.28);
}
.cmd-task-header {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
}
.cmd-task-id { color: var(--text-muted); }
.cmd-task-status {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--text-muted);
  font-size: 10px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
}
.cmd-task-status .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-faint);
}
.cmd-task-status.status-active .dot  { background: #4ADE80; }
.cmd-task-status.status-pending .dot { background: var(--accent-soft); }
.cmd-task-status.status-done .dot    { background: var(--text-dim); }
.cmd-task-msg {
  font-family: var(--font-display);
  font-size: var(--t-13);
  color: var(--text);
  line-height: 1.45;
  margin: 0;
}
.cmd-task-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.04em;
}

/* -------- Slide 08: running-totals meter ------------------------------- */
/* Anchored to the bottom of the slide, sits BELOW .flow-stage's mask gradient
   (stage's padding-bottom keeps the bottom row floating ~36cqh up, leaving
   room here for the three-cell meter without overlap). */
.flow-meter {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(40px, 5.5cqh, 76px);
  margin-inline: auto;
  width: min(760px, 88%);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.6cqw, 22px);
  z-index: 2;
}
/* Flat stat: number on top, mono uppercase label below. No card, no
   backdrop blur — same logic as the slide-7 / slide-9 stat blocks. */
.meter-cell {
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  gap: 6px;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}
.meter-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.meter-value {
  font-family: var(--font-mono);
  font-size: clamp(22px, 2.2cqw, 28px);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  height: 1em;
  line-height: 1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Slot machine — each char is a fixed cell. Digit cells contain a stacked
   column of 0–9 (×3 cycles) that translates Y to land on the new digit. The
   3-cycle stack means a "spin" of one full turn never reveals the column's
   ends: rest at middle cycle, animate down through the third cycle, snap
   back to middle. */
.slot-cell {
  display: inline-block;
  height: 1em;
  line-height: 1;
  text-align: center;
  vertical-align: top;
  position: relative;
  overflow: hidden;
}
.slot-cell--digit { width: 1ch; }
.slot-col {
  display: block;
  will-change: transform;
  transform: translateY(calc(-1em * var(--offset, 0)));
}
.slot-d {
  display: block;
  height: 1em;
  line-height: 1;
}

/* Fine-print row spans all three meter columns; tiny mono caption that
   surfaces the wage / cadence / subscription assumptions behind the totals. */
.meter-fine {
  grid-column: 1 / -1;
  margin: 4px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.45;
  letter-spacing: 0.02em;
  color: var(--text-dim);
  text-align: center;
}

/* -------- Slide 09: US Market ------------------------------------------ */
.slide-us {
  display: flex; flex-direction: column;
  gap: 32px;
}
.us-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 30ch;
}
.us-headline .em { font-family: var(--font-mono); font-size: 0.85em; color: var(--accent-bright); padding: 0 0.04em; }
/* Stats laid out flat — number on top, mono uppercase label below.
   Same logic as slide 7 (proof): no container, the type carries it. */
.us-stats {
  display: flex;
  align-items: flex-start;
  gap: clamp(28px, 3.4cqw, 56px);
  margin-top: clamp(8px, 1cqh, 16px);
}
.us-stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.us-stat .v {
  font-family: var(--font-mono);
  font-size: var(--t-32);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.03em;
  line-height: 1;
}
.us-stat-ref {
  font-family: var(--font-mono);
  font-size: 0.42em;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--text-soft);
  margin-left: 3px;
  vertical-align: super;
  line-height: 1;
}
.us-stat .l {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-soft);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.us-map-wrap {
  flex: 1;
  position: relative;
  margin: 0 auto;
  width: 100%;
  max-width: 1100px;
  align-self: center;
  display: flex; align-items: center; justify-content: center;
}
.us-map { display: block; width: 100%; height: auto; max-height: 64cqh; margin: 0 auto; }
.us-map .state {
  fill: var(--bg-elev-2);
  stroke: var(--border-strong);
  stroke-width: 0.7;
}
.us-map .dot {
  fill: var(--accent-bright);
  filter: none;
  /* Per-dot stagger: --dot-delay is set by main.js based on each circle's
     cx so the wave reads left → right when the slide first activates. */
  opacity: 0;
}
.slide-us .us-map .dot {
  transform-box: fill-box;
  transform-origin: center;
}
.slide-us.is-active.animate .us-map .dot {
  animation: us-dot-fade 700ms cubic-bezier(0.22, 1, 0.36, 1) var(--dot-delay, 0s) forwards;
}
/* Two-phase entrance: appear small + dim, peak with a brief scale-up,
   settle. Only opacity + transform are animated — both compositor-only
   properties, no main-thread paint cost. The earlier version animated
   `filter: drop-shadow` for a per-dot glow; with 448 dots that meant 448
   GPU compositing layers active during the 2s sweep, tanking FPS to ~15.
   The 1.55× scale-up alone reads as a peak without the drop-shadow. */
@keyframes us-dot-fade {
  0%   { opacity: 0; transform: scale(0.55); }
  55%  { opacity: 1; transform: scale(1.55); }
  100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .slide-us.is-active.animate .us-map .dot { animation: none; opacity: 1; }
}

/* -------- Slide 10: Global Market -------------------------------------- */
.slide-global {
  display: flex; flex-direction: column;
  gap: 24px;
}
.global-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 32ch;
}
.global-headline .em { font-family: inherit; font-style: normal; font-weight: inherit; color: var(--accent-bright); }
/* Title group must sit above the opaque orbs, which sweep into the upper
   portion of the slide. */
.slide-global > .reveal {
  position: relative;
  z-index: 10;
}
.global-stage {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: clamp(20px, 2cqw, 40px);
  align-items: end;
  padding: clamp(24px, 4cqw, 48px) 0;
  overflow: visible;
}
.global-bubble {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  position: relative;
}
/* Smallest orb on top, largest in back — bubble z-index drives the stacking
   because each bubble forms its own scope for the orb inside it. */
.global-bubble:nth-child(1) { z-index: 3; }
.global-bubble:nth-child(2) { z-index: 2; }
.global-bubble:nth-child(3) { z-index: 1; }
/* Orbs are absolute-positioned so they don't push the bubble height past
   the viewport. Each orb's BOTTOM sits 16px above the bubble's top — so all
   three orb bottoms land on the same horizontal "ground line" above the
   $stat numbers. Sizes scale dramatically; the largest extends way above
   the slide top arc and gets clipped naturally by the viewport. */
.global-orb {
  position: absolute;
  bottom: calc(100% + 16px);
  left: 50%;
  transform: translateX(-50%);
  border-radius: 50%;
  /* Opaque canvas-colored disc so larger orb borders + coronas can't bleed
     through smaller orbs. Stacking: smallest on top, largest in back. */
  background: var(--bg);
  border: 1px solid rgba(244, 245, 248, 0.24);
  box-shadow:
    0 0 28px rgba(255, 255, 255, 0.10),
    0 0 80px rgba(255, 255, 255, 0.06),
    0 0 160px rgba(255, 255, 255, 0.03);
  pointer-events: none;
}
.global-orb.size-sm {
  width: clamp(180px, 18cqw, 260px);
  aspect-ratio: 1;
  z-index: 3;
}
.global-orb.size-md {
  width: clamp(560px, 58cqw, 820px);
  aspect-ratio: 1;
  z-index: 2;
  box-shadow:
    0 0 80px rgba(255, 255, 255, 0.07),
    0 0 220px rgba(255, 255, 255, 0.04),
    0 0 440px rgba(255, 255, 255, 0.02);
}
.global-orb.size-lg {
  width: clamp(1400px, 145cqw, 2200px);
  aspect-ratio: 1;
  z-index: 1;
  box-shadow:
    0 0 140px rgba(255, 255, 255, 0.05),
    0 0 360px rgba(255, 255, 255, 0.025),
    0 0 720px rgba(255, 255, 255, 0.012);
}
.global-num {
  font-family: var(--font-mono);
  font-size: var(--t-32);
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--text);
  line-height: 1;
}
.global-label {
  font-family: var(--font-mono);
  font-size: var(--t-13);
  color: var(--text-dim);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 4px;
  line-height: 1.3;
}
.global-label span { white-space: nowrap; }
.global-label .global-label-title { color: var(--text); }
/* Industry list under the largest bubble. Slightly smaller, tighter
   tracking, normal case so the dots/middots read; allowed to wrap so
   long industry strings don't blow out the bubble width. */
.global-label .global-label-detail {
  font-size: 0.78em;
  letter-spacing: 0.06em;
  text-transform: none;
  color: var(--text-dim);
  white-space: normal;
  max-width: 22ch;
  margin-top: 2px;
}

/* -------- Slide 11 + 19: Three-row text slides ------------------------- */
.slide-tri {
  display: flex; flex-direction: column;
  gap: clamp(28px, 3cqw, 44px);
  justify-content: center;
}
.tri-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-40);
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--text);
  max-width: 38ch;
  margin-bottom: clamp(16px, 2cqw, 24px);
}
.tri-headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.005em;
}
.tri-list { display: grid; gap: 28px; }

/* Slide 5 (Why Now) — three-force squeeze + verdict line.
   Title pins to top-left; verdict is pushed to the bottom of the slide. */
.slide-tri:has(.crisis-forces) {
  justify-content: flex-start;
}
.crisis-forces {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 3cqw, 56px);
  width: 100%;
  max-width: 1100px;
  margin: auto auto 0;
}
.crisis-force {
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.4cqw, 18px);
  padding: clamp(28px, 3cqw, 40px) clamp(20px, 2cqw, 28px) 0;
  border-top: 1px solid var(--border-soft);
  position: relative;
}
.crisis-force::before {
  content: '';
  position: absolute;
  left: 0;
  top: -1px;
  width: clamp(28px, 3cqw, 40px);
  height: 1px;
  background: var(--accent-bright);
}
.crisis-num {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.22em;
  color: var(--text-dim);
}
.crisis-stat {
  display: flex;
  align-items: baseline;
  gap: clamp(8px, 1cqw, 14px);
  margin: clamp(6px, 1cqw, 12px) 0 clamp(4px, 0.6cqw, 8px);
  font-family: var(--font-display);
  letter-spacing: -0.04em;
  line-height: 0.95;
}
.crisis-force.is-up   .crisis-stat { color: #FFFFFF; }
.crisis-force.is-down .crisis-stat { color: var(--accent-bright); }
.crisis-force.is-up   .crisis-label-arrow { color: #FFFFFF; }
.crisis-force.is-down .crisis-label-arrow { color: var(--accent-bright); }
.crisis-label-arrow {
  width: 0.95em;
  height: 0.95em;
  flex: none;
  color: currentColor;
}
.crisis-stat-num {
  font-size: clamp(56px, 7cqw, 104px);
  font-weight: 300;
  letter-spacing: -0.045em;
  color: currentColor;
  /* Slot-machine container: tabular-nums keeps proportional-font digit cells
     aligned (1ch is the width of "0" — without tabular figures, slimmer
     digits like "1" look squeezed in their cells). */
  display: inline-flex;
  align-items: center;
  height: 1em;
  line-height: 1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.crisis-stat-ref {
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.95cqw, 14px);
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--text-soft);
  align-self: flex-start;
  margin-left: 4px;
  line-height: 1;
  position: relative;
  top: 0.15em;
}
.crisis-label {
  font-family: var(--font-display);
  font-size: clamp(20px, 1.9cqw, 28px);
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0;
  line-height: 1.05;
  display: flex;
  align-items: center;
  gap: clamp(6px, 0.6cqw, 10px);
}
.crisis-cap {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0;
}

.crisis-verdict {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-40);
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--text);
  text-align: center;
  /* Sit on a single line if the viewport allows; wrap balanced
     when it doesn't. Auto top + bottom margin centers the verdict
     vertically between the stat row above and the slide bottom. */
  max-width: 100%;
  margin: auto auto;
  text-wrap: balance;
}
.crisis-verdict .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  color: var(--accent-bright);
  letter-spacing: -0.005em;
}

/* Slide 11: two-pillar split — Demand + Implementation. Each panel has a
   small kicker, a punchy title, a hero (quote or stat), and a footing line. */
.why-split {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 5cqw, 80px);
  align-content: center;
  position: relative;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}
.why-split::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 8%;
  bottom: 8%;
  width: 1px;
  background: var(--border);
}
.why-split.is-single {
  grid-template-columns: 1fr;
  max-width: 720px;
}
.why-split.is-single::before { display: none; }
.why-side {
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 2.6cqw, 36px);
}
.why-head {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: clamp(14px, 1.4cqw, 18px);
  border-bottom: 1px solid var(--border-soft);
}
.why-mark {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.why-title {
  font-family: var(--font-display);
  font-size: var(--t-24);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0;
  line-height: 1.04;
}

.why-hero {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  justify-content: flex-start;
  padding-top: clamp(24px, 3cqw, 48px);
}
.why-quote {
  font-family: var(--font-display);
  font-size: clamp(24px, 2.6cqw, 36px);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--text);
  margin: 0;
}
.why-quote .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  color: var(--accent-bright);
  letter-spacing: -0.005em;
}
.why-attribution {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0;
}
.why-stat {
  display: flex;
  align-items: baseline;
  gap: clamp(12px, 1.4cqw, 20px);
  flex-wrap: wrap;
}
.why-stat-old {
  font-family: var(--font-mono);
  font-size: clamp(28px, 2.8cqw, 40px);
  color: var(--text-dim);
  letter-spacing: -0.02em;
  text-decoration: line-through;
  text-decoration-color: var(--text-faint);
}
.why-stat-arrow {
  font-family: var(--font-mono);
  font-size: var(--t-24);
  color: var(--text-faint);
}
.why-stat-new {
  font-family: var(--font-mono);
  font-size: clamp(40px, 4.4cqw, 60px);
  color: var(--text);
  font-weight: 500;
  letter-spacing: -0.03em;
}

.why-foot {
  font-family: var(--font-display);
  font-size: var(--t-15);
  color: var(--text-soft);
  line-height: 1.5;
  padding-top: clamp(14px, 1.4cqw, 20px);
  border-top: 1px solid var(--border-soft);
}
.why-foot-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.why-foot-list li {
  position: relative;
  padding-left: 14px;
}
.why-foot-list li::before {
  content: "•";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--text-faint);
}
.tri-row {
  display: grid;
  grid-template-columns: clamp(140px, 16cqw, 220px) 1fr;
  gap: clamp(24px, 3cqw, 56px);
  padding-top: 24px;
  border-top: 1px solid var(--border);
  align-items: baseline;
}
.tri-lead {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-20);
  color: var(--text);
  letter-spacing: -0.01em;
}
.tri-body {
  font-size: var(--t-15);
  color: var(--text-muted);
  line-height: 1.6;
  max-width: 64ch;
}
.tri-body strong { color: var(--text); font-weight: 500; }
.tri-body .em { color: var(--text); font-family: var(--font-serif); font-style: italic; }

/* -------- Slide 12: Risks --------------------------------------------- */
.slide-risks { display: flex; flex-direction: column; gap: 28px; justify-content: center; }
.risks-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
  margin-bottom: 16px;
}
.risks-list { display: grid; gap: 22px; }
.risk-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(20px, 2cqw, 32px);
  padding-top: 22px;
  border-top: 1px solid var(--border);
  align-items: baseline;
}
.risk-quote {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--t-56);
  color: var(--text-faint);
  line-height: 0.9;
  user-select: none;
  font-weight: 400;
}
.risk-content { display: grid; gap: 8px; }
.risk-objection {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-20);
  color: var(--text);
  letter-spacing: -0.01em;
}
.risk-rebuttal {
  font-size: var(--t-15);
  color: var(--text-muted);
  line-height: 1.55;
  max-width: 110ch;
}

/* -------- Admin analytics (admin.html) --------------------------------- */
/* The base reset locks html/body scroll for the deck; the admin page
   needs natural page scroll so expanded per-viewer rows don't get
   clipped at the viewport bottom. */
html:has(.admin-body),
body.admin-body {
  overflow: auto;
  height: auto;
  min-height: 100%;
}
.admin-body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-display);
  padding: clamp(24px, 4cqw, 48px);
}
.admin {
  max-width: 1100px;
  margin: 0 auto;
}
.admin-head { margin-bottom: 32px; }
.admin-logo { height: 32px; width: auto; opacity: 0.75; margin-bottom: 16px; display: block; }
.admin-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 6px;
}
.admin-sub {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-dim);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin: 0;
}
.admin-form { display: flex; gap: 10px; margin: 24px 0; max-width: 500px; }
.admin-form input {
  flex: 1; background: rgba(255,255,255,0.04); border: 1px solid var(--border);
  border-radius: 8px; padding: 12px 14px; color: var(--text);
  font-family: var(--font-display); font-size: var(--t-15); outline: none;
}
.admin-form input:focus { border-color: var(--accent-bright); }
.admin-form button {
  background: var(--accent-soft); color: #fff; border: 1px solid var(--accent-bright);
  border-radius: 8px; padding: 12px 18px; font-family: var(--font-display);
  font-weight: 500; font-size: var(--t-15); cursor: pointer;
}
.admin-form button:hover { background: var(--accent-bright); }
.admin-meta {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--text-dim);
  letter-spacing: 0.12em; text-transform: uppercase;
}
.admin-controls {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 14px; flex-wrap: wrap;
}
.admin-sort {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--text-dim);
  letter-spacing: 0.12em; text-transform: uppercase;
}
.admin-sort select {
  background: rgba(255,255,255,0.04); border: 1px solid var(--border);
  border-radius: 6px; padding: 6px 28px 6px 10px; color: var(--text);
  font-family: var(--font-display); font-size: var(--t-13); letter-spacing: 0;
  text-transform: none; outline: none; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-soft) 50%),
                    linear-gradient(135deg, var(--text-soft) 50%, transparent 50%);
  background-position: calc(100% - 14px) 50%, calc(100% - 9px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.admin-sort select:focus { border-color: var(--accent-bright); }
.admin-table {
  width: 100%; border-collapse: collapse;
  font-family: var(--font-display); font-size: var(--t-15);
}
.admin-table thead th {
  text-align: left; padding: 12px 12px; font-family: var(--font-mono);
  font-size: var(--t-11); color: var(--text-soft); letter-spacing: 0.16em;
  text-transform: uppercase; font-weight: 500; border-bottom: 1px solid var(--border);
}
.admin-table thead th.num { text-align: right; }
.admin-table tbody td {
  padding: 12px 12px; border-top: 1px solid var(--border-soft);
  color: var(--text-soft); font-variant-numeric: tabular-nums;
}
.admin-table tbody td.num { text-align: right; }
.admin-row { cursor: pointer; transition: background 120ms ease-out; }
.admin-row:hover { background: rgba(255,255,255,0.03); }
.admin-row.open { background: rgba(94,106,210,0.06); color: var(--text); }
.admin-row .toggle { width: 20px; color: var(--text-faint); font-family: var(--font-mono); }
.admin-row .viewer { color: var(--text); }
.admin-detail td {
  background: rgba(0,0,0,0.25); border-top: none; padding: 0;
}
.per-slide { padding: 16px 16px 22px 40px; }
.per-slide-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 4px 32px; font-family: var(--font-mono); font-size: var(--t-13);
}
.per-slide-row {
  display: grid; grid-template-columns: 30px 1fr auto auto;
  gap: 12px; align-items: baseline; padding: 4px 0;
  border-bottom: 1px dotted var(--border-soft);
}
.ps-num { color: var(--text-faint); }
.ps-name { color: var(--text); font-family: var(--font-display); }
.ps-visits { color: var(--text-dim); font-size: var(--t-11); }
.ps-time { color: var(--text); font-variant-numeric: tabular-nums; }
.admin-error {
  margin-top: 16px; padding: 12px 14px; border: 1px solid #ef4444;
  border-radius: 8px; background: rgba(239,68,68,0.08); color: #fca5a5;
  font-family: var(--font-mono); font-size: var(--t-13);
}

/* -------- Rotate-to-landscape overlay --------------------------------- */
/* Shown only on portrait phones (max-width: 768px + orientation: portrait).
   The deck is designed for landscape; instead of maintaining a parallel
   portrait stylesheet, we obscure the deck and ask the viewer to rotate. */
.rotate-prompt {
  display: none;
}
@media (max-width: 768px) and (orientation: portrait) {
  .rotate-prompt {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: var(--bg);
    align-items: center;
    justify-content: center;
    padding: 24px;
  }
  .rotate-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    text-align: center;
    max-width: 320px;
    color: var(--text);
  }
  .rotate-icon {
    width: 64px;
    height: 64px;
    color: var(--accent-bright);
    animation: rotate-prompt-tilt 2.4s ease-in-out infinite;
    transform-origin: 32px 32px;
  }
  .rotate-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 22px;
    letter-spacing: -0.015em;
    color: var(--text);
  }
  .rotate-sub {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--text-dim);
    line-height: 1.5;
  }
  /* Hide all other deck chrome behind the overlay so a finger-tap doesn't
     accidentally interact with the deck while the prompt is up. */
  body.is-mobile #deck,
  body.is-mobile .nav,
  body.is-mobile .progress,
  body.is-mobile .footer-meta,
  body.is-mobile .brand,
  body.is-mobile .help,
  body.is-mobile .ambient-caustics {
    visibility: hidden !important;
  }
}
@keyframes rotate-prompt-tilt {
  0%, 100% { transform: rotate(0deg); }
  40%      { transform: rotate(-90deg); }
  60%      { transform: rotate(-90deg); }
}

/* -------- Email gate (gate.html) --------------------------------------- */
.gate-body {
  min-height: 100cqh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-display);
}
.gate {
  position: relative;
  z-index: 2;
  width: min(92%, 520px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(20px, 2.4cqw, 28px);
  padding: clamp(24px, 4cqw, 48px);
}
.gate-logo {
  height: clamp(36px, 4cqw, 56px);
  width: auto;
  margin-bottom: clamp(16px, 2cqw, 24px);
}
.gate-title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(36px, 4.4cqw, 56px);
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--text);
  margin: 0;
}
.gate-title .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}
.gate-sub {
  font-family: var(--font-display);
  font-size: var(--t-17);
  color: var(--text-soft);
  margin: 0;
  line-height: 1.4;
}
.gate-form {
  display: flex;
  gap: 10px;
  width: 100%;
  margin-top: 8px;
}
.gate-form input {
  flex: 1;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--t-15);
  outline: none;
  transition: border-color 160ms ease-out, background 160ms ease-out;
}
.gate-form input:focus {
  border-color: var(--accent-bright);
  background: rgba(255, 255, 255, 0.06);
}
.gate-form input::placeholder {
  color: var(--text-faint);
}
.gate-form button {
  background: var(--accent-soft);
  color: #fff;
  border: 1px solid var(--accent-bright);
  border-radius: 8px;
  padding: 14px 20px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-15);
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background 160ms ease-out;
  white-space: nowrap;
}
.gate-form button:hover {
  background: var(--accent-bright);
}
.gate-foot {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-dim);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin: clamp(12px, 1.6cqw, 24px) 0 0;
}

/* -------- Slide 14: Pro forma ------------------------------------------ */
.slide-proforma {
  display: flex; flex-direction: column;
  gap: clamp(20px, 2.6cqw, 32px);
  justify-content: center;
}
.proforma-wrap {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.proforma-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: var(--t-13);
  font-variant-numeric: tabular-nums;
}
.proforma-table thead th {
  text-align: right;
  padding: 12px 10px;
  background: rgba(255,255,255,0.02);
  color: var(--text-soft);
  font-weight: 500;
  font-size: var(--t-11);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.proforma-table thead th.pf-label,
.proforma-table tbody td.pf-label {
  text-align: left;
  font-family: var(--font-display);
  text-transform: none;
  letter-spacing: -0.005em;
  color: var(--text);
  font-weight: 400;
  font-size: var(--t-13);
}
.proforma-table tbody td {
  padding: 10px 10px;
  text-align: right;
  color: var(--text-soft);
  border-top: 1px solid var(--border-soft);
}
.proforma-table tbody tr.pf-row-strong td {
  color: var(--text);
  background: rgba(255,255,255,0.025);
  font-weight: 500;
}
.proforma-table tbody tr.pf-row-cash td {
  color: var(--text);
  background: rgba(94, 106, 210, 0.08);
  font-weight: 500;
}
.proforma-foot {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-dim);
  letter-spacing: 0.02em;
  margin: 0;
  text-align: center;
}

/* -------- Slide 15: Moat (was 14, now 15) ----------------------------- */
.slide-moat {
  display: flex; flex-direction: column;
  gap: clamp(20px, 2.6cqw, 36px);
  justify-content: center;
  /* Push the centered content stack down a touch — the headline was
     reading too high against the slide's vertical midline. */
  padding-top: clamp(24px, 4cqh, 64px);
}
.moat-lede {
  font-family: var(--font-display);
  font-size: var(--t-20);
  color: var(--text-soft);
  max-width: 80ch;
  line-height: 1.4;
  margin: 0;
}
.moat-list { display: grid; gap: clamp(20px, 2cqw, 28px); }
.moat-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(20px, 2cqw, 32px);
  padding-top: 22px;
  border-top: 1px solid var(--border);
  align-items: baseline;
}
.moat-num {
  font-family: var(--font-mono);
  font-size: var(--t-13);
  color: var(--text-faint);
  letter-spacing: 0.18em;
  font-variant-numeric: tabular-nums;
}
.moat-content { display: grid; gap: 8px; }
.moat-claim {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-20);
  color: var(--text);
  letter-spacing: -0.01em;
}
.moat-body {
  font-size: var(--t-15);
  color: var(--text-muted);
  line-height: 1.55;
  max-width: 110ch;
  margin: 0;
  /* Avoids a single word landing alone on the last line. */
  text-wrap: pretty;
}

/* -------- Slide 13: GTM ------------------------------------------------ */
.slide-gtm {
  display: flex; flex-direction: column;
  gap: 24px;
}
.gtm-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 36ch;
}
.gtm-headline .arrow {
  font-family: var(--font-mono);
  color: #FFFFFF;
  padding: 0 0.18em;
  font-weight: 400;
}
.gtm-stage {
  flex: 1;
  display: grid;
  /* Equal columns + matching horizontal padding so the captions
     ($21k / $105k / $6.3m) align with the TAM stats on slide 11. */
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto;
  gap: clamp(20px, 3cqw, 56px);
  align-items: end;
  align-content: center;
  padding: clamp(20px, 3cqw, 40px) 0;
}
.gtm-fig {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.gtm-fig-img-wrap {
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.gtm-fig-img {
  width: 100%;
  max-width: 360px;
  height: auto;
  display: block;
}
.gtm-fig:nth-child(3) .gtm-fig-img { max-width: 460px; }

.gtm-caption {
  text-align: center;
  display: flex; flex-direction: column; gap: 6px;
  padding-top: 12px;
  border-top: 1px solid rgba(244,245,248,0.06);
  width: 78%;
  max-width: 260px;
}
.gtm-caption-acv {
  font-family: var(--font-mono);
  font-size: var(--t-32);
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--text);
  line-height: 1;
  margin-bottom: 4px;
}
.gtm-caption-label {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-15);
  color: var(--text);
  letter-spacing: -0.005em;
}
.gtm-caption-sub {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.10em;
  text-transform: uppercase;
}

.gtm-assumptions {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
  text-align: center;
  margin: clamp(12px, 1.6cqw, 20px) auto 0;
}

/* -------- Slide 14: Roadmap ------------------------------------------- */
.slide-roadmap {
  display: flex; flex-direction: column;
  gap: 24px;
}
.roadmap-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
}
.roadmap-headline .accent {
  font-family: var(--font-mono);
  color: var(--accent-bright);
  letter-spacing: -0.04em;
}
.roadmap {
  position: relative;
  flex: 1;
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  align-items: stretch;
  margin-top: clamp(24px, 3cqw, 40px);
  /* Constrain width to ~88% of the slide so the graph has breathing
     room on both sides; pure percentage (no px cap) so it scales with
     viewport at every size — a clamp here would leave the graph
     stranded mid-slide on a full-screen viewport once the upper bound
     engaged. */
  width: 88%;
  margin-inline: auto;
  padding: 0 24px;
  /* Even-spacing geometry: dots step from 0 toward the pill's CENTER
     (86%), not its left edge. Anchoring on the visual centre of the
     pill makes the gap "read" even — when we anchored on pill-left,
     the math was equal but the chunky pill made the final gap look
     wider than inter-dot. Last dot sits at 6/7 of the way to pill
     center, leaving the pill itself for the final beat. */
  --span: 86%;
  --step: calc(var(--span) / 7);
}
.roadmap-line {
  position: relative;
  height: 1px;
  background: linear-gradient(to right, var(--border-strong) 0 86%, transparent 86% 100%);
  align-self: center;
  overflow: visible;
}
/* Travelling glow that races down the line into SEED. Sits at z-index 0
   so the spend pills and final SEED pill (z-index 2) eclipse it as it
   passes — the pulse looks like it's running underneath them. */
.roadmap-pulse {
  position: absolute;
  top: 50%;
  left: 0;
  /* Solid white pill — the bloom comes entirely from the layered filter
     below. Same recipe as the slide-6 pulse-stroke so they read as the
     same kind of soft glowing dot. */
  width: 14px;
  height: 5px;
  transform: translate(-50%, -50%);
  background: #FFFFFF;
  border-radius: 999px;
  filter:
    blur(1.5px)
    drop-shadow(0 0 4px rgba(255, 255, 255, 0.95))
    drop-shadow(0 0 12px rgba(255, 255, 255, 0.6))
    drop-shadow(0 0 26px rgba(255, 255, 255, 0.34));
  pointer-events: none;
  z-index: 0;
  /* Ease-in: starts slow, accelerates the whole way down the line, hits
     SEED at peak velocity — no deceleration in the final stretch. */
  animation: roadmap-pulse-travel 3.2s cubic-bezier(0.42, 0, 1, 1) infinite;
}
@keyframes roadmap-pulse-travel {
  0%   { left: 0%;  opacity: 0; }
  6%   {            opacity: 1; }
  85%  { left: 86%; opacity: 1; }
  92%  { left: 86%; opacity: 0.6; }
  100% { left: 86%; opacity: 0; }
}
.roadmap-spend {
  position: absolute;
  top: 50%; transform: translate(-50%, -50%);
  background: var(--bg);
  border: 1px solid var(--border-strong);
  padding: 6px 12px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-soft);
  letter-spacing: 0.04em;
  white-space: nowrap;
  z-index: 2;
}
/* SEED: black pill, white wordmark, with a corona that idles low and
   blooms when the pulse arrives (synced via shared 4.8s cycle). */
.roadmap-final {
  position: absolute;
  top: 50%; left: 86%; transform: translate(-50%, -50%);
  background: #000;
  color: #FFFFFF;
  padding: 9px 22px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  /* Pill is anchored at left:86% with translate(-50%) so the available
     intrinsic width is ~14% of the row, which can shrink below content
     width on narrow viewports (landscape mobile) and force "SERIES A"
     to wrap onto two lines. nowrap pins the pill to its content width. */
  white-space: nowrap;
  z-index: 2;
  border: 1px solid rgba(255, 255, 255, 0.18);
  /* Glow cycle synced with the travelling pulse — same 3.2s ease-in
     timing so the bloom builds in lockstep with the accelerating dot. */
  animation: roadmap-final-glow 3.2s cubic-bezier(0.42, 0, 1, 1) infinite;
}
/* SEED stays dark until the pulse arrives — no idle glow. The bloom
   only fires in the last ~20% of the cycle, peaks at 88% (when the
   accelerating pulse reaches the pill), then fades back to dark before
   the loop wraps so the next cycle starts cold again. */
@keyframes roadmap-final-glow {
  0%, 72% {
    box-shadow: 0 0 0 rgba(255, 255, 255, 0);
    border-color: rgba(255, 255, 255, 0.18);
  }
  88% {
    box-shadow:
      0 0 6px rgba(255, 255, 255, 1),
      0 0 18px rgba(255, 255, 255, 0.82),
      0 0 48px rgba(255, 255, 255, 0.46),
      0 0 96px rgba(255, 255, 255, 0.22);
    border-color: rgba(255, 255, 255, 0.95);
  }
  100% {
    box-shadow: 0 0 0 rgba(255, 255, 255, 0);
    border-color: rgba(255, 255, 255, 0.18);
  }
}
@media (prefers-reduced-motion: reduce) {
  .roadmap-pulse { animation: none; opacity: 0; }
  .roadmap-final { animation: none; }
}
.roadmap-row { position: relative; z-index: 2; }
/* Visual content (first dot → pill right edge) spans ~0% → ~92% of
   the row width because the pill is centered at 86% with its own
   half-width. To center the visual mass within .roadmap, shift the
   rows + line by half the deficit (~4%) to the right. */
.roadmap-row, .roadmap-line { transform: translateX(4%); }
.roadmap-line { z-index: 1; }
.roadmap-milestone {
  position: absolute;
  width: 1px;
  background: var(--border);
}
.roadmap-row.top .roadmap-milestone { bottom: 0; height: 60%; }
.roadmap-row.bottom .roadmap-milestone { top: 0; height: 60%; }
.roadmap-milestone .dot {
  position: absolute;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent-bright);
  box-shadow: none;
  z-index: 2;
}
.roadmap-row.top .roadmap-milestone .dot { bottom: -3px; left: -3px; }
.roadmap-row.bottom .roadmap-milestone .dot { top: -3px; left: -3px; }
.roadmap-milestone .content {
  position: absolute;
  left: 16px;
  display: grid; gap: 6px;
  width: clamp(160px, 16cqw, 230px);
}
.roadmap-row.top .roadmap-milestone .content { top: 0; }
.roadmap-row.bottom .roadmap-milestone .content { bottom: 0; }
.roadmap-milestone .when {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-soft);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.roadmap-milestone .what {
  font-family: var(--font-display);
  font-size: var(--t-17);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.01em;
}
.roadmap-milestone .detail {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-15);
  color: var(--text-soft);
  line-height: 1.45;
}

/* -------- Slide 15: Appendix divider ----------------------------------- */
.slide-appendix {
  align-items: center;
  justify-content: center;
}
.appendix-mark {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-40);
  letter-spacing: -0.025em;
  line-height: 1.04;
  color: var(--text);
}

/* -------- Slide 16 + 17: Stat list slides ------------------------------ */
.slide-stats {
  display: flex; flex-direction: column;
  gap: clamp(28px, 3cqw, 44px);
  justify-content: center;
}
.stats-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 56ch;
  line-height: 1.2;
}
.stats-headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}
.stats-list { display: grid; gap: 22px; }
.stat-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(20px, 2cqw, 32px);
  padding-top: 22px;
  border-top: 1px solid var(--border);
  align-items: baseline;
}
.stat-marker {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-faint);
  letter-spacing: 0.16em;
  font-variant-numeric: tabular-nums;
}
.stat-content { display: grid; gap: 8px; }
.stat-claim {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--t-20);
  color: var(--text);
  letter-spacing: -0.01em;
}
.stat-body {
  font-size: var(--t-15);
  color: var(--text-muted);
  line-height: 1.55;
  max-width: 110ch;
  margin: 0;
  text-wrap: pretty;
}
.stat-content strong { color: var(--text); font-weight: 500; }
.stat-content .num {
  font-family: var(--font-mono);
  color: var(--accent-bright);
  font-weight: 500;
  letter-spacing: -0.02em;
}
.stat-content .ref {
  font-family: var(--font-mono);
  font-size: 0.7em;
  color: var(--text-faint);
  vertical-align: super;
  padding-left: 2px;
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
.stat-content .ref:hover { color: var(--accent-bright); }

.citations {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px 24px;
}
.citations li {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.04em;
}
.citations li::before { content: '— '; color: var(--text-faint); }

/* -------- Slide 10: Manual-supervision problem schematic ---------------
   Pure visual metaphor — boustrophedon (snake) path through 11 abstract
   glyph-nodes, no labels. Visual goal: the sheer length and back-and-
   forth of the path IS the message. Final node renders in danger to
   anchor the eye on the failure endpoint. */
.slide-problem {
  justify-content: flex-start;
  gap: clamp(28px, 3cqw, 48px);
}
.problem-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 2.8cqw, 46px);
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--text);
  margin: 0;
  max-width: 30ch;
}
.problem-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.08em;
  letter-spacing: -0.005em;
  color: var(--accent-bright);
}
.problem-flow {
  display: flex;
  flex: 1;
  min-height: 0;
  align-items: center;
  justify-content: center;
  margin-top: clamp(10px, 1.2cqw, 18px);
}
.problem-schematic {
  width: 100%;
  height: 100%;
  display: block;
  /* Path drawing animation. Generous dasharray covers the full path
     length so the line traces in once on slide activation. */
  stroke-linecap: round;
  stroke-linejoin: round;
}
.problem-schematic .schematic-path {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.6;
  stroke-dasharray: 5400;
  stroke-dashoffset: 5400;
  animation: schematic-draw 2400ms cubic-bezier(0.45, 0.05, 0.2, 1) 320ms forwards;
}
@keyframes schematic-draw {
  to { stroke-dashoffset: 0; }
}
/* Each node is a hollow disc that masks the path line where it crosses,
   with a centered abstract glyph inside. Stagger fade-in is timed so
   nodes appear roughly as the path traces past them. */
.problem-schematic .schematic-node {
  opacity: 0;
  animation: schematic-node-in 380ms var(--ease) forwards;
  animation-delay: calc(560ms + var(--n, 0) * 200ms);
}
@keyframes schematic-node-in {
  from { opacity: 0; transform-origin: center; }
  to   { opacity: 1; }
}
.problem-schematic .node-bg {
  fill: var(--bg);
  stroke: var(--border-strong);
  stroke-width: 1;
}
.problem-schematic .node-glyph {
  fill: none;
  stroke: var(--text);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.problem-schematic .node-glyph .glyph-dot {
  fill: var(--text);
  stroke: none;
}
/* Failure node: red disc + red glyph. No border, no soft fill — solid
   so the eye snaps to it as the resolved end of the journey. */
.problem-schematic .schematic-node.is-fail .node-bg {
  fill: var(--bg);
  stroke: var(--danger);
  stroke-width: 1.4;
}
.problem-schematic .schematic-node.is-fail .node-glyph {
  stroke: var(--danger);
}
.problem-schematic .schematic-node.is-fail .node-glyph .glyph-dot {
  fill: var(--danger);
}

/* -------- Appendix: Tribal-knowledge ideal-architecture loop ----------------
   Five-station closed loop (sense → understand → attribute → compile → verify
   → back to sense). The forward path is neutral hairline; the return arc is
   accent-colored to read as "this is the feedback that makes the system
   improve." Fully static — no animations. */
.slide-loop {
  justify-content: flex-start;
  gap: clamp(20px, 2.2cqw, 36px);
}
.loop-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 2.8cqw, 46px);
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: var(--text);
  margin: 0;
}
.loop-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.06em;
  letter-spacing: -0.005em;
  color: var(--accent-bright);
}
.loop-flow {
  display: flex;
  flex: 1;
  min-height: 0;
  align-items: center;
  justify-content: center;
  margin-top: clamp(8px, 1.2cqw, 22px);
}
.loop-schematic {
  width: 100%;
  height: 100%;
  display: block;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Arrow markers — neutral for forward, accent for return. */
.loop-schematic .tip-stroke {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.loop-schematic .tip-accent {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Forward connectors — neutral hairline. */
.loop-schematic .loop-forward line {
  stroke: var(--border-strong);
  stroke-width: 1.5;
  fill: none;
}

/* Return arc — same neutral hairline as the forward connectors, so the
   loop reads as a single continuous line rather than a colored callout. */
.loop-schematic .loop-return {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.5;
  opacity: 1;
}

/* Corona — soft white bloom behind each node. Starts hidden and fades in
   left-to-right on slide load so the loop "lights up" station by station. */
.loop-schematic .loop-coronas circle {
  fill: #FFFFFF;
  opacity: 0;
  filter: blur(22px);
  pointer-events: none;
}
.slide.is-active.animate.slide-loop .loop-coronas circle {
  animation: loop-corona-in 700ms var(--ease) both;
}
.slide.is-active.animate.slide-loop .loop-coronas circle:nth-child(1) { animation-delay: 420ms; }
.slide.is-active.animate.slide-loop .loop-coronas circle:nth-child(2) { animation-delay: 620ms; }
.slide.is-active.animate.slide-loop .loop-coronas circle:nth-child(3) { animation-delay: 820ms; }
.slide.is-active.animate.slide-loop .loop-coronas circle:nth-child(4) { animation-delay: 1020ms; }
.slide.is-active.animate.slide-loop .loop-coronas circle:nth-child(5) { animation-delay: 1220ms; }
@keyframes loop-corona-in {
  from { opacity: 0; }
  to   { opacity: 0.22; }
}

/* Nodes — concentric dashed halo + crisp inner disc + abstract glyph. */
.loop-schematic .loop-node-halo {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: 0.55;
  stroke-dasharray: 2 5;
}
.loop-schematic .loop-node-bg {
  fill: var(--bg);
  stroke: var(--text-muted);
  stroke-width: 1.2;
}
.loop-schematic .loop-node-glyph {
  fill: none;
  stroke: var(--text);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.loop-schematic .loop-node-glyph .loop-dot {
  fill: var(--text);
  stroke: none;
}
.loop-schematic .loop-node-glyph .loop-fill-dot {
  fill: var(--text);
  stroke: none;
}

/* Labels — "01  SENSE" style with accent-tinted number. */
.loop-schematic .loop-label text {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: 0.18em;
  fill: var(--text);
}
.loop-schematic .loop-label .loop-num {
  fill: var(--accent-bright);
  font-weight: 500;
  letter-spacing: 0.08em;
}
.loop-schematic .loop-label .loop-name {
  fill: var(--text);
}

/* Captions below each node — pure typography, no card chrome.
   Lead: display font, light-weight headline tone. Detail: a quieter,
   slightly tracked metadata line in muted ink. Hierarchy is built
   entirely through weight, size, and color — Apple-style restraint. */
.loop-schematic .loop-caption text {
  font-family: var(--font-display);
}
.loop-schematic .loop-caption .loop-caption-lead {
  font-size: 24px;
  font-weight: 400;
  letter-spacing: -0.012em;
  fill: var(--text);
}
.loop-schematic .loop-caption .loop-caption-detail {
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0.08em;
  fill: var(--text-muted);
  opacity: 0.78;
}

/* -------- Slide 11: Housekeeping use-case (before / after) ---------------
   Two-column layout. Left: the manual 9-step process today, rendered as
   a vertical pill stack with hairline connectors between steps (matching
   the slide-org-7 industries connector aesthetic). Right: a single
   @Tempo prompt + the autonomous task cards Tempo runs in response. */
.slide-housekeeping {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: clamp(20px, 2.4cqw, 36px);
}
.hk-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 1.8cqw, 30px);
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--text);
  margin: 0;
  /* No max-width: the headline runs the full slide width so it only wraps
     when it hits the right edge, not at an arbitrary character count. */
}
.hk-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.06em;
  color: var(--accent-bright);
}
.hk-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 4cqw, 80px);
  flex: 1;
  min-height: 0;
  /* Stretch (default for grid) lets both columns extend to the row height
     so the bottom result + cost group can pin to the baseline with
     margin-top: auto, and the center divider can span the full height. */
  align-items: stretch;
  position: relative;
}
/* Center divider — a hairline that visually splits "Today" from "With
   Tempo" so the slide reads as a single before/after diptych. Fades at
   the top/bottom so it doesn't crash into the column tags or slide edge. */
.hk-split::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: linear-gradient(
    to bottom,
    transparent 0,
    var(--border) 12%,
    var(--border) 88%,
    transparent 100%
  );
  transform: translateX(-50%);
  pointer-events: none;
}
.hk-column {
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.4cqw, 20px);
  min-width: 0;
}

/* "Fully loaded cost" callout on the left column — mirrors the slide-10
   ROI meter typography (mono value, uppercase mono label, dim mono fine
   print). margin-top: auto pins it to the bottom of the stretched column. */
.hk-foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding-top: clamp(14px, 1.6cqh, 24px);
}

/* Right-column ROI foot stays invisible until the task cascade completes
   (or the user fast-forwards). main.js adds .is-revealed when it kicks
   off the slot-machine roll. Hiding the whole block — number + label +
   fine print — means viewers never see the "0.0x" placeholder state. */
.slide-housekeeping .hk-after .hk-foot {
  opacity: 0;
  transition: opacity 280ms ease-out;
}
.slide-housekeeping .hk-after .hk-foot.is-revealed {
  opacity: 1;
}
/* Persistent soft glow on the ROI number once the slot lands — telegraphs
   "this is the payoff." Lives only on the .meter-value so the label and
   fine print stay clean. We use filter: drop-shadow at the .meter-value
   level rather than text-shadow on the digits because each digit lives
   inside a .slot-cell with overflow:hidden — text-shadow gets clipped at
   the cell boundary (looks like a hazy block). drop-shadow operates on
   the parent's rendered output, so it traces the actual visible digit
   silhouettes and extends past the cell edges. */
.slide-housekeeping .hk-after .hk-foot .meter-value {
  filter:
    drop-shadow(0 0 6px  rgba(255, 255, 255, 0.65))
    drop-shadow(0 0 16px rgba(255, 255, 255, 0.40))
    drop-shadow(0 0 36px rgba(255, 255, 255, 0.22));
}
.hk-foot-fine {
  margin: 4px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.45;
  letter-spacing: 0.02em;
  color: var(--text-dim);
  text-align: center;
}
.hk-column-tag {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding-bottom: clamp(6px, 0.7cqw, 10px);
  border-bottom: 1px solid var(--border-soft);
}
.hk-tag-label {
  font-family: var(--font-mono);
  font-size: clamp(12px, 0.95cqw, 15px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-bright);
  font-weight: 500;
}
.hk-tag-detail {
  font-family: var(--font-mono);
  font-size: clamp(12px, 0.95cqw, 15px);
  letter-spacing: 0.04em;
  color: var(--text-soft);
}

/* ── Left column: the 9-step manual process ─────────────────────────── */
.hk-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.4cqh, 18px);
}
.hk-step {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(10px, 1cqw, 14px);
  padding: clamp(10px, 1.1cqw, 15px) clamp(14px, 1.2cqw, 18px);
  background: var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: 9999px;
  font-family: var(--font-display);
  font-size: clamp(12px, 0.9cqw, 14px);
  line-height: 1.3;
  color: var(--text-soft);
}
.hk-step-num {
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.7cqw, 11px);
  letter-spacing: 0.18em;
  color: var(--accent-bright);
  flex: none;
}
/* Service-recovery label that replaces the step number on .hk-step--recovery
   rows. Bold red to telegraph "whoops, we dropped the ball" — these are the
   unplanned items the manual supervisor has to handle on top of the
   numbered routine, which Tempo prevents from happening at all. */
.hk-step-recovery {
  font-family: var(--font-display);
  font-size: clamp(12px, 0.9cqw, 14px);
  font-weight: 700;
  color: var(--danger);
  flex: none;
  white-space: nowrap;
}
.hk-step-text {
  flex: 1;
  min-width: 0;
}
/* Right-aligned timestamp showing when this step happens in the supervisor's
   day. Mono + tabular-nums so the column aligns vertically across every
   pill regardless of how the step text wraps or which prefix it has. */
.hk-step-time {
  flex: none;
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.7cqw, 11px);
  letter-spacing: 0.04em;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  min-width: 6ch;
  text-align: right;
}
.hk-step-icon {
  width: clamp(14px, 1.1cqw, 17px);
  height: clamp(14px, 1.1cqw, 17px);
  flex: none;
  color: var(--text-dim);
  margin-left: auto;
}
/* Hairline connector between consecutive steps */
.hk-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: calc(-1 * clamp(8px, 1cqh, 14px));
  width: 1px;
  height: clamp(8px, 1cqh, 14px);
  background: var(--border-strong);
  transform: translateX(-50%);
}

/* Spotlight cycle: 9/10 supervisor steps stay dimmed; the animation
   sweeps one full-opacity highlight through the column step-by-step
   so the eye lands on a single task at a time instead of trying to
   read all ten at once. Cycle = 30s (3s per step); each step's
   highlight peaks for ~1.8s with a 0.6s cross-fade at each edge so
   adjacent steps overlap softly rather than snapping.
   `animation-fill-mode: both` holds the keyframe state during the
   negative-delay portion, so the column shows the correct dim/lit
   mix at t=0 instead of flashing fully-bright before settling. */
.hk-step {
  opacity: 0.24;
  animation: hk-step-spotlight 30s linear infinite both;
}
/* Positive delays (not negative) sweep top-to-bottom: each step waits
   at the 0% keyframe (opacity 0.24, held by fill-mode: both) until
   its turn, then plays through its 30s loop. Negative delays put
   each step at a different point in the cycle at t=0, which sweeps
   bottom-to-top — wrong direction. */
.hk-step:nth-child(1)  { animation-delay:  0s; }
.hk-step:nth-child(2)  { animation-delay:  3s; }
.hk-step:nth-child(3)  { animation-delay:  6s; }
.hk-step:nth-child(4)  { animation-delay:  9s; }
.hk-step:nth-child(5)  { animation-delay: 12s; }
.hk-step:nth-child(6)  { animation-delay: 15s; }
.hk-step:nth-child(7)  { animation-delay: 18s; }
.hk-step:nth-child(8)  { animation-delay: 21s; }
.hk-step:nth-child(9)  { animation-delay: 24s; }
.hk-step:nth-child(10) { animation-delay: 27s; }
@keyframes hk-step-spotlight {
  0%   { opacity: 0.24; }
  2%   { opacity: 1; }
  8%   { opacity: 1; }
  10%  { opacity: 0.24; }
  100% { opacity: 0.24; }
}
@media (prefers-reduced-motion: reduce) {
  .hk-step {
    animation: none;
    opacity: 1;
  }
}

/* ── Right column: @Tempo prompt + autonomous task cards ────────────── */
.hk-plate {
  align-self: stretch;
  max-width: none;
  margin: 0;
}
.hk-plate .cmd-row {
  font-size: clamp(13px, 1cqw, 16px);
}
/* Action row (icons + send button) at the bottom of the prompt plate.
   The shared `.cmd-icon` is 30×30 / `.cmd-send` is 28px tall — fine for
   the tiny portrait-mobile plate but visually heavy in the housekeeping
   slide where the plate is a wide hero block next to compact task
   cards. Scale them down here so the buttons read as controls, not
   competing with the cards. */
.hk-plate .cmd-icon {
  width: 24px;
  height: 24px;
}
.hk-plate .cmd-icon svg {
  width: 11px;
  height: 11px;
}
.hk-plate .cmd-send {
  height: 24px;
  padding: 0 3px 0 8px;
}
.hk-plate .cmd-send svg {
  width: 11px;
  height: 11px;
}
.hk-plate .cmd-send-chevron {
  height: 14px;
  padding-left: 4px;
  margin-left: 3px;
}
.hk-plate .cmd-send-chevron svg {
  width: 9px;
  height: 9px;
}
.hk-tasks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1cqh, 14px);
  position: relative;
}
.hk-task {
  position: relative;
  padding: clamp(10px, 1cqw, 14px) clamp(12px, 1.2cqw, 16px);
  gap: clamp(4px, 0.5cqh, 8px);
}
.hk-task .cmd-task-header { padding: 0; border-bottom: 0; }
.hk-task .cmd-task-msg { font-size: clamp(12px, 0.9cqw, 14px); line-height: 1.42; }
/* Connector between the prompt plate and the first task, plus between tasks */
.hk-plate + .hk-tasks::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(-1 * clamp(8px, 1cqh, 14px));
  width: 1px;
  height: clamp(8px, 1cqh, 14px);
  background: var(--border-strong);
  transform: translateX(-50%);
}
.hk-task:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: calc(-1 * clamp(8px, 1cqh, 14px));
  width: 1px;
  height: clamp(8px, 1cqh, 14px);
  background: var(--border-strong);
  transform: translateX(-50%);
}

/* ── Right-column demo: typewriter, sonar pulse, cascading tasks ──────────
   The slide plays a non-interactive demo when it activates. JS clears the
   input text, types it back letter by letter, pulses the send button, then
   reveals each task as Active (blinking dot) → Complete in sequence. CSS
   here owns the animations; housekeeping-demo.js owns the orchestration. */

/* Once JS attaches .is-demo to the slide, the static text is replaced by a
   live-typed <span> (.cmd-text-typed) followed by a blinking caret. Hide
   any whitespace-only text nodes so they don't push the caret right. */
.slide-housekeeping.is-demo .cmd-text {
  display: inline-flex;
  align-items: center;
  min-height: 1.2em;
}
.cmd-text-typed {
  white-space: pre;
}
.cmd-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 2px;
  background: var(--accent-bright);
  vertical-align: -0.12em;
  animation: hk-caret-blink 900ms steps(2, end) infinite;
}
.cmd-caret.is-hidden { display: none; }
@keyframes hk-caret-blink {
  0%, 50%   { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* Send button sonar — concentric ring pulses outward from the button once
   the prompt is fully typed, signaling "ready to fire". */
.slide-housekeeping .cmd-send { position: relative; }
.slide-housekeeping .cmd-send.is-sonar::before,
.slide-housekeeping .cmd-send.is-sonar::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 8px;
  border: 1.5px solid var(--accent-bright);
  pointer-events: none;
  animation: hk-sonar 1.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
.slide-housekeeping .cmd-send.is-sonar::after {
  animation-delay: 0.7s;
}
@keyframes hk-sonar {
  0%   { transform: scale(1);    opacity: 0.85; }
  100% { transform: scale(1.55); opacity: 0;    }
}

/* Tasks hidden by default while the demo is staged; revealed one at a time
   by JS adding .is-shown. No-JS fallback below restores them. */
.slide-housekeeping.is-demo .hk-task {
  opacity: 0;
  transform: translateY(6px);
  transition:
    opacity 320ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 320ms cubic-bezier(0.16, 1, 0.3, 1),
    border-color 420ms ease-out,
    box-shadow 420ms ease-out;
}
.slide-housekeeping.is-demo .hk-task.is-shown {
  opacity: 1;
  transform: translateY(0);
}

/* Glowing white border on whichever task is currently the cascade focus
   (typewriter streaming, dot pulsing). When the next task gets
   .is-cascade-active, this class is removed from the previous one and the
   transition above fades the glow out — so the focus visibly hands off. */
.slide-housekeeping .hk-task.is-cascade-active {
  border-color: rgba(255, 255, 255, 0.32);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.10),
    0 0 18px -4px rgba(255, 255, 255, 0.22),
    0 0 36px -10px rgba(255, 255, 255, 0.14);
}

/* Dot pulse while a task is the "currently active" one in the cascade.
   Strong, fast — signals "just activated". Sits on top of the existing
   .status-active green base color. */
.slide-housekeeping .hk-task.is-cascade-active .cmd-task-status .dot {
  animation: hk-dot-pulse 1s ease-in-out infinite;
  box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.7);
}
@keyframes hk-dot-pulse {
  0%, 100% { box-shadow: 0 0 0 0   rgba(74, 222, 128, 0.55); opacity: 1;   }
  60%      { box-shadow: 0 0 0 6px rgba(74, 222, 128, 0);    opacity: 0.4; }
}

/* Steady-state "still running" pulse on every Active dot once the cascade
   has finished. Softer + slower than the cascade pulse. Each task gets a
   slightly different duration and negative delay so the four ambient
   dots breathe out of phase with each other — telegraphs "these are all
   independently doing their thing" rather than marching in lockstep. */
.slide-housekeeping .hk-task:not(.is-cascade-active) .cmd-task-status.status-active .dot {
  animation: hk-dot-pulse-soft 2.0s ease-in-out infinite;
}
.slide-housekeeping .hk-task:nth-child(1) .cmd-task-status.status-active .dot { animation-duration: 1.85s; animation-delay: -0.25s; }
.slide-housekeeping .hk-task:nth-child(2) .cmd-task-status.status-active .dot { animation-duration: 2.15s; animation-delay: -0.95s; }
.slide-housekeeping .hk-task:nth-child(3) .cmd-task-status.status-active .dot { animation-duration: 2.40s; animation-delay: -1.55s; }
.slide-housekeeping .hk-task:nth-child(4) .cmd-task-status.status-active .dot { animation-duration: 1.95s; animation-delay: -0.55s; }
.slide-housekeeping .hk-task:nth-child(5) .cmd-task-status.status-active .dot { animation-duration: 2.25s; animation-delay: -1.20s; }
@keyframes hk-dot-pulse-soft {
  0%, 100% { box-shadow: 0 0 0 0   rgba(74, 222, 128, 0.45); transform: scale(1);    opacity: 1;    }
  55%      { box-shadow: 0 0 0 4px rgba(74, 222, 128, 0);    transform: scale(1.10); opacity: 0.35; }
}

/* Reduced-motion: skip the demo entirely. JS adds .is-demo only when
   motion is allowed, so this rule is a belt-and-braces safety net. */
@media (prefers-reduced-motion: reduce) {
  .slide-housekeeping.is-demo .hk-task { opacity: 1; transform: none; }
  .cmd-caret { animation: none; opacity: 0; }
  .slide-housekeeping .cmd-send.is-sonar::before,
  .slide-housekeeping .cmd-send.is-sonar::after { animation: none; opacity: 0; }
  .slide-housekeeping .hk-task.is-cascade-active .cmd-task-status .dot,
  .slide-housekeeping .hk-task:not(.is-cascade-active) .cmd-task-status.status-active .dot {
    animation: none;
  }
  .slide-housekeeping .hk-task.is-cascade-active {
    border-color: inherit;
    box-shadow: none;
  }
}

/* -------- Slide 27: Citations / sources -------------------------------- */
.slide-citations {
  justify-content: flex-start;
  gap: clamp(14px, 1.6cqw, 22px);
}
.citations-headline {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(26px, 2.4cqw, 36px);
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--text);
  margin: 0;
  max-width: 22ch;
}
.citations-list {
  list-style: none;
  margin: clamp(8px, 1cqw, 14px) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.25cqw, 18px);
  width: 100%;
  max-width: 1380px;
}
.citation-row {
  display: grid;
  grid-template-columns: clamp(40px, 3.2cqw, 52px) 1fr;
  gap: clamp(14px, 1.4cqw, 20px);
  padding-top: clamp(11px, 1.1cqw, 16px);
  border-top: 1px solid var(--border-soft);
}
/* Per-slide section header — groups citations by source slide so the
   appendix reads "Slide 04 → its citations, Slide 06 → its citations".
   Border-top is heavier than the row separator to anchor the group. */
.citation-section {
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: clamp(12px, 1.1cqw, 18px);
  padding-top: clamp(12px, 1.3cqw, 18px);
  margin-top: clamp(4px, 0.5cqw, 8px);
  border-top: 1px solid var(--border-strong);
}
.citation-section:first-child {
  padding-top: 0;
  margin-top: 0;
  border-top: none;
}
.citation-section-num {
  font-family: var(--font-mono);
  font-size: clamp(14px, 1.1cqw, 17px);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.citation-section-title {
  font-family: var(--font-mono);
  font-size: clamp(12px, 0.95cqw, 15px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-soft);
}
/* The first citation under a section header doesn't need its own
   divider line — the section header above already separates it. */
.citation-section + .citation-row {
  border-top: none;
  padding-top: clamp(8px, 0.9cqw, 12px);
}
.citation-marker {
  font-family: var(--font-mono);
  font-size: clamp(18px, 1.55cqw, 22px);
  letter-spacing: 0.04em;
  color: var(--text);
  line-height: 1;
  padding-top: 4px;
}
.citation-body {
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.65cqw, 10px);
  min-width: 0;
}
.citation-claim {
  font-family: var(--font-display);
  font-size: clamp(17px, 1.4cqw, 22px);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.22;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: clamp(8px, 0.8cqw, 12px);
  flex-wrap: wrap;
}
.citation-stat {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 1.15em;
  letter-spacing: -0.04em;
  color: var(--accent-bright);
  font-variant-numeric: tabular-nums;
}
.citation-method {
  font-family: var(--font-mono);
  font-size: clamp(12px, 0.88cqw, 14.5px);
  line-height: 1.55;
  color: var(--text-soft);
  margin: 0;
  padding: 8px 12px;
  background: rgba(244,245,248,0.04);
  border-left: 2px solid var(--accent-bright);
  border-radius: 2px;
  max-width: 100%;
}
.citation-method strong {
  color: var(--text);
  font-weight: 500;
}
.citation-sources {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 0.55cqw, 8px);
}
.citation-sources li {
  font-family: var(--font-display);
  font-size: clamp(13.5px, 1.02cqw, 16px);
  line-height: 1.5;
  color: var(--text-soft);
  max-width: 100%;
}
.citation-sources li strong {
  color: var(--text);
  font-weight: 500;
}
.citation-sources li em {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-style: normal;
  color: var(--text-soft);
  letter-spacing: 0.02em;
}
.citation-sources .cite-link {
  color: var(--text-soft);
  text-decoration: underline;
  text-decoration-color: rgba(110, 123, 230, 0.35);
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: color 120ms ease, text-decoration-color 120ms ease;
}
.citation-sources .cite-link:hover,
.citation-sources .cite-link:focus-visible {
  color: var(--accent-bright);
  text-decoration-color: var(--accent-bright);
}
.cite-tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.78em;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-right: 8px;
  padding: 2px 7px;
  border: 1px solid rgba(244,245,248,0.16);
  border-radius: 3px;
  vertical-align: 1px;
}

/* -------- Slide 18: Competition table ---------------------------------- */
.slide-comp {
  display: flex; flex-direction: column;
  gap: clamp(28px, 3cqw, 44px);
  justify-content: center;
}
.comp-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-32);
  letter-spacing: -0.02em;
  color: var(--text);
}
.comp-headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.01em;
}
.comp-table-wrap {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-elev);
}
.comp-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-display);
  font-size: var(--t-13);
}
.comp-table thead th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: var(--t-11);
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 14px 18px;
  background: var(--bg-elev-2);
  border-bottom: 1px solid var(--border);
}
.comp-table tbody td {
  padding: 16px 18px;
  border-bottom: 1px solid var(--border-soft);
  color: var(--text-soft);
  vertical-align: top;
  line-height: 1.5;
}
.comp-table tbody tr:last-child td { border-bottom: none; }
.comp-table tbody tr:hover td { background: rgba(255,255,255,0.012); }
.comp-table .col-cat { color: var(--text); font-weight: 500; }
.comp-table .col-players { color: var(--text-soft); font-family: var(--font-mono); font-size: 12px; }
.comp-table .col-funding { color: var(--text-muted); font-family: var(--font-mono); font-size: 12px; }
.comp-table .threat {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 4px;
  border: 1px solid;
  white-space: nowrap;
}
.threat.high      { color: var(--danger);  border-color: rgba(239, 68, 68, 0.3);  background: rgba(239, 68, 68, 0.06); }
.threat.med-high  { color: var(--warn);    border-color: rgba(245, 158, 11, 0.3); background: rgba(245, 158, 11, 0.06); }
.threat.med       { color: var(--warn);    border-color: rgba(245, 158, 11, 0.2); background: rgba(245, 158, 11, 0.04); }
.threat.med-low   { color: #C5E8B7;        border-color: rgba(74, 222, 128, 0.25); background: rgba(74, 222, 128, 0.05); }
.threat.low       { color: var(--success); border-color: rgba(74, 222, 128, 0.3);  background: rgba(74, 222, 128, 0.06); }

/* -------- Unified slide title ------------------------------------------- */
/* Every slide's H2 matches slide 8 (.flow-headline). Stays on one line at
   desktop widths; if the viewport is too narrow only the words that don't
   fit overflow to the next line (standard wrap, not balanced). Declared at
   end of file so it wins source order over the per-slide classes above. */
.team-headline,
.traction-headline,
.flow-headline,
.us-headline,
.global-headline,
.tri-headline,
.risks-headline,
.gtm-headline,
.roadmap-headline,
.stats-headline,
.comp-headline,
.slide-head .headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-40);
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--text);
  max-width: none;
  white-space: normal;
  text-wrap: wrap;
  margin-top: 8px;
  margin-bottom: 0;
}


/* Traction headline carries italic emphasis on a single line. */
.traction-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  color: var(--accent-bright);
  letter-spacing: -0.005em;
}

/* -------- Slides 21 & 22: Style guide ---------------------------------
   These two slides are designed AS specimens — every type sample is
   rendered in its production style, every color tile is the actual hue
   in the actual size it lives at. The goal: a designer should be able
   to recognise the system on sight and reproduce it from this page. */

.slide-style {
  display: flex;
  flex-direction: column;
}
.slide-style .headline {
  max-width: none;
}
.slide-style .headline .em {
  color: var(--accent-bright);
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  letter-spacing: -0.005em;
}

/* ============================ Slide 21: Color =========================== */
/* Hero row of four large color tiles, then a single text-tier strip below.
   Generous breathing room — the tiles are the slide. */
.slide-style-color .color-tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(20px, 2.4cqw, 36px);
  margin-top: clamp(28px, 3.4cqh, 48px);
  flex: 1;
  min-height: 0;
}
.slide-style-color .color-tile {
  display: flex;
  flex-direction: column;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  min-height: 0;
}
.slide-style-color .color-tile-fill {
  height: clamp(120px, 18cqh, 200px);
  flex-shrink: 0;
  position: relative;
}
.slide-style-color .color-tile-fill--energy {
  background: radial-gradient(ellipse 65% 60% at 50% 50%,
    rgba(255,255,255,0.85) 0%,
    rgba(255,255,255,0.4) 25%,
    rgba(255,255,255,0.12) 50%,
    rgba(255,255,255,0.02) 75%,
    transparent 100%);
}
.slide-style-color .color-tile-meta {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1cqh, 12px);
  padding: clamp(18px, 2cqw, 28px) clamp(20px, 2.2cqw, 30px);
  flex: 1;
  min-height: 0;
}
.slide-style-color .color-tile-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.slide-style-color .color-tile-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 1.8cqw, 26px);
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0;
}
.slide-style-color .color-tile-rule {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-13);
  line-height: 1.5;
  color: var(--text-soft);
  margin: 0;
  flex: 1;
}
.slide-style-color .color-tile-rule code,
.slide-style-color .color-tile-rule em {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-style: normal;
  color: var(--text);
  background: rgba(255,255,255,0.04);
  padding: 0 5px;
  border-radius: 3px;
}
.slide-style-color .color-tile-rule em {
  background: transparent;
  font-family: var(--font-serif);
  font-style: italic;
}
.slide-style-color .color-tile-tokens {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: clamp(6px, 0.8cqh, 12px);
  margin-top: auto;
  border-top: 1px solid var(--border);
}
.slide-style-color .color-tile-tokens code {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--accent-bright);
  letter-spacing: 0;
  background: none;
  padding: 0;
}
.slide-style-color .color-tile-hex {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

/* Text-tier strip below the color tiles — the real grays in real type. */
.color-text-tiers {
  margin-top: clamp(20px, 2.6cqh, 36px);
  padding-top: clamp(14px, 1.6cqh, 22px);
  border-top: 1px solid var(--border);
}
.color-tier-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-bottom: clamp(10px, 1.2cqh, 14px);
}
.color-tier-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(14px, 1.8cqw, 28px);
}
.color-tier {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.color-tier-sample {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 2cqw, 26px);
  letter-spacing: -0.015em;
}
.color-tier code {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-soft);
}
.color-tier-hex {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

/* ============================ Slide 22: Type ============================ */
/* Three voices in a manifesto strip, then specimen rows where the LEFT
   shows the actual style at production size and the RIGHT names it. */
.slide-style-type .type-voices {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 2.4cqw, 36px);
  margin-top: clamp(16px, 2.2cqh, 28px);
  padding: clamp(14px, 1.8cqh, 22px) clamp(22px, 2.2cqw, 32px);
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-elev);
}
.slide-style-type .type-voice {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.slide-style-type .type-voice-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.slide-style-type .type-voice-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 2.6cqw, 34px);
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--text);
}
.slide-style-type .type-voice-role {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

/* Spec rows: left rail = the actual sample in actual style, right rail =
   the spec line + designer note. The dashed rule between rows reads as
   spec-sheet, not as a list. */
.slide-style-type .type-specs {
  list-style: none;
  margin: clamp(14px, 1.8cqh, 24px) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
.slide-style-type .type-spec-row {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: clamp(24px, 3cqw, 56px);
  align-items: baseline;
  padding: clamp(6px, 0.9cqh, 12px) 0;
  border-bottom: 1px dashed rgba(255,255,255,0.08);
}
.slide-style-type .type-spec-row:last-child { border-bottom: none; }
.slide-style-type .type-spec-row--stat { align-items: center; }

.slide-style-type .type-spec-side {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.slide-style-type .type-spec-name {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.slide-style-type .type-spec-line {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-muted);
  letter-spacing: 0.02em;
  line-height: 1.5;
}
.slide-style-type .type-spec-line code {
  color: var(--text-soft);
  background: rgba(255,255,255,0.05);
  padding: 0 5px;
  border-radius: 3px;
}
.slide-style-type .type-spec-rule {
  font-family: var(--font-display);
  font-weight: 400;
  font-style: italic;
  font-size: var(--t-13);
  line-height: 1.5;
  color: var(--text-dim);
}
.slide-style-type .type-spec-rule em,
.slide-style-type .type-spec-rule code {
  font-style: normal;
  color: var(--text-soft);
}
.slide-style-type .type-spec-rule code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: rgba(255,255,255,0.05);
  padding: 0 4px;
  border-radius: 3px;
}

/* The actual production styles, rendered as samples. */
.type-sample--kicker {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.type-sample--headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 2.2cqw, 30px);
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--text);
}
.type-sample--claim {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(22px, 2.2cqw, 30px);
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: var(--text);
}
.type-sample--claim em {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.005em;
}
.type-sample--stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
.type-sample--stat .stat-num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: clamp(26px, 2.6cqw, 36px);
  line-height: 1;
  letter-spacing: -0.03em;
  color: #FFFFFF;
}
.type-sample--stat .stat-lbl {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #FFFFFF;
}
.type-sample--body {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-15);
  line-height: 1.55;
  color: var(--text-soft);
  max-width: 48ch;
}
.type-sample--inprose {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 2cqw, 26px);
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--text);
}
.type-sample--inprose .ip-em {
  font-family: var(--font-mono);
  font-size: 0.85em;
  color: var(--accent-bright);
  padding: 0 0.04em;
}
.type-sample--fine {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.04em;
  color: var(--text-dim);
}


/* =================================================================
   MOBILE PORTRAIT  (≤ 768px wide AND portrait orientation)
   -----------------------------------------------------------------
   Each slide is a fixed full-viewport page. Touch swipe up/down
   advances/retreats one slide via the same go(n) used by desktop;
   the active slide gets .is-active and runs its choreography.
   No page-level scroll — slides that need more room get an inner
   `.slide-scroll` container that scrolls within the slide.

   Landscape phones get desktop content layout but the same mobile
   architecture (fixed slides + swipe), defined in its own block at
   the bottom of this file. The orientation:portrait clause keeps
   the portrait single-column overrides from leaking into a small
   landscape phone (which also has max-width < 768).
   ================================================================= */
@media (max-width: 768px) and (orientation: portrait) {

  /* Lock the page — no body scroll. The deck sizes the viewport. */
  html, body {
    overflow: hidden;
    height: 100%;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: none;
  }
  body {
    font-size: 15px;
  }

  /* Deck IS the viewport. Slides absolute-position over each other,
     identical to desktop — only the .is-active slide is visible. */
  #deck {
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    position: fixed;
    inset: 0;
    overflow: hidden;
    z-index: 2;
    background: transparent;
  }

  /* Desktop letterbox stage collapses on portrait phones — the existing
     mobile layouts take over via the rules below. */
  .stage {
    position: static;
    top: auto; left: auto;
    width: 100%;
    height: 100%;
    transform: none;
    container-type: normal;
    overflow: visible;
    background: transparent;
  }

  .slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    /* Tight top: brand logo is ~36px including its 14px top offset.
       The headline can sit just below it. Bottom padding is small —
       there's no nav chrome on mobile. */
    padding: 30px clamp(16px, 4vw, 24px) 20px;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    gap: clamp(14px, 4vw, 22px);
    /* Slide visibility is driven by .is-active (set by go() in main.js).
       Inactive slides are display:none so they don't intercept taps. */
  }

  .slide:not(.is-active) {
    display: none !important;
  }

  .slide.is-active {
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
    transition: none !important;
  }

  /* Reveal staging is moot — every visible slide is "settled". */
  .slide .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  /* Hide kickers entirely on portrait mobile — title gets the space. */
  .slide .kicker { display: none !important; }

  /* Pause expensive infinite animations on inactive slides only.
     The base "pause on inactive" rule still works; on mobile, slides
     are flagged is-active by IntersectionObserver as they enter view. */

  /* ---- Chrome -------------------------------------------------- */
  .nav,
  .progress,
  .help,
  .footer-meta { display: none !important; }

  .brand {
    position: fixed;
    top: 14px;
    right: 14px;
    z-index: 10;
  }
  .brand-logo { height: 22px; }

  /* ---- Headlines ----------------------------------------------- */
  .traction-v2-headline,
  .traction-v2-headline--single,
  .pipeline-headline-plain,
  .us-headline,
  .crisis-verdict,
  .crisis-headline,
  .tri-headline,
  .roadmap-headline,
  .stats-headline,
  .comp-headline,
  .moat-headline,
  .gtm-headline,
  .flow-headline,
  .global-headline,
  .traction-headline,
  .what-headline,
  .insight-headline,
  .why-headline,
  .risks-headline,
  .pro-forma-headline,
  .why-full-headline,
  .close-headline,
  .headline {
    white-space: normal !important;
    max-width: 100% !important;
    text-wrap: balance;
    font-size: clamp(22px, 6.6vw, 30px);
    line-height: 1.18;
  }

  .slide-cover .cover-headline,
  .slide-cover h1.headline {
    font-size: clamp(34px, 9vw, 48px);
    max-width: 100% !important;
    white-space: normal !important;
  }

  /* ---- Multi-col grids → 1 col --------------------------------- */
  .v2-split,
  .proof-split,
  .v2-chart-pair,
  .pipeline-stack,
  .traction-split,
  .crisis-forces,
  .why-split,
  .team-grid,
  .global-stage,
  .day-log-row,
  .v2-grid,
  .style-grid,
  .color-tiles,
  .type-voices,
  .color-tier-row,
  .tri-row,
  .moat-grid,
  .insight-stack,
  .insight-cols,
  .traction-projections,
  .traction-supporting {
    display: flex !important;
    flex-direction: column !important;
    grid-template-columns: 1fr !important;
    gap: clamp(14px, 4vw, 22px) !important;
  }

  .slide-style-type .type-spec-row {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
  }

  /* ---- Slide 4 (Why now / crisis): compact so 3 stats + verdict all
     fit within 100svh on phones. Numbers shrink, gaps tighten. */
  .slide-tri .crisis-forces {
    gap: 14px !important;
  }
  .slide-tri .crisis-force {
    padding: 14px 0 0 !important;
    gap: 4px !important;
  }
  .slide-tri .crisis-stat {
    margin: 2px 0 !important;
  }
  .slide-tri .crisis-stat-num {
    font-size: 44px !important;
  }
  .slide-tri .crisis-label {
    font-size: 18px !important;
  }
  .slide-tri .crisis-verdict {
    font-size: clamp(16px, 4.4vw, 20px) !important;
    margin-top: 14px !important;
    line-height: 1.3 !important;
  }

  /* ---- Slide 8 (Pipeline): smaller pipeline headline, less gap
     between traction-headline and ARR chart. */
  .slide-traction-pipeline .traction-v2-headline {
    margin-bottom: 4px !important;
  }
  .slide-traction-pipeline .pipeline-stack {
    gap: 14px !important;
  }
  .slide-traction-pipeline .pipeline-block + .pipeline-block { margin-top: 0; }
  .slide-traction-pipeline .pipeline-headline-plain {
    font-size: 13.5px !important;
    line-height: 1.35 !important;
  }
  .slide-traction-pipeline .pipeline-fine {
    display: none !important;
  }
  .slide-traction-pipeline .pipeline-block-head {
    gap: 4px !important;
  }

  /* ---- Slide 16 (Risks & rebuttals): tighter body so 3 long
     objections fit within 100svh. */
  .slide-risks .risks-list { gap: 8px !important; }
  .slide-risks .risk-row {
    padding-top: 8px !important;
    gap: 0 !important;
    grid-template-columns: 1fr !important;
  }
  .slide-risks .risk-quote { display: none !important; }
  .slide-risks .risk-objection {
    font-size: 13.5px !important;
    line-height: 1.2 !important;
  }
  .slide-risks .risk-rebuttal {
    font-size: 11.5px !important;
    line-height: 1.32 !important;
  }
  .slide-risks .risk-content { gap: 3px !important; }
  .slide-risks .risks-headline {
    margin-bottom: 8px !important;
  }

  /* ---- Slide 18 (Stats): tighten body + citations so 3 long stats
     fit. */
  .slide-stats .stats-list { gap: 10px !important; }
  .slide-stats .stat-row,
  .slide-stats .stat-item { padding: 8px 0 !important; gap: 8px !important; }
  .slide-stats .stat-body,
  .slide-stats p { font-size: 12.5px !important; line-height: 1.4 !important; }
  .slide-stats .citations {
    font-size: 9px !important;
    line-height: 1.4 !important;
    padding-top: 8px !important;
  }
  .slide-stats .stats-headline {
    margin-bottom: 6px !important;
  }

  /* ---- Slide 12 (Land and expand): keep three isometric figures in a
     row on mobile (compressed) instead of stacking — stacking made the
     slide ~3× viewport tall. */
  .slide-gtm .gtm-stage {
    display: grid !important;
    grid-template-columns: 1fr 1fr 1fr !important;
    gap: 6px !important;
    align-items: end;
    align-content: center;
    padding: 4px 0 !important;
  }
  .slide-gtm .gtm-fig { gap: 8px !important; }
  .slide-gtm .gtm-fig-img,
  .slide-gtm .gtm-fig:nth-child(3) .gtm-fig-img {
    max-width: 100% !important;
    width: 100% !important;
  }
  .slide-gtm .gtm-caption {
    width: 100%;
    max-width: none;
    padding-top: 8px;
  }
  .slide-gtm .gtm-caption-acv { font-size: 18px !important; }
  .slide-gtm .gtm-caption-label { font-size: 12px !important; }
  .slide-gtm .gtm-caption-sub {
    font-size: 8.5px !important;
    letter-spacing: 0.06em !important;
  }
  /* Stack the two fragments on separate lines and hide the dot
     separator on mobile, so all three columns share the same height. */
  .slide-gtm .gtm-caption-sub {
    display: flex !important;
    flex-direction: column !important;
    gap: 1px;
    align-items: center;
  }
  .slide-gtm .gtm-caption-sub > span { white-space: nowrap; }
  .slide-gtm .gtm-caption-sub > .sep { display: none !important; }
  .slide-gtm .gtm-assumptions {
    font-size: 9px !important;
    letter-spacing: 0.1em !important;
  }

  /* ---- Slide 9 (Tempo Automates / flow): make the flow-stage flex-grow
     into the slide (instead of forcing 100% min-height that pushed the
     meter off-screen). Slide is fixed 100svh; stage takes whatever's
     left after headline + meter. */
  .slide-flow .flow-stage {
    flex: 1 1 auto !important;
    min-height: 0 !important;
  }
  .slide-flow .flow-meter {
    flex: 0 0 auto !important;
    margin-top: 12px !important;
    padding-top: 10px !important;
    border-top: 1px solid var(--border-soft);
  }
  .slide-flow .meter-fine {
    display: none !important;
  }

  /* ---- W Hotels proof slide: full-bleed image with logo + claim
     overlaid on it. Stats sit underneath. */
  .slide-traction-proof .proof-split {
    position: relative !important;
    flex: 1 1 auto;
    display: flex !important;
    flex-direction: column !important;
    gap: 14px !important;
    min-height: 0;
  }
  /* Image fills the space below the headline; logo + claim overlay it. */
  .slide-traction-proof .proof-media {
    position: relative !important;
    width: 100%;
    flex: 1 1 auto;
    min-height: 0;
    border-radius: 14px;
    overflow: hidden;
  }
  /* Fade ramps from clear at the top to nearly opaque at the bottom so
     the claim sits on a deep, legible background. Starts higher (8%)
     and ramps faster so the lower third is fully dark. */
  .slide-traction-proof .proof-media::after {
    content: "";
    position: absolute; inset: 0;
    pointer-events: none;
    background:
      linear-gradient(180deg,
        rgba(8, 9, 10, 0) 8%,
        rgba(8, 9, 10, 0.55) 46%,
        rgba(8, 9, 10, 0.96) 100%);
  }
  /* proof-text overlays the image area only (matches proof-media bounds
     by being absolutely-positioned to its sibling via the proof-split
     containing block — see grid-area reset below). */
  .slide-traction-proof .proof-text {
    position: absolute !important;
    left: 0 !important;
    right: 0 !important;
    top: 0 !important;
    bottom: 0 !important;
    padding: 16px 18px 22px !important;
    display: grid !important;
    grid-template-rows: auto 1fr auto auto !important;
    z-index: 2;
    gap: 0 !important;
    pointer-events: none;
  }
  .slide-traction-proof .proof-text > * { pointer-events: auto; }
  .slide-traction-proof .proof-text > .proof-logo { display: none !important; }
  .slide-traction-proof .proof-text > .proof-stats { grid-row: 3; }
  .slide-traction-proof .proof-text > .proof-claim { grid-row: 4; align-self: end; padding-top: 12px; }
  .slide-traction-proof .proof-logo {
    height: 28px !important;
    align-self: flex-start;
    margin: 0 !important;
    filter: brightness(0) invert(1);
    opacity: 1;
  }
  .slide-traction-proof .proof-claim {
    font-size: clamp(26px, 7.6vw, 38px) !important;
    line-height: 1.08 !important;
    max-width: 14ch !important;
    color: #FFFFFF !important;
    margin: 0 !important;
  }
  .slide-traction-proof .proof-body {
    display: none;
  }
  .slide-traction-proof .proof-stats {
    display: grid !important;
    grid-template-columns: 1fr 1fr 1fr !important;
    gap: 10px !important;
    padding: 0 !important;
    align-self: end;
  }
  .slide-traction-proof .proof-stat { gap: 0; }
  .slide-traction-proof .proof-stat-divider { display: none !important; }
  .slide-traction-proof .proof-num {
    font-size: clamp(18px, 5.4vw, 24px) !important;
    color: #FFFFFF !important;
    line-height: 1.05;
  }
  .slide-traction-proof .proof-lbl {
    font-size: 9.5px !important;
    line-height: 1.3;
    color: rgba(255, 255, 255, 0.72) !important;
    letter-spacing: 0.08em;
  }

  /* ---- Touch targets ------------------------------------------- */
  .cmd-icon { width: 36px !important; height: 36px !important; }
  .cmd-send { height: 36px !important; padding: 0 8px !important; }
  .flow-row .cmd-icon { width: 30px !important; height: 30px !important; }
  .flow-row .cmd-send { height: 30px !important; }

  /* ---- Wide tables get horizontal scroll ----------------------- */
  .comp-table-wrap,
  .proforma-wrap {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  /* Wider so "How Tempo wins" body text doesn't wrap line-by-line and
     make every row absurdly tall. The table scrolls horizontally on
     mobile anyway, so trading a wider table for shorter rows is fine. */
  .comp-table { min-width: 1020px; }
  .comp-table tbody td:nth-child(5),
  .comp-table thead th:nth-child(5) { width: 420px; min-width: 420px; }
  .proforma-table { min-width: 600px; }

  /* ---- Slide 9 product flow: chat-style. The first prompt sits roughly
     centered in the viewport. Tapping send dispatches the row's task
     cards, which appear below the plate and push it up. The next prompt
     appears below the completed cards. The slide grows tall and the
     user free-scrolls within it. */
  /* Slide is a fixed-height swipe page. The chat scrolls within it.
     Old rows fade out behind a top mask as new ones come in. */
  .slide-flow .flow-stage {
    position: relative !important;
    display: flex !important;
    flex-direction: column;
    justify-content: flex-end; /* anchor newest row to bottom */
    gap: 18px;
    min-height: 100%;
    padding: 0 0 16px;
    margin-bottom: 0 !important; /* desktop margin-bottom would shrink the
                                     stage on mobile where the slide scrolls */
    overflow: visible !important; /* desktop overflow-y: auto is wrong here —
                                     on mobile the slide is the scroller */
    width: 100%;
    /* Top fade so old rows pushed up disappear behind the page bg. */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,0.15) 8%, black 24%, black 100%);
            mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,0.15) 8%, black 24%, black 100%);
  }
  /* Hide the desktop spacer pseudo-element — mobile uses justify-content:
     flex-end (which works here because the SLIDE is the scroller, not the
     stage, so the bug doesn't apply). */
  .slide-flow .flow-stage::before { display: none !important; }
  .slide-flow .flow-row {
    position: relative !important;
    inset: auto !important;
    grid-template-columns: 1fr !important;
    gap: 12px !important;
    display: flex !important;
    flex-direction: column !important;
    opacity: 1 !important;
    pointer-events: auto !important;
    transition: opacity 400ms ease, transform 400ms ease;
  }
  /* Hidden rows collapse + fade + drop down by 16px so the awaiting
     row visibly slides UP into view rather than popping. */
  .slide-flow .flow-row {
    transition:
      max-height 480ms cubic-bezier(0.16, 1, 0.3, 1),
      opacity 320ms ease-out,
      transform 480ms cubic-bezier(0.16, 1, 0.3, 1) !important;
  }
  .slide-flow .flow-row[data-state="hidden"] {
    max-height: 0 !important;
    opacity: 0 !important;
    pointer-events: none !important;
    transform: translateY(16px);
    margin-top: 0 !important;
  }
  .slide-flow .flow-row[data-state="awaiting"],
  .slide-flow .flow-row[data-state="dispatching"],
  .slide-flow .flow-row[data-state="complete"] {
    transform: translateY(0);
  }
  /* Once a row is dimmed (a newer row has taken over), fade it out
     entirely so it disappears behind the top gradient mask. The mask
     does the rest as it scrolls upward. */
  .slide-flow .flow-row.is-dimmed {
    opacity: 0.32 !important;
  }
  .slide-flow .cmd-branch,
  .slide-flow .flow-branch { display: none !important; }
  .slide-flow .cmd-outputs {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
  }
  .slide-flow .cmd-plate { max-width: none !important; }
  .slide-flow .cmd-task { padding: 10px 12px !important; }
  .slide-flow .flow-meter {
    position: relative !important;
    bottom: auto !important;
    width: 100% !important;
    max-width: none !important;
    grid-template-columns: 1fr 1fr 1fr !important;
    gap: 12px !important;
    margin-top: 24px;
  }
  .slide-flow .meter-fine {
    grid-column: 1 / -1;
    font-size: 10px !important;
    line-height: 1.4 !important;
  }

  /* ---- Style guide slides are internal design refs, not deck content. */
  .slide-style { display: none !important; }

  /* ---- Slide 13 roadmap: vertical timeline. Single continuous left
     line with a pulse traveling top→bottom, dots at each milestone,
     SEED pill at the end that lights up when the pulse arrives. */
  .slide-roadmap .roadmap {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    padding: 0 0 56px 0 !important;
    margin-top: 8px;
    position: relative;
    grid-template-rows: none !important;
    flex: 1 1 auto;
  }
  .slide-roadmap .roadmap-milestone {
    padding: 2px 0 2px 22px !important;
  }
  .slide-roadmap .roadmap-milestone .when {
    font-size: 10px !important;
    letter-spacing: 0.12em;
  }
  .slide-roadmap .roadmap-milestone .what {
    font-size: 13.5px !important;
    line-height: 1.2;
  }
  .slide-roadmap .roadmap-milestone .detail {
    font-size: 12px !important;
    line-height: 1.35 !important;
  }
  .slide-roadmap .roadmap-row {
    display: contents;
    transform: none !important;
  }
  /* Repurpose the desktop center-line container as a vertical line on
     the left, anchored to the roadmap container. Pulse + SEED stay as
     children so their existing animations carry over. */
  .slide-roadmap .roadmap-line {
    display: block !important;
    position: absolute !important;
    left: 0 !important;
    top: 4px;
    bottom: 36px; /* ends where SEED begins so the pulse lands on it */
    width: 1px !important;
    height: auto !important;
    background: var(--border-strong) !important;
    align-self: auto !important;
    transform: none !important;
    overflow: visible !important;
    margin: 0 !important;
    z-index: 1;
  }
  /* Pulse runs along the vertical line (top → bottom). */
  .slide-roadmap .roadmap-pulse {
    position: absolute !important;
    left: 0 !important;
    top: 0;
    width: 8px !important;
    height: 14px !important;
    transform: translate(-50%, 0) !important;
    animation: roadmap-pulse-vertical 3.2s cubic-bezier(0.42, 0, 1, 1) infinite !important;
  }
  /* Spend pills along the desktop track don't translate vertically;
     hide them on mobile to keep the chrome quiet. */
  .slide-roadmap .roadmap-spend { display: none !important; }
  /* SEED pill anchored at the bottom of the timeline, centered against
     the full slide width. (main.js moves it out of .roadmap-line on
     mobile so its absolute positioning is relative to .roadmap.) */
  /* SEED pill is left-justified so its left edge sits on the vertical
     line. The line bottom matches the pill's top edge so the travelling
     pulse arrives directly at the pill. */
  .slide-roadmap .roadmap-final {
    position: absolute !important;
    left: 0 !important;
    transform: none !important;
    top: auto !important;
    bottom: 0 !important;
  }
  /* Milestones stack to the right of the line. Top + bottom rows
     interleave chronologically via `order`. */
  .slide-roadmap .roadmap-milestone {
    position: relative !important;
    width: 100% !important;
    height: auto !important;
    background: none !important;
    left: auto !important;
    bottom: auto !important;
    top: auto !important;
    padding: 4px 0 4px 22px;
    border-left: none;
  }
  .slide-roadmap .roadmap-milestone .content {
    position: relative !important;
    left: 0 !important;
    width: 100% !important;
    top: 0 !important;
    bottom: 0 !important;
    gap: 4px;
  }
  .slide-roadmap .roadmap-milestone .dot {
    position: absolute !important;
    top: 10px !important;
    bottom: auto !important;
    left: -4px !important;
    width: 8px !important;
    height: 8px !important;
    z-index: 2;
  }
  /* Chronological interleave: top1, bottom1, top2, bottom2, … */
  .slide-roadmap .roadmap-row.top    .roadmap-milestone:nth-child(1) { order: 1; }
  .slide-roadmap .roadmap-row.bottom .roadmap-milestone:nth-child(1) { order: 2; }
  .slide-roadmap .roadmap-row.top    .roadmap-milestone:nth-child(2) { order: 3; }
  .slide-roadmap .roadmap-row.bottom .roadmap-milestone:nth-child(2) { order: 4; }
  .slide-roadmap .roadmap-row.top    .roadmap-milestone:nth-child(3) { order: 5; }
  .slide-roadmap .roadmap-row.bottom .roadmap-milestone:nth-child(3) { order: 6; }
  .slide-roadmap .roadmap-row.top    .roadmap-milestone:nth-child(4) { order: 7; }

  /* ---- Slide 11 global market: TAM-SAM-SOM circles tangent at the
     bottom (same ground line). The largest extends OFF the top of the
     viewport — same dramatic proportion as the desktop view. */
  .slide-global .global-stage {
    position: relative;
    display: block !important;
    width: 100%;
    height: 70svh;
    min-height: 480px;
    margin: 12px 0 0 !important;
    padding: 0 !important;
    flex: none !important;
    overflow: visible !important;
    grid-template-columns: none !important;
  }
  .slide-global .global-bubble {
    position: absolute;
    inset: 0;
    display: block;
  }
  /* All three orbs share the same bottom-tangent point — one ground line. */
  .slide-global .global-orb {
    position: absolute !important;
    left: 50% !important;
    bottom: -2% !important;
    top: auto !important;
    transform: translateX(-50%) !important;
    background: transparent !important;
    box-shadow: 0 0 36px rgba(110, 123, 230, 0.18) !important;
    border: 1px solid rgba(110, 123, 230, 0.42) !important;
  }
  /* Same proportions as desktop: largest is ~8× smallest. Largest blows
     past the top of the viewport on purpose. */
  .slide-global .global-orb.size-sm {
    width: 22vw !important;
    aspect-ratio: 1 !important;
    height: auto !important;
  }
  .slide-global .global-orb.size-md {
    width: 70vw !important;
    aspect-ratio: 1 !important;
    height: auto !important;
  }
  .slide-global .global-orb.size-lg {
    width: 175vw !important;
    aspect-ratio: 1 !important;
    height: auto !important;
  }
  /* Each $-figure + label sits inside its ring near the top of the ring
     (above the ring beneath it), all centered horizontally. */
  .slide-global .global-bubble > .global-num,
  .slide-global .global-bubble > .global-label {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    text-align: center;
    white-space: nowrap;
  }
  /* US Hotels — centered within the visible portion of the small ring. */
  .slide-global .global-bubble:nth-child(1) > .global-num   { bottom: 8%; font-size: 15px !important; }
  .slide-global .global-bubble:nth-child(1) > .global-label { bottom: 3%; font-size: 9px !important; }
  /* Global Hotels — vertically centered between the top of the small
     ring (~16% from stage bottom) and the top of the medium ring
     (~58% from stage bottom). */
  .slide-global .global-bubble:nth-child(2) > .global-num   { bottom: 33%; font-size: 17px !important; }
  .slide-global .global-bubble:nth-child(2) > .global-label { bottom: 28%; font-size: 9px !important; }
  /* Global Retail/CRE/Hotels — visible portion of the large ring,
     above the medium ring's top. */
  .slide-global .global-bubble:nth-child(3) > .global-num   { bottom: 84%; font-size: 18px !important; }
  .slide-global .global-bubble:nth-child(3) > .global-label { bottom: 79%; font-size: 9px !important; white-space: normal; max-width: 70%; line-height: 1.2; }
  .slide-global .global-num,
  .slide-global .global-label {
    z-index: 5;
  }

  /* Vertical pulse-travel keyframes for the mobile roadmap. Mirrors
     the desktop horizontal animation but on the y-axis. */
  @keyframes roadmap-pulse-vertical {
    0%   { top: 0%;    opacity: 0; }
    6%   { opacity: 1; }
    85%  { top: 100%; opacity: 1; }
    92%  { top: 100%; opacity: 0.6; }
    100% { top: 100%; opacity: 0; }
  }

  /* ---- Slide 6 (A New Capability): mobile font matching.
     The supervisor pills on slide 5 are SVG text — they scale with the
     SVG viewBox so they shrink with the chart. The dep-cards here are
     HTML, so by default they keep CSS px size and look comparatively
     huge / bold next to the previous slide. Match the SVG scaling by
     sizing font as a fraction of the dep-stage (container) width:
     11 / 820 ≈ 1.34cqw — same ratio used by .org-node text on slide 5.
     Force pill shape — webkit on iOS sometimes loses border-radius on
     children inside `transform-style: preserve-3d` parents. */
  .slide-org-7 .dep-stage {
    container-type: inline-size;
  }
  .slide-org-7 .dep-card {
    font-size: 1.34cqw !important;
    font-weight: 500 !important;
    letter-spacing: 0.02em !important;
    border-radius: 9999px !important;
  }
  .slide-org-7 .tempo-card {
    border-radius: 9999px !important;
  }
  .slide-org-7 .dep-card > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
  }
  /* SVG node text (slide 5 + 6 frontline rows) — also scale down. */
  .slide-org .org-node text,
  .slide-org-7 .org-node text {
    font-size: clamp(5px, 1.3vw, 9px);
  }

  /* ---- Team slide: keep two founders side-by-side as compact
     cards so both fit in one viewport. */
  .team-grid {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: clamp(12px, 3vw, 18px) !important;
    align-items: start;
  }
  .founder-card {
    max-width: none !important;
    gap: 10px !important;
  }
  .founder-status { font-size: 9px; padding: 4px 8px; }
  .founder-status-dot { width: 5px; height: 5px; }
  .founder-name { font-size: clamp(16px, 4.4vw, 20px) !important; }
  .founder-role { font-size: 9px; letter-spacing: 0.18em; }
  .founder-bio { font-size: 12px; max-width: none; }
  .founder-photo-wrap { aspect-ratio: 4/5; }
}


/* =================================================================
   MOBILE LANDSCAPE  (≤ 500px tall, landscape orientation)
   -----------------------------------------------------------------
   Landscape phones reuse the DESKTOP content layout — the desktop
   deck is already a landscape canvas and translates naturally — but
   wrap it in the mobile architecture (each slide is a fixed
   100cqh page, touch-swipe to navigate, no page-level scroll, no
   chrome). Per-slide content sizes are scaled down via vh/vw clamps
   that already exist in the desktop CSS.
   ================================================================= */
/* Landscape mobile uses the same 1920×1080 canvas as desktop and just
   scales down with cinema-block letterbox — PDF-style. The block below
   is disabled (impossible media condition) but kept intact so the
   density-tuned rules are recoverable if we ever want a separate
   landscape-mobile canvas again. */
@media (max-height: 0px) and (orientation: landscape) {

  /* Scale type tokens down for the short viewport. Desktop tokens
     have a min via clamp(); landscape lowers that min so headlines
     and big stats fit alongside their content. */
  :root {
    --t-11:  clamp( 9px, 0.7cqw, 11px);
    --t-12:  clamp(10px, 0.8cqw, 12px);
    --t-13:  clamp(11px, 0.9cqw, 13px);
    --t-15:  clamp(12px, 1.0cqw, 15px);
    --t-17:  clamp(13px, 1.15cqw, 17px);
    --t-20:  clamp(14px, 1.4cqw, 20px);
    --t-24:  clamp(16px, 1.7cqw, 22px);
    --t-32:  clamp(18px, 2.0cqw, 26px);
    --t-40:  clamp(20px, 2.4cqw, 30px);
    --t-56:  clamp(26px, 3.2cqw, 40px);
    --t-72:  clamp(32px, 4.0cqw, 52px);
    --t-96:  clamp(40px, 5.0cqw, 70px);
    --t-128: clamp(54px, 7.0cqw, 100px);
    --pad: clamp(20px, 3cqw, 36px);
  }

  /* Lock the page — no body scroll. The deck sizes the viewport. */
  html, body {
    overflow: hidden;
    height: 100%;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: none;
  }

  /* Deck IS the viewport. Slides absolute-position over each other —
     only the .is-active slide is visible (same as desktop, but every
     slide's reveal is forced settled and inner scroll is allowed). */
  #deck {
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    position: fixed;
    inset: 0;
    overflow: hidden;
    z-index: 2;
    background: transparent;
  }

  /* Locked landscape canvas at 932×430 (iPhone 15/16 Pro Max viewport)
     — same PDF-style approach as desktop, just sized for a phone. JS
     computes --deck-scale = min(innerW/932, innerH/430) and the GPU
     does the uniform scale. Container queries inside resolve against
     this fixed box, so layouts render identically across phones. */
  .stage {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 932px;
    height: 430px;
    transform: translate(-50%, -50%) scale(var(--deck-scale, 1));
    transform-origin: center center;
    container-type: size;
    container-name: stage;
    overflow: hidden;
  }

  .slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* Tighter padding than desktop — there's no nav chrome on
       landscape mobile and the screen is small. */
    padding: 10px clamp(20px, 3cqw, 32px) 12px;
    /* No scroll on landscape — every slide fits the viewport via
       clamp()-based sizing on its content. */
    overflow: hidden;
    /* Many desktop slides set gap: 32-48px between hero + content;
       compress for landscape. */
    gap: clamp(6px, 1.4cqh, 12px);
  }

  .slide:not(.is-active) {
    display: none !important;
  }

  .slide.is-active {
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
    transition: none !important;
  }

  .slide .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  /* Hide desktop chrome — swipe IS navigation. */
  .nav,
  .progress,
  .help,
  .footer-meta { display: none !important; }

  /* Brand mark sits inside the locked stage (inherits position: absolute
     from the desktop rule) so it scales with the canvas. Tightened
     offsets and sized for the smaller landscape canvas. */
  .brand {
    top: 10px !important;
    right: 12px !important;
    z-index: 10;
  }
  .brand-logo { height: 18px !important; }

  /* Hide kickers entirely on mobile — title gets the space. */
  .slide .kicker { display: none !important; }

  /* Normalize all H2 slide headlines to the smaller size — the
     unified rule at the bottom of styles.css sets font-size: var(--t-40)
     which is 20-30px on landscape. Override to the more compact
     size used by risks/stats/team/comp so every slide reads at the
     same scale. */
  .team-headline,
  .traction-headline,
  .traction-v2-headline,
  .flow-headline,
  .us-headline,
  .global-headline,
  .tri-headline,
  .risks-headline,
  .gtm-headline,
  .roadmap-headline,
  .stats-headline,
  .comp-headline,
  .slide-head .headline {
    /* Hard-coded 20px (no clamp/cqw) so every headline lands at the same
       size on iOS Safari, where container query unit resolution can vary
       across slide-specific selectors and produce inconsistencies. */
    font-size: 20px !important;
    line-height: 1.2 !important;
    margin-top: 14px !important;
  }
  /* Appendix slides keep their headlines tight against the top — they
     have denser content stacks below and need every vertical pixel. */
  .slide-risks .risks-headline,
  .slide-stats .stats-headline,
  .slide-comp .comp-headline,
  .slide-moat .moat-headline,
  .slide-proforma .slide-head .headline,
  .slide-appendix .headline {
    margin-top: 4px !important;
  }

  /* ---- Slide 1 (Cover): the desktop margin-bottom on .cover-mark
     (clamp 48-96px) pushes the TEMPO wordmark above a 430px-tall
     viewport. Tighten the grid spacing for landscape. Headline
     shrinks so "AI Orchestration" stays on a single line. */
  .slide-cover .cover-grid {
    padding: 14px clamp(20px, 3cqw, 32px) !important;
    gap: clamp(12px, 2cqw, 24px) !important;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) !important;
    /* Pull the headline + rings toward the center of the canvas — the
       full-width grid was leaving them stranded at the slide edges. */
    width: 84% !important;
    max-width: 800px;
    margin-inline: auto;
  }
  .slide-cover .cover-mark {
    margin-bottom: 0 !important;
  }
  .slide-cover .cover-rings-img {
    max-width: clamp(200px, 26cqw, 280px) !important;
  }
  .slide-cover .cover-headline {
    font-size: clamp(30px, 4.8cqw, 56px) !important;
    line-height: 1.02 !important;
    text-wrap: balance;
  }

  /* ---- Slide 2 (Team): vertical founder cards (photo on top, name +
     role + bio below) — matches the desktop hierarchy but compressed
     for the short viewport. Photos go wider so the row of two
     founders fills the slide; names stay on a single line. */
  .slide-team .team-grid {
    grid-template-columns: 1fr 1fr;
    gap: clamp(24px, 4cqw, 48px);
    max-width: clamp(560px, 76cqw, 720px);
    margin: clamp(14px, 4cqh, 28px) auto 0;
    align-content: start;
  }
  .slide-team .founder-card {
    flex-direction: column;
    align-items: stretch;
    gap: clamp(8px, 1.4cqh, 12px);
    max-width: none;
    width: 100%;
  }
  .slide-team .founder-photo-wrap {
    flex: 0 0 auto;
    width: 100%;
    aspect-ratio: 1 / 1;
    /* Cap photo height so name + role + bio still fit within slide. */
    max-height: clamp(120px, 38cqh, 180px);
  }
  .slide-team .founder-photo-wrap > img,
  .slide-team .founder-photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Anchor the crop near the top so heads + hair stay in frame. */
    object-position: center top;
  }
  /* Maso's photo is framed lower — pull the crop down a touch so his
     neck/shoulders aren't clipped. */
  .slide-team .founder-card:nth-child(2) .founder-photo {
    object-position: center 25% !important;
  }
  .slide-team .founder-id {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: baseline;
    gap: 10px;
  }
  .slide-team .founder-status {
    font-size: 9px !important;
    padding: 3px 8px !important;
    align-self: flex-start;
    margin-bottom: 4px;
  }
  .slide-team .founder-name {
    font-size: clamp(18px, 2.6cqw, 24px) !important;
    line-height: 1.05;
    white-space: nowrap; /* keep name on a single line */
  }
  .slide-team .founder-role {
    font-size: 9px !important;
    letter-spacing: 0.18em;
  }
  .slide-team .founder-bio {
    font-size: 14px !important;
    line-height: 1.4;
    margin-top: 6px !important;
  }
  .slide-team .founder-bullets {
    gap: 6px !important;
    padding-top: 10px !important;
  }
  .slide-team .founder-bullets li {
    font-size: 13px !important;
    line-height: 1.35 !important;
    padding-left: 14px !important;
  }
  .slide-team .founder-bullets li::before {
    width: 4px !important;
    height: 4px !important;
    top: 7px !important;
    left: 2px !important;
  }
  .slide-team .team-headline {
    /* Inherit the unified 20px from the rule above; only need to add
       the bottom margin so the team grid doesn't crowd the headline. */
    margin-bottom: 6px;
  }

  /* ---- Slides 5/6 (Org charts): cap chart size by viewport height,
     not just width. Aspect-ratio is 820/470 ≈ 1.745, so max-width is
     derived from the height budget so the chart never overflows
     vertically while preserving aspect. */
  .slide-org > .org-chart,
  .slide-org-7 .org-chart-3d {
    width: 100%;
    max-width: min(880px, calc((100cqh - 110px) * 820 / 470)) !important;
    aspect-ratio: 820 / 470;
    height: auto !important;
    align-self: center;
  }
  /* Slide 6: dep-card pill text scales with the SVG container so
     "Assistant Director" / "Supervisor" don't overrun their pills.
     Same 1.34cqw ratio (11/820) used by the SVG <text> on slide 5. */
  .slide-org-7 .dep-stage { container-type: inline-size; }
  .slide-org-7 .dep-card {
    font-size: 1.34cqw !important;
    font-weight: 500 !important;
    letter-spacing: 0.02em !important;
  }
  /* `.org-headline` is a defunct class (no slide uses it any more — slide
     7's headline is `.slide-head .headline`, which inherits the unified
     20px). Kept only for the bottom margin in case the class returns. */
  .slide-org .org-headline,
  .slide-org-7 .org-headline {
    margin-bottom: 6px !important;
  }
  .slide-head { gap: 6px !important; }

  /* ---- Slide 8 (Pipeline): tighten the chart-pair stack and give
     the logo marquee more vertical room so the brand strip doesn't
     feel squeezed. Hide the fine print — it's a footnote that
     belongs only on the desktop / portrait view. */
  .slide-traction-pipeline .traction-v2-headline {
    /* Font size inherits the unified 20px above — keep only the
       margin/line-height tweaks the slide layout actually needs. */
    margin-bottom: 4px !important;
    line-height: 1.18 !important;
  }
  /* Chart is the hero — let it take all the available height. The
     marquee block sizes itself to its content (single-row logo strip
     + headline). */
  .slide-traction-pipeline .pipeline-stack {
    gap: 14px !important;
  }
  .slide-traction-pipeline .pipeline-block--chart {
    flex: 1 1 auto !important;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  .slide-traction-pipeline .pipeline-stack {
    gap: 14px !important;
  }
  /* Shift the logo strip UP visually by ~half the empty space below
     the chart canvas (the canvas was pulled up via -24px margin). The
     transform is purely visual — flex layout / chart size unchanged. */
  .slide-traction-pipeline .pipeline-block--marquee {
    flex: 0 0 auto !important;
    transform: translateY(-13px);
  }
  /* The desktop rule uses `margin-top: auto` to push the marquee toward
     the bottom of its block, but the mobile override above shrinks the
     block to its content (flex: 0 0 auto), so auto-margins collapse to
     zero and the headline kisses the logos. Force an explicit gap. */
  .slide-traction-pipeline .pipeline-block--marquee .v2-marquee {
    margin-top: clamp(14px, 3cqh, 24px) !important;
    margin-bottom: 0 !important;
  }
  .slide-traction-pipeline .v2-chart-pair {
    gap: clamp(16px, 2cqw, 28px) !important;
    flex: 1 1 auto;
    /* Narrower chart cards make the growth lines/bars look steeper. */
    max-width: 600px;
    margin: 0 auto;
    width: 100%;
  }
  .slide-traction-pipeline .v2-chart-title {
    font-size: 11px !important;
    padding-bottom: 2px !important;
  }
  .slide-traction-pipeline .v2-chart-title-meta {
    font-size: 11px !important;
  }
  .slide-traction-pipeline .pipeline-headline-plain {
    font-size: 13px !important;
    line-height: 1.3 !important;
  }
  .slide-traction-pipeline .pipeline-fine {
    display: none !important;
  }
  .slide-traction-pipeline .v2-marquee--single .v2-marquee-track img {
    height: 22px !important;
    margin-right: clamp(40px, 5cqw, 68px) !important;
  }

  /* ---- Slide 7 (W Hotels proof): claim shrinks, less vertical gap. */
  .slide-traction-proof .proof-claim {
    font-size: clamp(20px, 3.4cqw, 32px) !important;
    line-height: 1.06 !important;
  }
  .slide-traction-proof .proof-body {
    font-size: 11px !important;
    line-height: 1.4 !important;
  }
  .slide-traction-proof .proof-text { gap: 10px !important; }
  /* Three stat columns evenly distributed across the right column. */
  .slide-traction-proof .proof-stats {
    display: grid !important;
    grid-template-columns: 1fr 1fr 1fr !important;
    gap: 0 !important;
    width: 100%;
    margin-top: 6px !important;
  }
  .slide-traction-proof .proof-stat { gap: 4px; }
  .slide-traction-proof .proof-stat-divider { display: none !important; }
  /* Stats sized to keep "30 days" on a single line in each column. */
  .slide-traction-proof .proof-num {
    font-size: clamp(16px, 2.2cqw, 22px) !important;
    white-space: nowrap;
  }
  .slide-traction-proof .proof-lbl { font-size: 9px !important; }

  /* ---- Slide 11 (Global): orbs scale down for the short viewport so
     the largest doesn't extend half a viewport off-screen. */
  .slide-global .global-orb.size-sm {
    width: clamp(110px, 14cqw, 150px);
  }
  .slide-global .global-orb.size-md {
    width: clamp(360px, 44cqw, 540px);
  }
  .slide-global .global-orb.size-lg {
    width: clamp(900px, 105cqw, 1200px);
  }
  .slide-global .global-num { font-size: clamp(18px, 2.4cqw, 26px) !important; }
  .slide-global .global-label { font-size: 10px !important; }

  /* ---- Slide 12 (Land and expand): smaller iso boxes + tighter
     captions so the row doesn't push past the headline + assumptions. */
  .slide-gtm .gtm-fig-img,
  .slide-gtm .gtm-fig:nth-child(3) .gtm-fig-img {
    max-width: clamp(140px, 22cqw, 220px);
  }
  .slide-gtm .gtm-fig { gap: 8px; }
  .slide-gtm .gtm-stage { padding: 6px 0; gap: clamp(8px, 1.5cqw, 16px); }
  .slide-gtm .gtm-caption-acv { font-size: clamp(16px, 2.2cqw, 22px) !important; }
  .slide-gtm .gtm-caption-label { font-size: clamp(11px, 1.3cqw, 13px) !important; }
  .slide-gtm .gtm-caption-sub { font-size: 9px !important; }
  /* gtm-headline inherits the unified 20px rule above — no slide-specific
     override so all landscape headlines render at the same size. */
  .slide-gtm .gtm-assumptions { font-size: 9px !important; margin-top: 6px !important; }

  /* ---- Slide 13 (Roadmap): horizontal timeline already fits, just
     tighten typography. The desktop translateX(7%) on the line +
     rows looks off-center on a phone — remove it so the timeline
     spans the slide evenly. */
  /* roadmap-headline inherits the unified 20px rule above; only retain
     the bottom-margin tweak that the timeline layout needs below. */
  .slide-roadmap .roadmap-headline { margin-bottom: 6px; }
  .slide-roadmap .roadmap-row,
  .slide-roadmap .roadmap-line {
    transform: translateX(3.5%) !important;
  }
  /* Each milestone content column is tighter so the detail text
     doesn't wrap into a tall block that bleeds into the next
     milestone vertically. */
  .slide-roadmap .roadmap-milestone .content {
    width: clamp(110px, 14cqw, 150px) !important;
    gap: 2px !important;
  }
  .slide-roadmap .roadmap-milestone .when { font-size: 9px !important; letter-spacing: 0.1em !important; }
  .slide-roadmap .roadmap-milestone .what { font-size: 11px !important; line-height: 1.15; }
  .slide-roadmap .roadmap-milestone .detail {
    font-size: 9.5px !important;
    line-height: 1.3 !important;
    /* Cap detail to 2 lines so vertical spillover doesn't bleed
       into the spend pills below or the row above. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* ---- Slide 16 (Risks): tighter body, narrower quote column. */
  .slide-risks .risks-headline { margin-bottom: 6px !important; }
  .slide-risks .risks-list { gap: 8px !important; }
  .slide-risks .risk-row {
    grid-template-columns: 22px 1fr !important;
    gap: 10px !important;
    padding-top: 8px !important;
  }
  .slide-risks .risk-quote { font-size: 26px !important; line-height: 0.9; }
  .slide-risks .risk-objection { font-size: 12px !important; line-height: 1.2 !important; }
  .slide-risks .risk-rebuttal { font-size: 10.5px !important; line-height: 1.35 !important; }
  .slide-risks .risk-content { gap: 3px !important; }

  /* Landscape-only: the next prompt waits for a tap on the row. The
     row gets a faint pulse and a "Tap to continue →" hint so the
     viewer knows what to do. */
  .slide-flow .flow-row.flow-row-await-tap {
    cursor: pointer;
    position: relative;
    /* Kill iOS Safari's default tap highlight + text-selection drag
       overlay that shows up when you tap the row. */
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
  .slide-flow .flow-row.flow-row-await-tap::after {
    content: "Tap to continue →";
    position: absolute;
    right: 0;
    bottom: -22px;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent-bright);
    opacity: 0;
    animation: flow-tap-hint 1.6s ease-in-out 200ms infinite;
    pointer-events: none;
  }
  @keyframes flow-tap-hint {
    0%, 100% { opacity: 0; transform: translateX(-4px); }
    50%      { opacity: 0.9; transform: translateX(0); }
  }

  /* ---- Slide 9 (Tempo automates / flow): hide the fine print so
     the three meter numbers can breathe; UI modal scales down so it
     doesn't dominate. */
  .slide-flow .meter-fine {
    display: none !important;
  }
  .slide-flow .flow-meter {
    bottom: clamp(16px, 3.5cqh, 28px);
    gap: 0;
    width: min(440px, 70%);
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .slide-flow .meter-value {
    font-size: clamp(20px, 2.4cqw, 26px) !important;
  }
  .slide-flow .meter-label {
    font-size: 10px !important;
    letter-spacing: 0.1em;
  }
  .slide-flow .meter-cell { gap: 4px; }
  /* Anchor flow rows to the bottom of the stage so they sit just
     above the meter (stats) — newest at the bottom, older rows
     slide up and fade behind a top mask. */
  .slide-flow .flow-stage {
    justify-content: flex-end;
    padding-bottom: clamp(60px, 12cqh, 100px);
    margin-bottom: 0 !important;
    /* The slide itself is fixed-height and `overflow: hidden`, so the
       stage must also clip — without it, flex:1 + min-height:auto lets
       the rows force the stage taller than the slide, the newest row
       lands off-screen, and the absolutely-positioned meter ends up
       overlapping older rows. */
    overflow: hidden !important;
    min-height: 0 !important;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,0.2) 8%, black 24%, black 100%);
            mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,0.2) 8%, black 24%, black 100%);
  }
  .slide-flow .flow-stage::before { display: none !important; }
  .slide-flow .flow-row {
    transition:
      max-height 480ms cubic-bezier(0.16, 1, 0.3, 1),
      opacity 320ms ease-out,
      transform 480ms cubic-bezier(0.16, 1, 0.3, 1);
  }
  .slide-flow .flow-row[data-state="hidden"] {
    max-height: 0 !important;
    opacity: 0 !important;
    transform: translateY(16px);
    pointer-events: none;
    margin-top: 0 !important;
  }
  .slide-flow .flow-row[data-state="awaiting"],
  .slide-flow .flow-row[data-state="dispatching"],
  .slide-flow .flow-row[data-state="complete"] {
    transform: translateY(0);
  }
  /* Compact UI modal — narrower plate, smaller buttons, smaller body
     so it sits comfortably above the stat row. */
  .slide-flow .flow-row .cmd-plate {
    max-width: clamp(360px, 56cqw, 540px);
    margin-inline: auto;
  }
  .slide-flow .cmd-prompt,
  .slide-flow .flow-row .cmd-prompt {
    font-size: 13px !important;
    line-height: 1.35 !important;
  }
  .slide-flow .flow-row .cmd-icon { width: 22px !important; height: 22px !important; }
  .slide-flow .flow-row .cmd-icon svg { width: 11px !important; height: 11px !important; }
  .slide-flow .flow-row .cmd-send { height: 22px !important; padding: 0 3px 0 7px !important; }
  .slide-flow .flow-row .cmd-send svg { width: 11px !important; height: 11px !important; }
  .slide-flow .flow-tasks .cmd-task { padding: 8px 12px !important; }

  /* ---- Slide 19 (Competition): make the table scrollable in both
     directions on landscape — desktop locks `overflow: hidden` on the
     wrap, but the comp table is wider AND taller than the small
     viewport, so scrolling has to be allowed inside it. */
  .slide-comp .comp-table-wrap {
    overflow: auto !important;
    -webkit-overflow-scrolling: touch;
    max-height: calc(100cqh - 80px);
  }
  .slide-comp .comp-table {
    min-width: 1020px;
    font-size: 11px !important;
  }
  .slide-comp .comp-table thead th {
    font-size: 9.5px !important;
  }
  .slide-comp .comp-headline {
    font-size: clamp(15px, 2.2cqw, 20px) !important;
  }

  /* ---- Slide 21 (Moat): typography scales with viewport height,
     and the moat-list grows to fill remaining space — rows are
     distributed evenly between headline and bottom edge so no
     empty band sits below them. */
  .slide-moat {
    justify-content: flex-start !important;
    gap: clamp(4px, 1.4cqh, 14px) !important;
  }
  .slide-moat .moat-lede {
    font-size: clamp(10px, 3cqh, 18px) !important;
    line-height: 1.35 !important;
  }
  .slide-moat .moat-list {
    flex: 1 1 auto;
    display: flex !important;
    flex-direction: column;
    justify-content: space-evenly;
    gap: 0 !important;
  }
  .slide-moat .moat-row {
    padding-top: clamp(6px, 2cqh, 18px) !important;
    gap: clamp(10px, 2cqw, 22px) !important;
  }
  .slide-moat .moat-num {
    font-size: clamp(8px, 2.1cqh, 12px) !important;
    letter-spacing: 0.12em !important;
  }
  .slide-moat .moat-content { gap: 2px !important; }
  .slide-moat .moat-claim {
    font-size: clamp(11px, 3.4cqh, 20px) !important;
    line-height: 1.18 !important;
  }
  .slide-moat .moat-body {
    font-size: clamp(9.5px, 2.7cqh, 16px) !important;
    line-height: 1.4 !important;
  }

  /* ---- Slide 18 (Stats): tighter copy + citation. */
  .slide-stats .stats-headline { font-size: clamp(15px, 2.2cqw, 20px) !important; margin-bottom: 4px !important; }
  .slide-stats .stats-list { gap: 6px !important; }
  .slide-stats .stats-list > * { padding: 6px 0 !important; }
  .slide-stats p,
  .slide-stats .stat-body { font-size: 10.5px !important; line-height: 1.32 !important; }
  .slide-stats .citations {
    font-size: 8.5px !important;
    line-height: 1.3 !important;
    padding-top: 6px !important;
    /* All 5 citations on one row. */
    grid-template-columns: repeat(5, 1fr) !important;
    gap: 4px 10px !important;
  }
  .slide-stats .citations li {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* ---- Slide 9 (Org chart with industries tier): every desktop rule
     here is a `clamp(floor, cqw/cqh, ceiling)`. On landscape the cqw/
     cqh value resolves smaller than the floor, so the floor wins and
     the tier "pops" larger relative to the canvas than it does on
     desktop. Drop the floors so container queries can scale the whole
     tier proportionally — landscape becomes the desktop layout, just
     smaller. Connector + chart formula also fix the residual vertical
     budget (connector floor 80px was almost a fifth of the canvas;
     chart's original reserve assumed no industries-tier). */
  .slide-org-7 .industries-list {
    max-width: 66cqw !important;
  }
  .slide-org-7 .industry-node {
    padding: 0.4cqw 1cqw !important;
    font-size: 0.9cqw !important;
  }
  .slide-org-7 .industries-connector {
    height: 8cqh !important;
    margin-bottom: -1cqh !important;
  }
  .slide-org-7 .org-chart-3d {
    max-width: min(880px, calc((100cqh - 170px) * 820 / 470)) !important;
  }

  /* ---- Slide 10 (Housekeeping flow): same floor-dropping approach as
     slide 9. The desktop styles use clamp() with min floors that win
     against the smaller cqw/cqh on landscape, making the slide ~678px
     tall in a 430px canvas. The desktop canvas has aspect 1.78:1 but
     landscape is 2.17:1, so the slide is height-constrained — use
     cqh for vertical sizing (font, padding-y, gaps) so the layout
     scales with the height budget, and cqw for horizontal padding
     where width is generous. Result: every element is the desktop
     element, just smaller. */
  .slide-housekeeping {
    gap: 1.5cqh !important;
  }
  .slide-housekeeping .hk-headline {
    font-size: 3.2cqh !important;
    line-height: 1.18 !important;
  }
  .slide-housekeeping .hk-split {
    gap: 3cqw !important;
  }
  .slide-housekeeping .hk-column {
    gap: 1cqh !important;
  }
  .slide-housekeeping .hk-column-tag {
    padding-bottom: 0.6cqh !important;
  }
  .slide-housekeeping .hk-tag-label,
  .slide-housekeeping .hk-tag-detail {
    font-size: 1.5cqh !important;
  }
  .slide-housekeeping .hk-steps {
    gap: 0.7cqh !important;
  }
  .slide-housekeeping .hk-step {
    gap: 1cqw !important;
    padding: 0.8cqh 1.2cqw !important;
    font-size: 1.85cqh !important;
    line-height: 1.25 !important;
  }
  .slide-housekeeping .hk-step-num,
  .slide-housekeeping .hk-step-time {
    font-size: 1.55cqh !important;
  }
  .slide-housekeeping .hk-step-recovery {
    font-size: 1.85cqh !important;
  }
  .slide-housekeeping .hk-step-icon {
    width: 2cqh !important;
    height: 2cqh !important;
  }
  .slide-housekeeping .hk-step:not(:last-child)::after {
    bottom: calc(-1 * 0.7cqh) !important;
    height: 0.7cqh !important;
  }
  .slide-housekeeping .hk-plate .cmd-row {
    font-size: 1.85cqh !important;
    padding: 0 0.4cqw 0.6cqh !important;
  }
  /* Shrink the plate's own padding — desktop has 16/12px which is
     ~half the modal height on landscape. */
  .slide-housekeeping .hk-plate.cmd-plate {
    padding: 1cqh 1.2cqw 0.6cqh !important;
  }
  .slide-housekeeping .hk-plate .cmd-actions {
    padding-top: 0.6cqh !important;
  }
  .slide-housekeeping .hk-tasks {
    gap: 0.7cqh !important;
  }
  .slide-housekeeping .hk-task {
    padding: 0.9cqh 1.2cqw !important;
    gap: 0.4cqh !important;
  }
  .slide-housekeeping .hk-task .cmd-task-msg {
    font-size: 1.85cqh !important;
  }
  /* `cmd-task-header` (the "BOARD-BUILD · COMPLETE" row) and `cmd-task-
     status` use fixed 11/10px on desktop; in landscape that's huge
     relative to the surrounding body text. Scale them with the
     canvas — sized to match the prompt-line body so the modal reads
     as a coherent typographic system. */
  .slide-housekeeping .hk-task .cmd-task-header {
    font-size: 1.55cqh !important;
  }
  .slide-housekeeping .hk-task .cmd-task-status {
    font-size: 1.4cqh !important;
    gap: 0.6cqh !important;
  }
  .slide-housekeeping .hk-task .cmd-task-status .dot {
    width: 1cqh !important;
    height: 1cqh !important;
  }
  .slide-housekeeping .hk-foot {
    padding-top: 1cqh !important;
    gap: 0.4cqh !important;
  }
  .slide-housekeeping .hk-foot .meter-value {
    font-size: 4cqh !important;
  }
  .slide-housekeeping .hk-foot .meter-label {
    font-size: 1.4cqh !important;
  }
  .slide-housekeeping .hk-foot-fine {
    font-size: 1.3cqh !important;
    margin-top: 0.2cqh !important;
  }

  /* ---- Sources / citations slides: desktop pagination splits the
     citations into 4-5 fixed pages measured against the 1080px stage.
     In landscape that pagination doesn't fire (non-active slides are
     display:none during the boot measurement), so all 9 citations end
     up on a single 2500-px-tall slide that hard-clips at 430. Allow
     internal scroll within the slide and shrink the body so more fits
     per visible frame. */
  .slide-citations {
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
    justify-content: flex-start !important;
    padding-top: 8px !important;
  }
  .slide-citations .citations-headline {
    font-size: clamp(14px, 3.2cqh, 20px) !important;
    margin: 0 !important;
  }
  .slide-citations .kicker {
    margin-bottom: 4px !important;
  }
  .slide-citations .citations-list {
    gap: 6px !important;
    max-width: 100% !important;
  }
  .slide-citations .citation-row {
    grid-template-columns: 22px 1fr !important;
    gap: 8px !important;
    padding-top: 6px !important;
  }
  .slide-citations .citation-marker {
    font-size: 11px !important;
    padding-top: 2px !important;
  }
  .slide-citations .citation-body {
    gap: 3px !important;
  }
  .slide-citations .citation-claim {
    font-size: 11px !important;
    line-height: 1.2 !important;
    gap: 6px !important;
  }
  .slide-citations .citation-method {
    font-size: 9px !important;
    line-height: 1.4 !important;
    padding: 4px 6px !important;
  }
  .slide-citations .citation-sources {
    gap: 2px !important;
  }
  .slide-citations .citation-sources li {
    font-size: 9.5px !important;
    line-height: 1.35 !important;
  }
  .slide-citations .citation-sources li em {
    font-size: 0.9em !important;
  }
  .slide-citations .cite-tag {
    font-size: 0.78em !important;
    padding: 1px 4px !important;
    margin-right: 4px !important;
  }
  .slide-citations .citation-section {
    padding-top: 8px !important;
    margin-top: 4px !important;
    gap: 8px !important;
  }
  .slide-citations .citation-section-num {
    font-size: 10px !important;
  }
  .slide-citations .citation-section-title {
    font-size: 9px !important;
  }
}

/* -------- Appendix: pricing-evolution slide ---------------------------- */
/* Three phase cards in a row + connector arrows + a strategic-note
   callout. Visual progression: phase 3 (FTE-replacement) wins with
   accent border + glow so the eye reads it as the destination. ACV is
   the hero on each card — biggest type, top of the visual stack. */
.slide-pricing {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.8cqh, 26px);
}
.pricing-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 1.8cqw, 30px);
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--text);
  margin: 0;
}
.pricing-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.06em;
  color: var(--accent-bright);
}
.pricing-phases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 2.6cqw, 44px);
  /* Cards stretch to match the tallest; block centers vertically in the
     slide via auto margins so freed space breathes on the page rather
     than padding the inside of every card. Matches .revenue-phases. */
  align-items: stretch;
  margin: auto 0;
  position: relative;
}
.pricing-phase {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 0.9cqh, 12px);
  padding: clamp(18px, 1.8cqw, 28px);
  background: linear-gradient(180deg, rgba(255,255,255,0.02) 0%, rgba(255,255,255,0) 100%), var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  min-width: 0;
  position: relative;
}
/* Connector chevron ">" between consecutive phase cards. Two angled
   borders form a clean arrow; sits in the gap, vertically centered. */
.pricing-phase:not(:last-child)::after {
  content: "";
  position: absolute;
  right: calc(-1 * clamp(28px, 2.6cqw, 44px) / 2 - clamp(5px, 0.5cqw, 7px));
  top: 50%;
  width: clamp(10px, 0.9cqw, 14px);
  height: clamp(10px, 0.9cqw, 14px);
  border-top: 2px solid var(--accent-bright);
  border-right: 2px solid var(--accent-bright);
  transform: translateY(-50%) rotate(45deg);
  opacity: 0.65;
  pointer-events: none;
}
/* Phase 3 — the unlock. Accent border, soft inner glow, brighter ACV. */
.pricing-phase--final {
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(110, 123, 230, 0.12) 0%, transparent 70%),
    var(--bg-elev);
  border-color: rgba(110, 123, 230, 0.45);
  box-shadow:
    0 0 0 1px rgba(110, 123, 230, 0.18),
    0 0 32px -8px rgba(110, 123, 230, 0.35);
}
.pricing-phase-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.pricing-phase-num {
  font-family: var(--font-mono);
  font-size: clamp(12px, 0.95cqw, 15px);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent-bright);
  font-weight: 500;
}
.pricing-phase-when {
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.85cqw, 13px);
  letter-spacing: 0.08em;
  color: var(--text-dim);
}
.pricing-phase-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 1.85cqw, 30px);
  letter-spacing: -0.015em;
  color: var(--text);
  line-height: 1.1;
}
/* ACV — the hero. Much larger, anchors the visual hierarchy. */
.pricing-phase-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: clamp(6px, 0.6cqh, 10px) 0 clamp(4px, 0.4cqh, 6px);
  padding-bottom: clamp(10px, 1cqh, 14px);
  border-bottom: 1px solid var(--border-soft);
}
.pricing-phase-acv {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(34px, 3cqw, 50px);
  color: var(--text);
  letter-spacing: -0.025em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.pricing-phase--final .pricing-phase-acv {
  color: #FFFFFF;
  text-shadow:
    0 0 12px rgba(110, 123, 230, 0.4),
    0 0 28px rgba(110, 123, 230, 0.2);
}
.pricing-phase-acv-unit {
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.75cqw, 12px);
  color: var(--text-dim);
  letter-spacing: 0.04em;
}
.pricing-phase-model {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(13px, 1.05cqw, 15px);
  color: var(--text);
  line-height: 1.3;
}
.pricing-phase-formula {
  margin: 0;
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.7cqw, 11px);
  color: var(--text-dim);
  letter-spacing: 0.02em;
}
/* Budget-anchor chip — pinned to the bottom of the card to match the
   incumbents footer on .revenue-phase. The Phase 3 wage variant glows
   accent. */
.pricing-phase-anchor {
  display: flex;
  align-items: baseline;
  gap: clamp(8px, 0.8cqw, 12px);
  margin-top: auto;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  align-self: stretch;
  flex-wrap: wrap;
}
.pricing-anchor-label {
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.75cqw, 11px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
}
.pricing-anchor-value {
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.9cqw, 14px);
  color: var(--text-soft);
  letter-spacing: 0.02em;
  line-height: 1.4;
}
.pricing-phase-anchor--wage {
  background: rgba(110, 123, 230, 0.1);
  border-color: rgba(110, 123, 230, 0.4);
}
.pricing-phase-anchor--wage .pricing-anchor-label { color: var(--accent-bright); }
.pricing-phase-anchor--wage .pricing-anchor-value { color: #FFFFFF; }

.pricing-phase-bullets {
  list-style: none;
  /* Bottom margin guarantees breathing room before the bottom-pinned
     anchor chip. Matches .revenue-phase-bullets. */
  margin: clamp(4px, 0.4cqh, 6px) 0 clamp(32px, 3.2cqh, 52px);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.7cqh, 10px);
}
.pricing-phase-bullets li {
  font-family: var(--font-display);
  font-size: clamp(13px, 1.05cqw, 16px);
  line-height: 1.5;
  color: var(--text-soft);
  padding-left: 16px;
  position: relative;
}
.pricing-phase-bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-bright);
  opacity: 0.7;
}
.pricing-phase-bullets .em {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 1.04em;
  color: var(--text);
}

/* Strategic-note callout below the three phase cards. Single-line accent
   bar on the left + label + body — feels like a margin note rather than
   a heavy boxed callout. */
.pricing-insight {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(14px, 1.4cqw, 22px);
  align-items: start;
  padding: clamp(14px, 1.4cqw, 20px) clamp(16px, 1.6cqw, 24px);
  background: rgba(255, 255, 255, 0.025);
  border-radius: 8px;
  border-left: 2px solid rgba(110, 123, 230, 0.5);
}
.pricing-insight-label {
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.72cqw, 11px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-bright);
  padding-top: 3px;
  width: clamp(110px, 9.5cqw, 150px);
  line-height: 1.4;
}
.pricing-insight-body {
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.6cqh, 9px);
  max-width: 92ch;
}
.pricing-insight-body p {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(12px, 0.9cqw, 13px);
  line-height: 1.5;
  color: var(--text-soft);
}
.pricing-insight-body .num {
  font-family: var(--font-mono);
  font-weight: 500;
  color: var(--text);
}
.pricing-insight-body .ref {
  font-family: var(--font-mono);
  font-size: 0.7em;
  color: var(--accent-bright);
  margin-left: 1px;
  vertical-align: super;
  line-height: 0;
}
.pricing-insight-benchmarks {
  padding-top: clamp(4px, 0.4cqh, 6px);
  margin-top: clamp(2px, 0.2cqh, 4px) !important;
  border-top: 1px dashed var(--border-soft);
  font-family: var(--font-mono) !important;
  font-size: clamp(11px, 0.78cqw, 12px) !important;
  color: var(--text-dim) !important;
  letter-spacing: 0.01em;
}
.pricing-insight-benchmarks .num { color: var(--text-soft) !important; }

/* -------- Appendix: hotel-financials McKinsey-style stat grid --------- */
/* Four equal cards in a single row. The supervisor-spend card answers the
   slide's lead question ("how much is spent on frontline supervisors?")
   and gets the accent-glow hero treatment so it reads as the answer at a
   glance. Big numbers carry the visual hierarchy; short detail lines below
   each stat give just enough context without becoming prose. */
.slide-financials {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2cqh, 32px);
}
.financials-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 2cqw, 34px);
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--text);
  margin: 0;
}
.financials-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.06em;
  color: var(--accent-bright);
}
.financials-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(20px, 2cqw, 36px);
  align-items: stretch;
  margin: auto 0;
}
.financials-card {
  display: flex;
  flex-direction: column;
  padding: clamp(22px, 2.2cqw, 36px);
  background: linear-gradient(180deg, rgba(255,255,255,0.02) 0%, rgba(255,255,255,0) 100%), var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  min-width: 0;
  position: relative;
}
/* Hero card — accent border + soft inner glow so the eye reads it first. */
.financials-card--hero {
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(110, 123, 230, 0.12) 0%, transparent 70%),
    var(--bg-elev);
  border-color: rgba(110, 123, 230, 0.45);
  box-shadow:
    0 0 0 1px rgba(110, 123, 230, 0.18),
    0 0 32px -8px rgba(110, 123, 230, 0.35);
}
.financials-label {
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.85cqw, 13px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-bright);
  font-weight: 500;
}
/* Big-number hero — pushed down so the label sits at top and the stat
   lands in the upper-middle of the card. */
.financials-stat {
  margin-top: clamp(14px, 1.6cqh, 24px);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(34px, 2.9cqw, 52px);
  color: var(--text);
  letter-spacing: -0.03em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.financials-card--hero .financials-stat {
  color: #FFFFFF;
  text-shadow:
    0 0 12px rgba(110, 123, 230, 0.4),
    0 0 28px rgba(110, 123, 230, 0.2);
}
.financials-unit {
  margin-top: clamp(4px, 0.4cqh, 6px);
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.85cqw, 13px);
  color: var(--text-dim);
  letter-spacing: 0.04em;
}
/* Detail line — pinned to the bottom of the card with a hairline divider
   above. Cards are equal-stretched so the detail bars line up across the
   row regardless of how tall each stat renders. */
.financials-detail {
  margin: 0;
  margin-top: auto;
  padding-top: clamp(14px, 1.4cqh, 22px);
  border-top: 1px solid var(--border-soft);
  font-family: var(--font-display);
  font-size: clamp(12px, 0.95cqw, 14px);
  line-height: 1.5;
  color: var(--text-soft);
}
.financials-detail .em {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.06em;
  color: #FFFFFF;
}
.slide-financials .citations {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 0.4cqh, 6px);
}
.slide-financials .citations li {
  font-family: var(--font-mono);
  font-size: clamp(9px, 0.68cqw, 10px);
  color: var(--text-dim);
  letter-spacing: 0.02em;
  line-height: 1.5;
}
.slide-financials .citations em {
  font-style: italic;
  color: var(--text-soft);
}
/* Numbered superscript next to each big stat — ties the figure on the
   card back to its row in the citations footer. Tabular-nums on the
   parent already handles digit alignment; the ref sits above baseline. */
.financials-stat .ref {
  font-family: var(--font-mono);
  font-size: 0.32em;
  color: var(--accent-bright);
  margin-left: 0.18em;
  vertical-align: super;
  line-height: 0;
  letter-spacing: 0.04em;
  font-weight: 500;
}

/* Inline-URL style used in appendix slide citations — small mono link
   below the citation label so the source is auditable on the slide. */
.cite-url {
  font-family: var(--font-mono);
  font-size: 0.92em;
  color: var(--accent-bright);
  text-decoration: none;
  word-break: break-all;
}
.cite-url:hover { text-decoration: underline; }

.slide-pricing .citations {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 0.4cqh, 6px);
}
.slide-pricing .citations li {
  font-family: var(--font-mono);
  font-size: clamp(9px, 0.68cqw, 10px);
  color: var(--text-dim);
  letter-spacing: 0.02em;
  line-height: 1.5;
}

/* -------- Appendix: revenue-roadmap slide ----------------------------- */
/* Three-phase progression mirroring pricing-evolution structurally, but
   the hero of each card is the DEPARTMENT (not an ACV figure) — this
   slide tells the strategic story of which surfaces we own when, and
   which incumbents we displace at each phase. Phase 3 (guest-facing
   upsell) gets the accent glow as the destination phase. */
.slide-revenue {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.5cqh, 22px);
}
.revenue-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 1.8cqw, 30px);
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--text);
  margin: 0;
}
.revenue-headline .em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1.06em;
  color: var(--accent-bright);
}
.revenue-phases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 2.6cqw, 44px);
  /* All cards stretch to the height of the tallest (currently phase 3 with
     the RTW label). The block is centered vertically in the slide via auto
     margins so the freed space breathes on the page rather than padding
     the inside of every card. */
  align-items: stretch;
  margin: auto 0;
  position: relative;
}
.revenue-phase {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 0.9cqh, 12px);
  padding: clamp(18px, 1.8cqw, 28px);
  background: linear-gradient(180deg, rgba(255,255,255,0.02) 0%, rgba(255,255,255,0) 100%), var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  min-width: 0;
  position: relative;
}
/* Connector chevron between consecutive phase cards — same visual as
   pricing-evolution so the two appendix progressions read as a set. */
.revenue-phase:not(:last-child)::after {
  content: "";
  position: absolute;
  right: calc(-1 * clamp(28px, 2.6cqw, 44px) / 2 - clamp(5px, 0.5cqw, 7px));
  top: 50%;
  width: clamp(10px, 0.9cqw, 14px);
  height: clamp(10px, 0.9cqw, 14px);
  border-top: 2px solid var(--accent-bright);
  border-right: 2px solid var(--accent-bright);
  transform: translateY(-50%) rotate(45deg);
  opacity: 0.65;
  pointer-events: none;
}
/* Phase 3 destination card — accent border + soft inner glow so the eye
   reads it as where the strategy lands. */
.revenue-phase--final {
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(110, 123, 230, 0.12) 0%, transparent 70%),
    var(--bg-elev);
  border-color: rgba(110, 123, 230, 0.45);
  box-shadow:
    0 0 0 1px rgba(110, 123, 230, 0.18),
    0 0 32px -8px rgba(110, 123, 230, 0.35);
}
.revenue-phase-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.revenue-phase-num {
  font-family: var(--font-mono);
  font-size: clamp(12px, 0.95cqw, 15px);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent-bright);
  font-weight: 500;
}
.revenue-phase-when {
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.85cqw, 13px);
  letter-spacing: 0.08em;
  color: var(--text-dim);
}
.revenue-phase-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 1.85cqw, 30px);
  letter-spacing: -0.015em;
  color: var(--text);
  line-height: 1.1;
}
/* Department pill — single chip naming the surface(s) the phase owns.
   Replaces a labeled "Department/Surface" block to keep the card visually
   light. Long phase-2 string wraps to two lines inside the pill rather
   than blowing out the card width. */
.revenue-phase-pill {
  align-self: flex-start;
  margin: clamp(4px, 0.5cqh, 8px) 0 clamp(2px, 0.3cqh, 4px);
  padding: 8px 16px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border-strong);
  border-radius: 99px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(15px, 1.2cqw, 18px);
  letter-spacing: -0.005em;
  line-height: 1.3;
  color: var(--text);
  max-width: 100%;
}
.revenue-phase-pill--final {
  background: rgba(110, 123, 230, 0.12);
  border-color: rgba(110, 123, 230, 0.5);
  color: #FFFFFF;
  text-shadow:
    0 0 12px rgba(110, 123, 230, 0.25),
    0 0 24px rgba(110, 123, 230, 0.15);
}
.revenue-phase-bullets {
  list-style: none;
  /* Bottom margin guarantees breathing room before the bottom-pinned
     incumbents chip, even in the tallest card where `margin-top: auto`
     on the chip resolves to 0. Composes additively with the parent
     flex `gap`. */
  margin: clamp(4px, 0.4cqh, 6px) 0 clamp(32px, 3.2cqh, 52px);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.7cqh, 10px);
}
.revenue-phase-bullets li {
  font-family: var(--font-display);
  font-size: clamp(13px, 1.05cqw, 16px);
  line-height: 1.5;
  color: var(--text-soft);
  padding-left: 16px;
  position: relative;
}
.revenue-phase-bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-bright);
  opacity: 0.7;
}
/* Right-to-win label sits between the pill and the case bullets on the
   destination card. Mono caps, accent color — matches the visual register
   of `.revenue-phase-num` so the eye reads it as a stamp, not a sentence. */
.revenue-rtw-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: clamp(6px, 0.7cqh, 10px);
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.85cqw, 13px);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent-bright);
  font-weight: 500;
  align-self: flex-start;
}
.revenue-rtw-label::before {
  content: "";
  width: clamp(14px, 1.2cqw, 20px);
  height: 1px;
  background: var(--accent-bright);
  opacity: 0.65;
}
.revenue-phase-bullets .em {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 1.04em;
  color: var(--text);
}
/* Bold agent-persona lead-in used on Phase 3 bullets (Sales agents,
   Upsell agents, VIP amenity agents). Display sans, weight 600, white —
   reads as a label that the rest of the bullet describes. */
.revenue-phase-bullets strong {
  font-family: var(--font-display);
  font-weight: 600;
  color: #FFFFFF;
}
/* Incumbents footer chip — names the competitive set the phase
   displaces. Phase 3 uses --crowded variant tinted accent to telegraph
   that the crowded frontend is what gets absorbed last. */
.revenue-phase-incumbents {
  display: flex;
  align-items: baseline;
  gap: clamp(8px, 0.8cqw, 12px);
  /* Pin to the bottom of the card so all three "Displacing/Absorbing"
     chips align across the row regardless of how many bullets sit above. */
  margin-top: auto;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  align-self: stretch;
  flex-wrap: wrap;
}
.revenue-phase-incumbents .incumbents-label {
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.75cqw, 11px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
}
.revenue-phase-incumbents .incumbents-list {
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.9cqw, 14px);
  color: var(--text-soft);
  letter-spacing: 0.02em;
  line-height: 1.4;
}
.revenue-phase-incumbents--crowded {
  background: rgba(110, 123, 230, 0.1);
  border-color: rgba(110, 123, 230, 0.4);
}
.revenue-phase-incumbents--crowded .incumbents-label { color: var(--accent-bright); }
.revenue-phase-incumbents--crowded .incumbents-list { color: #FFFFFF; }
