// compute-story.jsx — 60-second animated short.
// Story: a trader sees a BTC/ETH long-short signal. Two parallel paths
// race side-by-side: "Other Platform" runs a fake quantum spinner and
// fires blind. EpochCore routes through the real cuStateVec dispatcher,
// gets a verifiable receipt, fires with a compute_proof attached. The
// camera ends on the receipt difference. Tagline: only at EpochCore LLC.

// ── Palette (from QP brand system) ────────────────────────────
const QC = {
  bg:           '#050507',
  surface:      '#0e0f12',
  surfaceHi:    '#171a20',
  border:       'rgba(244,244,240,0.10)',
  borderHi:     'rgba(244,244,240,0.22)',
  text:         '#F4F4F0',
  muted:        'rgba(244,244,240,0.55)',
  mutedDim:     'rgba(244,244,240,0.30)',
  green:        '#42f977',   // Velocity Teal
  greenSoft:    'rgba(66,249,119,0.10)',
  red:          '#e72020',   // Oscillation Crimson
  redSoft:      'rgba(231,32,32,0.10)',
  cyan:         '#23c8e9',   // Calibration Cyan — compute
  cyanSoft:     'rgba(35,200,233,0.10)',
  amber:        '#a59523',   // Yield Gold
  amberSoft:    'rgba(165,149,35,0.10)',
  orange:       '#b05222',   // Consensus Orange
  magenta:      '#c6207a',   // Session Magenta
  violet:       '#a334f3',   // Swarm Violet
  indigo:       '#28239b',   // Coherence Indigo
};

const GEIST  = 'Geist, sans-serif';
const GMONO  = '"Geist Mono", ui-monospace, monospace';

// ── Atoms ─────────────────────────────────────────────────────
function Mono({ children, color = QC.muted, size = 12, style = {} }) {
  return (
    <span style={{
      fontFamily: GMONO, fontSize: size, letterSpacing: 0.6,
      textTransform: 'uppercase', color, ...style,
    }}>{children}</span>
  );
}

function PulseDot({ color = QC.green, size = 8 }) {
  return (
    <span style={{
      display: 'inline-block', width: size, height: size, borderRadius: '50%',
      background: color, boxShadow: `0 0 0 4px ${color}33`,
      animation: 'pulse-soft 1.4s ease-out infinite',
    }}/>
  );
}

// ── Title cards ───────────────────────────────────────────────
function TitleCard({ eyebrow, title, subtitle, start, end, fadeIn = 0.4, fadeOut = 0.6 }) {
  return (
    <Sprite start={start} end={end} fadeIn={fadeIn} fadeOut={fadeOut}>
      <div style={{
        position: 'absolute', inset: 0,
        display: 'flex', flexDirection: 'column',
        alignItems: 'center', justifyContent: 'center',
        textAlign: 'center', padding: 80, background: QC.bg,
      }}>
        {eyebrow && (
          <Mono color={QC.cyan} size={14} style={{ marginBottom: 24, letterSpacing: 3 }}>
            {eyebrow}
          </Mono>
        )}
        <h1 style={{
          fontFamily: GEIST, fontWeight: 600,
          fontSize: 88, letterSpacing: -3, lineHeight: 1.02,
          margin: 0, color: QC.text, maxWidth: 1400,
        }}>{title}</h1>
        {subtitle && (
          <p style={{
            marginTop: 28, fontFamily: GEIST, fontSize: 22, lineHeight: 1.5,
            color: QC.muted, letterSpacing: -0.2, maxWidth: 900,
          }}>{subtitle}</p>
        )}
      </div>
    </Sprite>
  );
}

