/* ═══════════════════════════════════════════════════════════════════════
   REPURPOSE STUDIO: home page
   Composes with assets/css/tokens.css (colours, type, spacing, chrome).
   Gradients and glows use only --fire / --fire-soft / --void / --coal.
   Motion rule: only transform and opacity are ever animated continuously.
   Everything here has a matching kill-switch in the
   prefers-reduced-motion block at the bottom of this file, on top of the
   blanket animation-duration override tokens.css already applies.
   ═══════════════════════════════════════════════════════════════════════ */

/* ---- scroll progress bar ---- */
.scroll-progress {
  position: fixed; top: 0; left: 0; width: 100%; height: 3px;
  z-index: 60; pointer-events: none;
}
.scroll-progress span {
  display: block; height: 100%; width: 100%;
  background: var(--fire);
  transform-origin: 0 0;
  transform: scaleX(0);
}

/* ---- reveal choreography: stagger by --i, set inline per element ---- */
.reveal { transition-delay: calc(var(--i, 0) * 0.09s); }

/* Progressive enhancement: where the browser can genuinely tie opacity/
   transform to scroll position, let it, instead of the one-shot JS toggle. */
@supports (animation-timeline: view()) {
  .reveal {
    transition: none;
    animation: reveal-in linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 35%;
    animation-delay: calc(var(--i, 0) * 0.06s);
  }
  @keyframes reveal-in {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: translateY(0); }
  }
}

/* ---- hero ---- */
.hero { position: relative; overflow: hidden; padding-top: var(--s8); }

.hero-glow {
  position: absolute;
  top: -160px; left: 50%;
  width: min(1000px, 160vw); height: 900px;
  background: radial-gradient(circle at 50% 32%, var(--fire-soft) 0%, transparent 62%);
  filter: blur(30px);
  pointer-events: none; z-index: 0;
  transform: translateX(-50%) translateY(0) scale(1);
  animation: glow-breathe 12s ease-in-out infinite;
}
@keyframes glow-breathe {
  0%, 100% { transform: translateX(-50%) translateY(0) scale(1); opacity: 0.55; }
  50%      { transform: translateX(-46%) translateY(14px) scale(1.08); opacity: 1; }
}

.hero-spotlight {
  position: absolute; top: 0; left: 0;
  width: 480px; height: 480px; margin: -240px 0 0 -240px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--fire-soft) 0%, transparent 70%);
  transform: translate(var(--sx, -1000px), var(--sy, 0px));
  pointer-events: none; z-index: 0;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.hero-spotlight.is-active { opacity: 1; }

.hero-inner {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1.05fr 1fr;
  gap: var(--s6); align-items: center;
}
@media (max-width: 900px) {
  .hero-inner { grid-template-columns: 1fr; gap: var(--s5); }
}

.hero-copy h1 { margin: var(--s3) 0 var(--s4); }
.hero-ctas { display: flex; gap: var(--s3); flex-wrap: wrap; margin: var(--s4) 0 var(--s3); }
.hero-note { color: var(--ash); }

/* word-by-word headline assembly */
.assemble { overflow: visible; }
.assemble .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(16px);
  filter: blur(8px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease), filter 0.6s var(--ease);
  transition-delay: calc(var(--wi, 0) * 0.08s);
}
.reveal.in .word,
.assemble.in .word { opacity: 1; transform: none; filter: blur(0); }
/* the assemble element itself must not also slide as a block */
h1.assemble.reveal { transition: none; }
h1.assemble.reveal,
h1.assemble.reveal.in { opacity: 1; transform: none; }
@supports (animation-timeline: view()) {
  h1.assemble.reveal { animation: none; opacity: 1; transform: none; }
}

.hero-diagram { position: relative; z-index: 1; overflow-x: auto; padding: var(--s2); }
.diagram-svg { display: block; margin: 0 auto; width: clamp(480px, 100%, 640px); height: auto; }

/* fan-out flow lines, looping continuously */
.diagram-line {
  fill: none; stroke: var(--fire); stroke-width: 1.5; opacity: 0.5;
  stroke-dasharray: 6 10;
  animation: flow-dash 3.6s linear infinite;
  animation-delay: var(--ld, 0s);
}
@keyframes flow-dash { to { stroke-dashoffset: -160; } }