// ── Scene 1 — Establishing: BTC/ETH terminal + pair signal ────
function SceneEstablishing({ start, end }) {
  return (
    <Sprite start={start} end={end} fadeIn={0.4} fadeOut={0.5}>
      <SceneEstablishingInner start={start}/>
    </Sprite>
  );
}
function SceneEstablishingInner({ start }) {
  const t = useTime() - start;
  // BTC & ETH prices tick over the first 4s, then a pair-signal banner slides in.
  const btcPrice = (62_400 + Math.sin(t * 2.2) * 60 + t * 8).toFixed(0);
  const ethPrice = (3_120 + Math.sin(t * 1.7) * 12 + t * 1.2).toFixed(0);
  const signalIn = animate({ from: 60, to: 0, start: 3.4, end: 4.4, ease: Easing.easeOutBack })(t);
  const signalOp = animate({ from: 0, to: 1, start: 3.4, end: 4.4 })(t);

  // Subtle camera zoom — never static
  const zoom = animate({ from: 1, to: 1.04, start: 0, end: 8 })(t);

  return (
    <div style={{
      position: 'absolute', inset: 0, background: QC.bg,
      display: 'grid', placeItems: 'center',
      transform: `scale(${zoom})`, transformOrigin: 'center center',
    }}>
      <div style={{
        width: 1640, height: 880, background: QC.surface,
        border: `1px solid ${QC.border}`, position: 'relative',
        padding: 48, display: 'flex', flexDirection: 'column', gap: 40,
      }}>
        {/* Header */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <PulseDot color={QC.green}/>
            <Mono color={QC.text} size={14}>TRADER · LAKE NORMAN · NC</Mono>
          </div>
          <Mono color={QC.mutedDim} size={12}>09:38:14 ET · MAY 21 2026</Mono>
        </div>

        {/* Two price tiles side by side */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28 }}>
          <PriceTile symbol="BTC/USD" price={`$${Number(btcPrice).toLocaleString()}`}
            delta="+0.42%" color={QC.green} side="LONG"/>
          <PriceTile symbol="ETH/USD" price={`$${Number(ethPrice).toLocaleString()}`}
            delta="-0.18%" color={QC.red} side="SHORT"/>
        </div>

        {/* Pair-signal banner */}
        <div style={{
          marginTop: 'auto',
          opacity: signalOp,
          transform: `translateY(${signalIn}px)`,
          padding: '24px 32px',
          background: QC.surfaceHi, border: `1px solid ${QC.cyan}`,
          display: 'flex', alignItems: 'center', gap: 24,
        }}>
          <div style={{
            width: 56, height: 56, borderRadius: 28,
            background: QC.cyanSoft, border: `1px solid ${QC.cyan}`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: QC.cyan, fontFamily: GMONO, fontSize: 22, fontWeight: 600,
          }}>↻</div>
          <div style={{ flex: 1 }}>
            <Mono color={QC.cyan} size={11}>PAIR-TRADE SIGNAL · EXPIRES IN 18 SECONDS</Mono>
            <div style={{
              fontFamily: GEIST, fontSize: 28, fontWeight: 600, color: QC.text,
              letterSpacing: -0.6, marginTop: 6,
            }}>
              Long BTC · Short ETH · 1.0× / 1.0×
              <span style={{ color: QC.muted, fontWeight: 400, fontSize: 18, marginLeft: 12 }}>
                target ratio break · 30-min hold
              </span>
            </div>
          </div>
          <Mono color={QC.text} size={13}>NEEDS PROOF →</Mono>
        </div>
      </div>
    </div>
  );
}