.diagram-spark, .diagram-halo {
  fill: var(--fire);
  offset-rotate: 0deg;
  animation: spark-move 3.6s linear infinite;
  animation-delay: var(--ld, 0s);
}
.diagram-halo { opacity: 0.18; }
@keyframes spark-move {
  0%   { offset-distance: 0%;   opacity: 0; }
  6%   { opacity: 1; }
  90%  { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}

.diagram-source circle {
  fill: var(--coal-2); stroke: var(--fire); stroke-width: 2;
  transform-box: fill-box; transform-origin: center;
  animation: source-breathe 3.6s ease-in-out infinite;
}
@keyframes source-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.06); }
}
.diagram-source-label { font-family: var(--mono); font-size: 10.5px; letter-spacing: 1px; fill: var(--fire-ink); }

.diagram-target circle {
  fill: var(--coal); stroke: var(--line-strong); stroke-width: 1.5;
  transform-box: fill-box; transform-origin: center;
  animation: target-pulse 3.6s linear infinite;
  animation-delay: var(--ld, 0s);
}
@keyframes target-pulse {
  0%, 84%, 100% { transform: scale(1); stroke: var(--line-strong); }
  90%           { transform: scale(1.22); stroke: var(--fire); }
}
.diagram-target-glyph { font-family: var(--mono); font-size: 12px; font-weight: 500; fill: var(--bone); }
.diagram-target-label { font-family: var(--mono); font-size: 13px; fill: var(--bone-dim); }

/* ---- section dividers that draw themselves in ---- */
.divider { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s4); }
.divider svg { width: 100%; height: 6px; overflow: visible; }
.divider line {
  stroke: var(--fire); stroke-width: 1.5;
  stroke-dasharray: 200; stroke-dashoffset: 200;
  transition: stroke-dashoffset 1.1s var(--ease);
}
.divider.in line { stroke-dashoffset: 0; }

/* ---- problem / marquee ---- */
.section-head { max-width: 640px; margin: 0 0 var(--s5); }
.section-head h2 { margin-top: var(--s2); }
.section-head .lede { margin-top: var(--s3); }

.marquee {
  overflow: hidden;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: var(--s3) 0;
}
.marquee-track {
  display: flex; gap: var(--s6); width: max-content;
  animation: marquee-scroll 16s linear infinite;
}
.marquee-track span {
  font-family: var(--mono); font-size: 13px; letter-spacing: 2px;
  text-transform: uppercase; color: var(--ash); white-space: nowrap;
}
@keyframes marquee-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---- gradient-border cards (ink/ember, not tokens.css flat default) ---- */
.cap-grid .card, .privacy-tiles .card, .voice-card {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--coal), var(--coal)) padding-box,
    linear-gradient(150deg, var(--fire-soft), var(--line) 60%) border-box;
}
.cap-grid .card:hover, .privacy-tiles .card:hover, .voice-card:hover {
  background:
    linear-gradient(var(--coal), var(--coal)) padding-box,
    linear-gradient(150deg, var(--fire), var(--fire-soft) 65%) border-box;
}
.cap-grid .card h3, .privacy-tiles .card h3 { margin: var(--s2) 0 0; }
.cap-grid-foot { margin-top: var(--s5); }
.text-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 13px; letter-spacing: 0.6px;
  color: var(--fire-ink); border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease);
}
.text-link:hover { border-color: var(--fire-ink); }

/* ---- 3D tilt cards ---- */
.tilt {
  transform-style: preserve-3d;
  transform: perspective(800px) rotateX(0deg) rotateY(0deg) translateY(0);
  transition: transform 0.35s var(--ease), border-color 0.35s var(--ease);
}
.tilt:hover { transition-duration: 0.08s; }

/* ---- magnetic buttons ---- */
.magnetic { transition: transform 0.25s var(--ease), background 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease); }