function PriceTile({ symbol, price, delta, color, side }) {
  return (
    <div style={{
      padding: 28, background: QC.surfaceHi, border: `1px solid ${QC.border}`,
      display: 'flex', flexDirection: 'column', gap: 14,
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <Mono color={QC.muted} size={12}>{symbol}</Mono>
        <Mono color={color} size={11} style={{
          padding: '4px 10px', border: `1px solid ${color}`,
          background: color + '1a',
        }}>{side}</Mono>
      </div>
      <div style={{
        fontFamily: GMONO, fontSize: 56, fontWeight: 500,
        color: QC.text, letterSpacing: -1.2, lineHeight: 1,
      }}>{price}</div>
      <Mono color={color} size={14}>{delta} · last 1h</Mono>
      {/* tiny sparkline simulation */}
      <svg width="100%" height="40" viewBox="0 0 400 40" style={{ display: 'block' }}>
        <path d="M0 28 L 50 22 L 100 30 L 150 14 L 200 20 L 250 8 L 300 18 L 350 6 L 400 12"
          stroke={color} strokeWidth="2" fill="none" opacity="0.85"/>
      </svg>
    </div>
  );
}

// ── Scene 2 — Other Platform: fake quantum spinner, blind fire ─
function SceneOther({ start, end }) {
  return (
    <Sprite start={start} end={end} fadeIn={0.45} fadeOut={0.55}>
      <SceneOtherInner start={start}/>
    </Sprite>
  );
}
function SceneOtherInner({ start }) {
  const t = useTime() - start;
  const showSpin   = t > 0.5 && t < 7.5;
  const showFired  = t > 7.5;
  const confInOp   = animate({ from: 0, to: 1, start: 4.5, end: 5.5 })(t);
  const confValue  = Math.min(1, Math.max(0, animate({ from: 0, to: 1, start: 5, end: 7 })(t)));
  // The "confidence" reads as a fake number that just rises out of nothing.
  const fakeConf   = (0.42 + confValue * 0.49).toFixed(2);

  return (
    <div style={{
      position: 'absolute', inset: 0, background: QC.bg,
      display: 'grid', placeItems: 'center',
    }}>
      <div style={{
        width: 1640, height: 880, background: '#1a0a0a',
        border: `1px solid ${QC.red}`, position: 'relative',
        padding: 48, display: 'flex', flexDirection: 'column', gap: 28,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 8 }}>
          <Mono color={QC.red} size={14} style={{ padding: '6px 14px', border: `1px solid ${QC.red}`, background: QC.redSoft }}>
            OTHER PLATFORM · GENERIC AI
          </Mono>
          <Mono color={QC.mutedDim} size={12}>placeholder.example.com</Mono>
        </div>

        <h2 style={{
          fontFamily: GEIST, fontSize: 52, fontWeight: 600, margin: 0,
          color: QC.text, letterSpacing: -1.6, lineHeight: 1.05,
        }}>
          Running <span style={{ color: QC.red }}>QUANTUM AI™</span>…
        </h2>

        {/* Big fake spinner */}
        {showSpin && (
          <div style={{
            flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
            gap: 60, marginTop: 30,
          }}>
            <div style={{ animation: 'spin 1.4s linear infinite' }}>
              <svg width="220" height="220" viewBox="0 0 100 100">
                <circle cx="50" cy="50" r="42" fill="none" stroke={QC.red} strokeWidth="3"
                  strokeDasharray="80 200" opacity="0.5"/>
                <circle cx="50" cy="50" r="32" fill="none" stroke={QC.red} strokeWidth="2"
                  strokeDasharray="40 200" opacity="0.7"/>
                <circle cx="50" cy="50" r="22" fill="none" stroke={QC.red} strokeWidth="1.5"
                  opacity="0.4"/>
              </svg>
            </div>
            <div>
              <Mono color={QC.muted} size={13}>AI MAGIC CONFIDENCE</Mono>
              <div style={{
                fontFamily: GMONO, fontSize: 96, fontWeight: 500, color: QC.text,
                letterSpacing: -2, opacity: confInOp,
              }}>{fakeConf}</div>
              <Mono color={QC.red} size={12} style={{ animation: 'blink 1s linear infinite' }}>
                sources · undisclosed
              </Mono>
            </div>
          </div>
        )}

        {/* The "fire" — order goes out with no audit trail */}
        {showFired && (
          <div style={{
            flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center',
            animation: 'pulse-soft 1.6s ease-out infinite',
          }}>
            <div style={{
              padding: '20px 24px', background: QC.surfaceHi,
              border: `1px solid ${QC.red}`,
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            }}>
              <Mono color={QC.red} size={14}>ORDER SENT TO BROKER</Mono>
              <Mono color={QC.mutedDim} size={11}>no receipt · no proof · no audit</Mono>
            </div>
            <div style={{
              marginTop: 20, padding: 28, background: '#100404',
              border: `1px dashed ${QC.red}`, display: 'flex', gap: 24,
            }}>
              <div style={{ flex: 1 }}>
                <Mono color={QC.muted} size={11}>COMPUTE TRAIL</Mono>
                <div style={{ marginTop: 10, fontFamily: GMONO, fontSize: 18,
                  color: QC.red, letterSpacing: 0.4 }}>—— null ——</div>
              </div>
              <div style={{ flex: 1 }}>
                <Mono color={QC.muted} size={11}>VERIFIABLE BY</Mono>
                <div style={{ marginTop: 10, fontFamily: GMONO, fontSize: 18,
                  color: QC.red, letterSpacing: 0.4 }}>—— nobody ——</div>
              </div>
              <div style={{ flex: 1 }}>
                <Mono color={QC.muted} size={11}>IF WRONG, RECOURSE</Mono>
                <div style={{ marginTop: 10, fontFamily: GMONO, fontSize: 18,
                  color: QC.red, letterSpacing: 0.4 }}>—— none ——</div>
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Scene 3 — EpochCore: real dispatcher call, real receipt ───
function SceneEpochCore({ start, end }) {
  return (
    <Sprite start={start} end={end} fadeIn={0.5} fadeOut={0.55}>
      <SceneEpochCoreInner start={start}/>
    </Sprite>
  );
}
function SceneEpochCoreInner({ start }) {
  const t = useTime() - start;

  // Reveal each pipeline step at staggered times
  const stages = [
    { from: 0.6,  label: 'PANEL VOTE',  desc: '25 verifiers · 23 agree',           color: QC.green,   tag: '23 / 25 · CLEARED · 187ms' },
    { from: 3.0,  label: 'COMPUTE',     desc: 'cuStateVec @ Bell circuit · 1024 shots', color: QC.cyan, tag: 'backend=cusv · 87ms · 5e504bfd' },
    { from: 6.0,  label: 'RISK CHECK',  desc: '10 checks · liquidity · vol · size · pattern', color: QC.amber, tag: 'all clear · 64ms' },
    { from: 9.0,  label: 'BROKER',      desc: 'Alpaca / MooMoo · order accepted',  color: QC.violet,  tag: 'ord_a3b2-9c1f · accepted' },
    { from: 12.0, label: 'RECEIPT',     desc: 'Merkle root anchored to Base',      color: QC.green,   tag: 'block #46,270,762 · signed' },
  ];

  // Camera focuses on compute (stage 2) heavily — that's the differentiator
  const zoomedIntoCompute = t > 3.0 && t < 6.5;

  return (
    <div style={{
      position: 'absolute', inset: 0, background: QC.bg,
      display: 'grid', placeItems: 'center',
    }}>
      <div style={{
        width: 1640, height: 880, background: QC.surface,
        border: `1px solid ${QC.green}`, position: 'relative',
        padding: 48, display: 'flex', flexDirection: 'column', gap: 24,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 8 }}>
          <Mono color={QC.green} size={14} style={{ padding: '6px 14px', border: `1px solid ${QC.green}`, background: QC.greenSoft }}>
            EPOCHCORE TRADEXCHANGE
          </Mono>
          <Mono color={QC.mutedDim} size={12}>tradexchange.cc · MULTI-BROKER · VERIFIED PICKS</Mono>
        </div>

        <h2 style={{
          fontFamily: GEIST, fontSize: 44, fontWeight: 600, margin: 0,
          color: QC.text, letterSpacing: -1.4, lineHeight: 1.05,
        }}>
          Same trade. <span style={{ color: QC.green }}>Five real proofs.</span>
        </h2>

        {/* The pipeline */}
        <div style={{
          flex: 1, display: 'flex', flexDirection: 'column', gap: 12, marginTop: 8,
        }}>
          {stages.map((stage, i) => {
            const op = animate({ from: 0, to: 1, start: stage.from, end: stage.from + 0.5 })(t);
            const dy = animate({ from: 20, to: 0, start: stage.from, end: stage.from + 0.5, ease: Easing.easeOutBack })(t);
            const isFocus = zoomedIntoCompute && i === 1;
            const isCompute = i === 1;
            const isLive = t >= stage.from && t < stage.from + 1.2;
            return (
              <div key={i} style={{
                opacity: op, transform: `translateY(${dy}px) scale(${isFocus ? 1.05 : 1})`,
                transformOrigin: 'left center',
                transition: 'transform .4s cubic-bezier(.2,.7,.3,1)',
                display: 'grid', gridTemplateColumns: '52px 220px 1fr auto',
                gap: 18, alignItems: 'center',
                padding: '18px 22px',
                background: isFocus ? QC.cyanSoft : QC.surfaceHi,
                border: `1px solid ${isFocus ? QC.cyan : QC.border}`,
                boxShadow: isFocus ? `0 0 60px -20px ${QC.cyan}99` : 'none',
              }}>
                <Mono color={stage.color} size={12} style={{ letterSpacing: 1 }}>0{i+1}</Mono>
                <div>
                  <div style={{
                    fontFamily: GEIST, fontSize: 19, fontWeight: 600,
                    color: QC.text, letterSpacing: -0.2,
                  }}>{stage.label}</div>
                  {isCompute && (
                    <Mono color={QC.cyan} size={9.5} style={{ letterSpacing: 1.2, marginTop: 4 }}>
                      ← THE DIFFERENCE
                    </Mono>
                  )}
                </div>
                <div style={{
                  fontFamily: GEIST, fontSize: 15, color: QC.muted,
                  letterSpacing: -0.1,
                }}>{stage.desc}</div>
                <Mono color={stage.color} size={12} style={{
                  padding: '6px 12px',
                  border: `1px solid ${stage.color}`,
                  background: stage.color + (isLive ? '22' : '10'),
                  letterSpacing: 0.6,
                  transition: 'background .3s ease',
                }}>{stage.tag}</Mono>
              </div>
            );
          })}
        </div>
      </div>

      {/* Compute call-out overlay during the focus moment */}
      {zoomedIntoCompute && (
        <ComputeCallout/>
      )}
    </div>
  );
}

function ComputeCallout() {
  const t = useTime();
  // Lives 3-6.5s of scene 3 absolute — animations.jsx clamps useTime to the full timeline,
  // so we just lock it to a quick fade based on local computation.
  return (
    <div style={{
      position: 'absolute',
      right: 100, bottom: 130,
      width: 560,
      padding: 26,
      background: QC.surfaceHi,
      border: `1px solid ${QC.cyan}`,
      boxShadow: `0 30px 80px -20px ${QC.cyan}88, 0 0 0 4px ${QC.cyan}22`,
      animation: 'pulse-soft 2.4s ease-out infinite',
    }}>
      <Mono color={QC.cyan} size={11} style={{ letterSpacing: 1.6 }}>REAL GPU CALL · NOT MARKETING</Mono>
      <div style={{
        marginTop: 12, fontFamily: GMONO, fontSize: 14, lineHeight: 1.65,
        color: QC.text, letterSpacing: 0.2, whiteSpace: 'pre',
      }}>
{`POST cuquantum.epochcoreqcs.com/v1/run
authorization: Bearer ****
{
  "circuit": "<OpenQASM 2.0>",
  "shots":   1024,
  "backend": "cusv"
}

→ counts: { "00": 522, "11": 502 }
→ backend: cusv · 87ms
→ commit:  5e504bfd`}
      </div>
      <Mono color={QC.muted} size={10} style={{ display: 'block', marginTop: 10, letterSpacing: 0.8 }}>
        github.com/QuantumSwarms/epochcore-cusv-dispatcher
      </Mono>
    </div>
  );
}

// ── Scene 4 — Side-by-side receipt comparison ────────────────
function SceneCompare({ start, end }) {
  return (
    <Sprite start={start} end={end} fadeIn={0.5} fadeOut={0.55}>
      <SceneCompareInner start={start}/>
    </Sprite>
  );
}
function SceneCompareInner({ start }) {
  const t = useTime() - start;
  const slideIn = animate({ from: 80, to: 0, start: 0.4, end: 1.4, ease: Easing.easeOutCubic })(t);
  const fadeIn = animate({ from: 0, to: 1, start: 0.4, end: 1.4 })(t);

  return (
    <div style={{
      position: 'absolute', inset: 0, background: QC.bg, padding: 60,
      display: 'flex', flexDirection: 'column', gap: 40,
    }}>
      <div style={{ textAlign: 'center', opacity: fadeIn }}>
        <Mono color={QC.cyan} size={13} style={{ letterSpacing: 3 }}>BOTH ORDERS FILLED.</Mono>
        <h2 style={{
          fontFamily: GEIST, fontSize: 56, fontWeight: 600, margin: '12px 0 0',
          color: QC.text, letterSpacing: -1.8,
        }}>
          Only one left a <span style={{ color: QC.green }}>proof</span>.
        </h2>
      </div>

      <div style={{
        flex: 1, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 32,
        transform: `translateY(${slideIn}px)`, opacity: fadeIn,
      }}>
        <ReceiptColumn title="OTHER PLATFORM · RECEIPT" tone="bad"/>
        <ReceiptColumn title="EPOCHCORE · RECEIPT" tone="good"/>
      </div>
    </div>
  );
}

function ReceiptColumn({ title, tone }) {
  const good = tone === 'good';
  const accent = good ? QC.green : QC.red;
  const accentSoft = good ? QC.greenSoft : QC.redSoft;
  const rows = good ? [
    ['VERDICT',        'CLEARED',                         QC.green],
    ['AGREEMENT',      '23 / 25 verifiers · 92%',         QC.text],
    ['COMPUTE PROOF',  'backend=cusv · 87ms · 5e504bfd',  QC.cyan],
    ['RISK CHECK',     'all 10 checks passed',            QC.amber],
    ['BROKER',         'Alpaca · ord_a3b2-9c1f',          QC.violet],
    ['BASE BLOCK',     '#46,270,762',                     QC.text],
    ['MERKLE ROOT',    '0xMR…ab (signed)',                QC.text],
    ['CAN BE REPLAYED','YES — by anyone, on their GPU',   QC.green],
  ] : [
    ['VERDICT',        'FILLED',                          QC.red],
    ['CONFIDENCE',     '0.91 (source undisclosed)',       QC.red],
    ['COMPUTE PROOF',  '— null —',                        QC.red],
    ['RISK CHECK',     '— null —',                        QC.red],
    ['BROKER',         'order sent',                      QC.muted],
    ['BLOCK',          '— null —',                        QC.red],
    ['ROOT',           '— null —',                        QC.red],
    ['CAN BE REPLAYED','NO',                              QC.red],
  ];

  return (
    <div style={{
      background: QC.surface, border: `1px solid ${accent}`,
      padding: '32px 36px', display: 'flex', flexDirection: 'column', gap: 16,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <Mono color={accent} size={13} style={{
          padding: '6px 14px', border: `1px solid ${accent}`, background: accentSoft,
          letterSpacing: 1.4,
        }}>{title}</Mono>
        {good && <PulseDot color={QC.green}/>}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 0, marginTop: 6 }}>
        {rows.map(([k, v, c], i) => (
          <div key={k} style={{
            display: 'grid', gridTemplateColumns: '180px 1fr', gap: 16,
            padding: '14px 0', borderTop: i === 0 ? 'none' : `1px solid ${QC.border}`,
          }}>
            <Mono color={QC.muted} size={11}>{k}</Mono>
            <span style={{
              fontFamily: GMONO, fontSize: 16, color: c, letterSpacing: 0.4,
            }}>{v}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Scene 5 — Closing tagline ─────────────────────────────────
function SceneClose({ start, end }) {
  return (
    <Sprite start={start} end={end} fadeIn={0.6} fadeOut={0.4}>
      <SceneCloseInner start={start}/>
    </Sprite>
  );
}
function SceneCloseInner({ start }) {
  const t = useTime() - start;
  const lineY1 = animate({ from: 40, to: 0, start: 0.4, end: 1.6, ease: Easing.easeOutCubic })(t);
  const lineY2 = animate({ from: 40, to: 0, start: 1.2, end: 2.4, ease: Easing.easeOutCubic })(t);
  const op1    = animate({ from: 0, to: 1, start: 0.4, end: 1.6 })(t);
  const op2    = animate({ from: 0, to: 1, start: 1.2, end: 2.4 })(t);
  const op3    = animate({ from: 0, to: 1, start: 2.4, end: 3.4 })(t);

  return (
    <div style={{
      position: 'absolute', inset: 0, background: QC.bg,
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      gap: 28, padding: 80,
    }}>
      {/* Stylized mark — concentric rings, brand-like */}
      <div style={{ opacity: op1, transform: `translateY(${lineY1}px)` }}>
        <svg width="120" height="120" viewBox="0 0 120 120">
          <circle cx="60" cy="60" r="50" fill="none" stroke={QC.green} strokeWidth="2.5"
            strokeDasharray="10 5"/>
          <circle cx="60" cy="60" r="32" fill="none" stroke={QC.cyan} strokeWidth="1.5" opacity="0.6"/>
          <circle cx="60" cy="60" r="6" fill={QC.green}/>
        </svg>
      </div>

      <div style={{ opacity: op1, transform: `translateY(${lineY1}px)`, textAlign: 'center' }}>
        <Mono color={QC.cyan} size={14} style={{ letterSpacing: 3 }}>VERIFIABLE COMPUTE</Mono>
      </div>

      <h1 style={{
        margin: 0, fontFamily: GEIST, fontWeight: 600,
        fontSize: 96, letterSpacing: -3.5, lineHeight: 0.98, color: QC.text,
        opacity: op2, transform: `translateY(${lineY2}px)`, textAlign: 'center',
      }}>
        Only at <span style={{
          fontFamily: GEIST, fontStyle: 'italic', fontWeight: 500, color: QC.green,
        }}>EpochCore LLC</span>.
      </h1>

      <p style={{
        marginTop: 12, fontFamily: GEIST, fontSize: 22, color: QC.muted,
        letterSpacing: -0.2, opacity: op3, maxWidth: 980, textAlign: 'center', lineHeight: 1.5,
      }}>
        Every trade carries a receipt. Every receipt cites the GPU dispatcher commit it ran against. Replay any of them — same circuit, same counts, same answer. That's the difference.
      </p>

      <div style={{
        marginTop: 32, opacity: op3,
        display: 'flex', alignItems: 'center', gap: 22,
        fontFamily: GMONO, fontSize: 13, color: QC.mutedDim, letterSpacing: 1,
      }}>
        <span>tradexchange.cc</span>
        <span style={{ width: 1, height: 16, background: QC.borderHi }}/>
        <span>cuquantum.epochcoreqcs.com</span>
        <span style={{ width: 1, height: 16, background: QC.borderHi }}/>
        <span>chain.epochcoreqcs.com/v1/verify</span>
      </div>
    </div>
  );
}

// ── Timestamp label updater (per the animation skill) ─────────
function TimestampLabel() {
  const t = useTime();
  React.useEffect(() => {
    const root = document.getElementById('story-root');
    if (root) root.dataset.screenLabel = `t=${Math.floor(t)}s`;
  }, [Math.floor(t)]);
  return null;
}

// ── App ───────────────────────────────────────────────────────
function App() {
  // Scene boundaries (seconds):
  // 0–8     Establishing — BTC/ETH + pair signal
  // 8–18    Other Platform — fake quantum + blind fire
  // 18–34   EpochCore — 5-stage real pipeline with compute call-out at 21-24.5
  // 34–48   Side-by-side receipt comparison
  // 48–58   Tagline / close
  const DURATION = 58;
  return (
    <div id="story-root" data-screen-label="t=0s" style={{
      width: '100vw', minHeight: '100vh',
      background: QC.bg, color: QC.text,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <Stage width={1920} height={1080} duration={DURATION} background={QC.bg}>
        <TimestampLabel/>
        <SceneEstablishing start={0}    end={8}/>
        <SceneOther        start={8}    end={18}/>
        <SceneEpochCore    start={18}   end={34}/>
        <SceneCompare      start={34}   end={48}/>
        <SceneClose        start={48}   end={58}/>
      </Stage>
      {/* E.4 — story freshness signal */}
      <div style={{
        position: 'fixed', bottom: 12, left: 0, right: 0,
        textAlign: 'center',
        fontFamily: '"Geist Mono", ui-monospace, monospace',
        fontSize: 10, color: 'rgba(244,244,240,0.45)',
        letterSpacing: 0.6, pointerEvents: 'none',
      }}>
        This story was computed on {new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })} · New stories generated each trading day
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