/* ---- sticky "how it works" ---- */
.how-inner {
  display: grid; grid-template-columns: 0.85fr 1.15fr; gap: var(--s6);
  align-items: start;
}
@media (max-width: 800px) {
  .how-inner { grid-template-columns: 1fr; }
  .how-sticky-panel { position: static !important; }
}
.how-sticky-panel {
  position: sticky; top: 100px;
  display: flex; flex-direction: column; gap: var(--s2);
}
.how-visual-num {
  font-family: var(--serif); font-size: clamp(72px, 10vw, 140px);
  line-height: 1; color: var(--fire); opacity: 0.9;
  transition: opacity 0.3s var(--ease);
}
.how-steps { list-style: none; display: flex; flex-direction: column; gap: var(--s6); padding: var(--s5) 0; }
.how-step {
  padding-left: var(--s3);
  border-left: 2px solid var(--line);
  opacity: 0.4;
  transform: translateX(0);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease), border-color 0.4s var(--ease);
}
.how-step.active { opacity: 1; border-left-color: var(--fire); transform: translateX(6px); }
.how-step .step-num { display: block; font-family: var(--mono); font-size: 13px; letter-spacing: 2px; color: var(--fire-ink); margin-bottom: var(--s2); }
.how-step h3 { margin-bottom: var(--s1); }

/* ---- your voice, twice ---- */
.voice-section .section-head h2 { max-width: 16ch; }
.voice-ring {
  display: block; width: 46px; height: 46px; border-radius: 50%;
  background: conic-gradient(from 0deg, var(--fire), var(--fire-soft) 40%, transparent 70%, var(--fire));
  margin-bottom: var(--s3);
  position: relative;
  animation: ring-spin 9s linear infinite;
}
.voice-ring::after { content: ""; position: absolute; inset: 8px; border-radius: 50%; background: var(--void); }
@keyframes ring-spin { to { transform: rotate(360deg); } }

.voice-grid { margin-top: var(--s2); }
.voice-card h3 { margin-bottom: var(--s2); }
.voice-stat {
  text-align: center; color: var(--ash);
  margin-top: var(--s5); padding-top: var(--s4);
  border-top: 1px solid var(--line);
}
.count-up { color: var(--fire); font-weight: 500; }

/* ---- runs on your machine ---- */
.privacy-tiles { margin-top: var(--s5); }

/* ---- closing cta ---- */
.cta-close {
  text-align: center; border-top: 1px solid var(--line);
  background: radial-gradient(ellipse 900px 400px at 50% 0%, var(--fire-soft), transparent 65%);
}
.cta-close-inner { max-width: 620px; margin: 0 auto; }
.cta-close h2 { margin: var(--s3) 0 var(--s4); }
.cta-close .hero-ctas { justify-content: center; }

/* ---- small screens: simplify the heaviest effects ---- */
@media (max-width: 600px) {
  /* The diagram had a 480px minimum width inside an overflow-x box, so on a
     phone the platform labels were cut off unless you scrolled the graphic
     sideways. Let it scale to fit instead, and size the type up to compensate
     for the viewBox scaling everything down with it. */
  .hero-diagram { overflow-x: visible; padding-inline: 0; }
  .diagram-svg { width: 100%; min-width: 0; }
  .diagram-target-label { font-size: 17px; }
  .diagram-target-glyph { font-size: 15px; }
  .diagram-source-label { font-size: 13px; }

  .hero-glow { animation-duration: 16s; filter: blur(20px); }
  .hero-spotlight { display: none; }
  .diagram-halo { display: none; }
  .marquee-track { animation-duration: 10s; }
  .how-sticky-panel { display: none; }
}

/* ---- reduced motion: every effect above has a kill switch here,
   on top of tokens.css's blanket animation-duration override, because
   several effects here rely on transition-delay or offset-path timing
   that override alone does not zero out. ---- */
@media (prefers-reduced-motion: reduce) {
  .hero-glow, .hero-spotlight, .diagram-line, .diagram-halo, .diagram-spark,
  .diagram-source circle, .diagram-target circle, .voice-ring,
  .marquee-track { animation: none !important; }
  .marquee-track { transform: none !important; }
  /* without the animation, spark/halo would sit as a static cluster of
     dots at the path's start next to the essay circle; hide them so the
     static diagram reads as clean lines + labelled nodes instead. */
  .diagram-spark, .diagram-halo { opacity: 0 !important; }
  .assemble .word { transition-delay: 0s !important; opacity: 1 !important; transform: none !important; filter: none !important; }
  /* scroll-timeline progress is driven by scroll position, not wall-clock
     time, so tokens.css's blanket animation-duration override does not
     stop it: kill the animation outright here. */
  .reveal { transition-delay: 0s !important; animation: none !important; opacity: 1 !important; transform: none !important; }
  .tilt { transform: none !important; }
  .magnetic { transform: none !important; }
  .hero-spotlight { display: none; }
  .scroll-progress span { transition: none !important; }
  .how-step { opacity: 1; transform: none; }
}
