// ════════════════════════════════════════════════════════════════
// Agentic Forge · The Compounding Effect · v2 · 180s
// STEADY-STATE INTELLIGENCE SURFACE TOUR.
// Day 234 of using AF. Not a journey through time — a tour of
// what the framework knows now.
// 4 artifact beats × ~36s each:
//   beat A: Decision graph
//   beat B: Calibration intelligence
//   beat C: Skill / pattern catalog
//   beat D: Opportunity intelligence
// Each beat: Phase 1 (~18s) reveal artifact · Phase 2 (~18s) 4 enabled cards
// 0-12s    Cold open
// 12-48s   Beat A: Decision graph
// 48-84s   Beat B: Calibration
// 84-120s  Beat C: Skills
// 120-156s Beat D: Opportunities
// 156-180s Synthesis + close
// ════════════════════════════════════════════════════════════════

const T = window.TOKENS;
const CE = {
  carbon:'#080c14', charcoal:'#13151a', panel:'#1c1e24', line:'#2a2d35',
  white:'#fff', gray:'#a0a4ab', dim:'#6e7178', sub:'#535660',
  green:'#00da41', greenDim:'#00b836', blue:'#5b8def', amber:'#f4b400', red:'#ff6b6b', purple:'#8b6fe8',
};
const ease = t => t<=0?0:t>=1?1:1-Math.pow(1-t,3);
const fade = (time, start, dur=0.2) => Math.max(0, Math.min(1, ease((time-start)/dur)));
const slideUp = (time, start, dur=0.2, dist=4) => (1 - fade(time, start, dur)) * dist;
const cap = (n, max) => Math.min(n, max);
// Gradient — display-size emphasized green text. Reference as the "gradient" style.
const gradientStyle = {
  background: 'linear-gradient(135deg, #00E87B 0%, #00da41 50%, #00B35A 100%)',
  WebkitBackgroundClip: 'text',
  WebkitTextFillColor: 'transparent',
  backgroundClip: 'text',
  textShadow: 'none',
};
// Eyebrow — small uppercase accent label above a heading.
const eyebrowStyle = {
  fontSize: 18, fontWeight: 500, color: '#00da41',
  textTransform: 'uppercase', letterSpacing: '0.1em',
  marginBottom: 4, minHeight: 56,
  display: 'flex', alignItems: 'center', justifyContent: 'center',
};

// ─── shared chrome ───────────────────────────────────────────
function ISChrome({ section, sectionRight, children }) {
  return (
    <div style={{ position:'absolute', inset:0, background:CE.carbon, color:CE.white, fontFamily:T.sans, display:'flex', flexDirection:'column' }}>
      <div style={{ height:50, borderBottom:`1px solid ${CE.line}`, display:'flex', alignItems:'center', padding:'0 32px', gap:14, flexShrink:0 }}>
        <span style={{ width:8, height:8, borderRadius:4, background:CE.green }} />
        <span style={{ fontSize:14, color:'#fff', fontWeight:500 }}>Agentic Forge</span>
        <span style={{ color:CE.dim, margin:'0 4px' }}>·</span>
        <span style={{ fontSize:12, color:CE.gray, fontFamily:T.mono }}>{section}</span>
        {sectionRight && <span style={{ marginLeft:'auto', fontSize:11, color:CE.dim, fontFamily:T.mono }}>{sectionRight}</span>}
      </div>
      <div style={{ flex:1, position:'relative', minHeight:0 }}>{children}</div>
    </div>
  );
}
function AFChip({ skill, start = 0 }) {
  const time = useTime();
  const o = fade(time, start, 0.18);
  return (
    <div style={{
      display:'inline-flex', alignItems:'center', gap:8,
      background:CE.panel, borderLeft:`2px solid ${CE.green}`,
      borderRadius:4, padding:'5px 11px',
      fontFamily:T.sans, fontSize:11, fontWeight:500, color:CE.gray,
      opacity:o, transform:`translateY(${slideUp(time,start)}px)`,
    }}>
      <span style={{ width:6, height:6, borderRadius:3, background:CE.green, flexShrink:0 }} />
      <span>Agentic Forge · {skill}</span>
    </div>
  );
}
function Card({ children, accent, start = 0, padding = 18, style }) {
  const time = useTime();
  const o = fade(time, start, 0.25);
  return (
    <div style={{
      position:'relative', background:CE.charcoal, border:`1px solid ${CE.line}`,
      borderRadius:8, padding, fontFamily:T.sans, color:CE.white,
      opacity:o, transform:`translateY(${slideUp(time,start, 0.25, 6)}px)`, overflow:'hidden',
      ...style,
    }}>
      {accent && <div style={{ position:'absolute', left:0, top:0, bottom:0, width:3, background:accent }} />}
      {children}
    </div>
  );
}

// ─── Subtitles ────────────────────────────────────────────────
const SUBS = [
  { t:1.0,   end:7.0,   text:"Day 234 with Agentic Forge." },
  { t:7.5,   end:11.5,  text:"This is what the framework knows now." },
  { t:14.0,  end:20.0,  text:"Every decision the team has made — connected." },
  { t:30.0,  end:38.0,  text:"Question something today, and the framework cites the eight reasons it was rejected in March." },
  { t:50.0,  end:58.0,  text:"The framework knows how this team estimates." },
  { t:66.0,  end:74.0,  text:"Skew by service, by risk, by engineer — calibrated against 142 prior stories." },
  { t:86.0,  end:93.0,  text:"Patterns the team chose, with bypass rates and override telemetry." },
  { t:103.0, end:111.0, text:"When the framework's recommendation gets ignored too often, it learns and re-tunes." },
  { t:122.0, end:130.0, text:"Opportunities surface themselves." },
  { t:138.0, end:146.0, text:"Twelve agents watching for re-litigation, scope creep, debt clusters, calibration drift." },
  { t:158.0, end:165.0, text:"Every decision. Every estimate. Every pattern. Every opportunity." },
  { t:166.0, end:174.0, text:"Written down. Connected. Re-tuned." },
  { t:175.0, end:179.5, text:"That's the compounding effect." },
];
function Subtitles() {
  const time = useTime();
  const a = SUBS.find(s => time >= s.t && time <= s.end);
  if (!a) return null;
  const words = a.text.split(' ');
  const lines=[]; let cur='';
  for (const w of words) {
    const next = cur ? cur+' '+w : w;
    if (next.length > 50) { lines.push(cur); cur = w; } else cur = next;
  }
  if (cur) lines.push(cur);
  return (
    <div style={{ position:'absolute', left:0, right:0, bottom:60, display:'flex', justifyContent:'center', pointerEvents:'none', zIndex:200 }}>
      <div style={{ background:'rgba(28,30,36,0.82)', borderRadius:4, padding:'8px 14px', maxWidth:'76%' }}>
        {lines.map((l,i) => (
          <div key={i} style={{ fontFamily:T.sans, fontWeight:500, fontSize:21, color:'#fff', textAlign:'center', lineHeight:1.35 }}>{l}</div>
        ))}
      </div>
    </div>
  );
}

// ─── Beat header pill (in-frame, top-left) ───────────────────
function BeatHeader({ beat, title, start, hold }) {
  const time = useTime();
  const t = time - start;
  const o = t < 0.4 ? t/0.4 : t < hold ? 1 : t < hold + 0.4 ? 1 - (t - hold)/0.4 : 0;
  if (o <= 0) return null;
  return (
    <div style={{ position:'absolute', top:24, left:32, opacity:Math.max(0,o), zIndex:50, display:'flex', alignItems:'center', gap:10 }}>
      <div style={{ fontFamily:T.mono, fontSize:11, color:CE.green, letterSpacing:'0.16em', textTransform:'uppercase', fontWeight:600 }}>BEAT {beat}</div>
      <span style={{ color:CE.dim }}>·</span>
      <div style={{ fontFamily:T.sans, fontSize:14, color:CE.white, fontWeight:500 }}>{title}</div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════
// COLD OPEN (0-12s)
// ════════════════════════════════════════════════════════════════
function ColdOpen() {
  const time = useTime();
  const dayO    = fade(time, 1.0, 0.7);
  const lineO   = fade(time, 2.5, 0.7);
  const subO    = fade(time, 4.0, 0.6);
  const exitO   = time < 9.5 ? 1 : time < 11.5 ? 1 - (time - 9.5)/2 : 0;
  const bgO     = fade(time, 0, 0.6);
  return (
    <div style={{ position:'absolute', inset:0, background:CE.carbon, display:'flex', alignItems:'center', justifyContent:'center', opacity:exitO }}>
      <div style={{ position:'absolute', inset:0, background:'url(/assets/images/bg_hero.jpg) center/cover no-repeat', opacity:bgO }} />
      <div style={{ position:'relative', textAlign:'center', fontFamily:T.sans, color:CE.white, textShadow:'0 2px 12px rgba(0,0,0,0.7)' }}>
        <div style={{ ...eyebrowStyle, opacity:dayO, marginBottom:36 }}>
          The Compounding Effect
        </div>
        <div style={{ fontSize:72, fontWeight:500, color:CE.white, letterSpacing:'-0.01em', lineHeight:1.15, opacity:lineO, transform:`translateY(${(1-lineO)*8}px)` }}>
          Day 234 with <span style={gradientStyle}>Agentic Forge</span>.
        </div>
        <div style={{ fontSize:32, fontWeight:200, color:CE.white, marginTop:30, lineHeight:1.4, opacity:subO, transform:`translateY(${(1-subO)*8}px)` }}>
          This is what the framework knows now.
        </div>
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════
// BEAT A — DECISION GRAPH (12-48s)
// Phase A1 (12-30s): graph reveals — 38 nodes connected, color-coded
// Phase A2 (30-48s): 4 cards showing what the graph enables
// ════════════════════════════════════════════════════════════════

// Decision-graph data: 38 decisions, 4 categories
const GRAPH_NODES = (() => {
  const cats = ['arch','data','sec','perf'];
  const colors = { arch: CE.green, data: CE.blue, sec: CE.amber, perf: CE.purple };
  const seed = (i) => { const x = Math.sin(i*12.9898+7)*43758.5453; return x - Math.floor(x); };
  const arr = [];
  for (let i = 0; i < 38; i++) {
    const cat = cats[i % cats.length];
    // Cluster by category
    const ci = cats.indexOf(cat);
    const cx = 0.25 + (ci % 2) * 0.5;
    const cy = 0.3 + Math.floor(ci / 2) * 0.45;
    const a = seed(i) * Math.PI * 2;
    const r = 0.06 + seed(i+100) * 0.16;
    arr.push({
      id: i,
      x: cx + Math.cos(a) * r,
      y: cy + Math.sin(a) * r,
      cat, color: colors[cat],
      r: 5 + seed(i+200) * 5,
      important: i < 6,
    });
  }
  return arr;
})();
const GRAPH_EDGES = (() => {
  const e = [];
  // ~62 edges — sparse but connected
  for (let i = 0; i < GRAPH_NODES.length; i++) {
    for (let j = i+1; j < GRAPH_NODES.length; j++) {
      const a = GRAPH_NODES[i], b = GRAPH_NODES[j];
      const d = Math.hypot(a.x - b.x, a.y - b.y);
      if (d < 0.18 && Math.random() > 0.55) e.push([i, j]);
    }
  }
  return e;
})();

function DecisionGraph({ start, focusOnLater }) {
  const time = useTime();
  const W = 1100, H = 560;
  const t = time - start;
  // Edge reveal between 1-6s
  const edgeRev = Math.max(0, Math.min(1, (t - 1.5) / 4.5));
  const visibleEdges = Math.floor(GRAPH_EDGES.length * edgeRev);
  // Nodes pop 0.5-3.5s
  const nodeRev = (i) => fade(time, start + 0.5 + i*0.04, 0.3);
  // Late-stage focus: dim everything except DECISION-019 cluster + neighbors
  const focusActive = focusOnLater && time > focusOnLater;
  const focusO = focusActive ? Math.min(1, (time - focusOnLater) / 0.6) : 0;
  const focusNode = 4; // an "arch" node we'll call DECISION-019
  const neighbors = new Set();
  if (focusActive) {
    GRAPH_EDGES.forEach(([a,b]) => {
      if (a === focusNode) neighbors.add(b);
      if (b === focusNode) neighbors.add(a);
    });
    neighbors.add(focusNode);
  }

  return (
    <svg width="100%" height="100%" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet" style={{ display:'block' }}>
      {/* Edges */}
      {GRAPH_EDGES.slice(0, visibleEdges).map(([i, j], ei) => {
        const a = GRAPH_NODES[i], b = GRAPH_NODES[j];
        const dim = focusActive && !(i === focusNode || j === focusNode);
        return (
          <line key={ei}
            x1={a.x*W} y1={a.y*H} x2={b.x*W} y2={b.y*H}
            stroke={CE.green} strokeWidth={dim ? 0.5 : 1.2}
            strokeOpacity={dim ? 0.08 - focusO*0.05 : 0.3 - focusO*0.05} />
        );
      })}
      {/* Nodes */}
      {GRAPH_NODES.map((n, i) => {
        const op = nodeRev(i);
        const isFocus = focusActive && (i === focusNode);
        const dim = focusActive && !neighbors.has(i);
        return (
          <g key={i} opacity={op * (dim ? 0.18 : 1)}>
            {(n.important || isFocus) && <circle cx={n.x*W} cy={n.y*H} r={n.r*1.9} fill={n.color} opacity={isFocus ? 0.35 : 0.18} />}
            <circle cx={n.x*W} cy={n.y*H} r={isFocus ? n.r*1.4 : n.r} fill={n.color} />
          </g>
        );
      })}
      {/* Focus label */}
      {focusActive && (() => {
        const n = GRAPH_NODES[focusNode];
        return (
          <g opacity={focusO}>
            <line x1={n.x*W + 12} y1={n.y*H} x2={n.x*W + 80} y2={n.y*H - 30} stroke={CE.green} strokeWidth="1" />
            <rect x={n.x*W + 80} y={n.y*H - 60} width="240" height="60" fill={CE.charcoal} stroke={CE.green} strokeWidth="1" rx="4" />
            <text x={n.x*W + 92} y={n.y*H - 42} fill={CE.green} fontSize="11" fontFamily="JetBrains Mono">DECISION-019</text>
            <text x={n.x*W + 92} y={n.y*H - 24} fill="#fff" fontSize="13" fontFamily="Geologica">Shared retry middleware</text>
            <text x={n.x*W + 92} y={n.y*H - 9} fill={CE.amber} fontSize="11" fontFamily="JetBrains Mono">REJECTED · 8 reasons · 5 mo ago</text>
          </g>
        );
      })()}
    </svg>
  );
}

function GraphLegend({ start }) {
  const time = useTime();
  const items = [
    { c: CE.green,  label: 'architecture', n: 14 },
    { c: CE.blue,   label: 'data',         n: 9 },
    { c: CE.amber,  label: 'security',     n: 8 },
    { c: CE.purple, label: 'performance',  n: 7 },
  ];
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10, opacity: fade(time, start, 0.4) }}>
      {items.map((it, i) => (
        <div key={i} style={{ display:'flex', alignItems:'center', gap:10, fontSize:12, color:CE.gray }}>
          <span style={{ width:10, height:10, borderRadius:5, background:it.c, flexShrink:0 }} />
          <span style={{ flex:1 }}>{it.label}</span>
          <span style={{ fontFamily:T.mono, color:CE.dim }}>{it.n}</span>
        </div>
      ))}
    </div>
  );
}

function BeatA({ s }) {
  const time = useTime();
  const t = time - s;

  // Phase A1: 0-18s reveal graph
  // Phase A2: 18-36s 4 cards
  if (t < 18) {
    return (
      <ISChrome section="intelligence / decision-graph" sectionRight="38 decisions · 62 connections">
        <BeatHeader beat="01" title="Connected decisions" start={s} hold={6} />
        <div style={{ position:'absolute', inset:0, padding:'70px 32px 24px', display:'flex' }}>
          <div style={{ flex:1, position:'relative' }}>
            <DecisionGraph start={s} focusOnLater={s + 11} />
          </div>
          <div style={{ width:240, paddingLeft:24, display:'flex', flexDirection:'column', gap:24 }}>
            <div style={{ opacity: fade(time, s + 0.4, 0.4) }}>
              <div style={{ fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', marginBottom:10 }}>SCALE</div>
              <div style={{ fontSize:38, color:'#fff', fontWeight:300, lineHeight:1 }}>38</div>
              <div style={{ fontSize:12, color:CE.gray, marginTop:4 }}>decisions logged</div>
              <div style={{ fontSize:38, color:'#fff', fontWeight:300, lineHeight:1, marginTop:18 }}>62</div>
              <div style={{ fontSize:12, color:CE.gray, marginTop:4 }}>cross-references</div>
            </div>
            <div>
              <div style={{ fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', marginBottom:10 }}>BY CATEGORY</div>
              <GraphLegend start={s + 1.5} />
            </div>
            {time > s + 11.5 && (
              <Card start={s+11.5} accent={CE.green} padding={14}>
                <AFChip skill="decision-graph" start={s+11.6} />
                <div style={{ fontSize:13, color:'#fff', marginTop:10, lineHeight:1.5 }}>
                  Cited 47× this quarter
                </div>
              </Card>
            )}
          </div>
        </div>
      </ISChrome>
    );
  }
  // Phase A2: 4 cards
  return <BeatACards s={s + 18} />;
}

function EnabledCard({ start, badge, badgeColor, title, body, foot, footIcon }) {
  return (
    <Card start={start} style={{ height:'100%' }} padding={20}>
      <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:14 }}>
        <span style={{ fontFamily:T.mono, fontSize:10, color: badgeColor, letterSpacing:'0.08em', fontWeight:600, padding:'3px 8px', border:`1px solid ${badgeColor}55`, borderRadius:3 }}>{badge}</span>
      </div>
      <div style={{ fontSize:15, color:'#fff', fontWeight:500, marginBottom:10, lineHeight:1.35 }}>{title}</div>
      <div style={{ fontSize:12.5, color:CE.gray, lineHeight:1.6, marginBottom:14 }}>{body}</div>
      <div style={{ borderTop:`1px solid ${CE.line}`, paddingTop:12, fontSize:11, color:CE.dim, fontFamily:T.mono, display:'flex', alignItems:'center', gap:6 }}>
        {footIcon && <span style={{ color:CE.green }}>{footIcon}</span>}
        <span>{foot}</span>
      </div>
    </Card>
  );
}

function BeatACards({ s }) {
  const time = useTime();
  return (
    <ISChrome section="intelligence / decision-graph · enabled" sectionRight="4 of 12 capabilities">
      <BeatHeader beat="01" title="What this enables" start={s} hold={4} />
      <div style={{ position:'absolute', inset:0, padding:'70px 32px 24px', display:'flex', flexDirection:'column', gap:18 }}>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:18, flex:1 }}>
          <EnabledCard
            start={s + 0.4}
            badge="RE-LITIGATION GUARD"
            badgeColor={CE.green}
            title="Same proposal, surfaced with eight reasons it was rejected."
            body="When someone re-proposes shared retry middleware, the framework cites DECISION-019 with the original reasons. No re-debate."
            foot="DECISION-019 · 8 reasons · 5 mo ago"
            footIcon="✓"
          />
          <EnabledCard
            start={s + 0.7}
            badge="CONTEXT IN PR"
            badgeColor={CE.green}
            title="Reviewers see the decision lineage of every change."
            body="Each PR auto-links the decisions a change touches. Reviewers see what was decided, when, and why — without asking."
            foot="auto-linked · 47 PRs this quarter"
            footIcon="◉"
          />
          <EnabledCard
            start={s + 1.0}
            badge="ARCHITECTURE COHERENCE"
            badgeColor={CE.green}
            title="Cross-service patterns checked against accepted decisions."
            body="When a new service deviates from a graph-anchored pattern, the framework flags the gap before code review."
            foot="14 architecture decisions · 0 unflagged drifts"
            footIcon="◉"
          />
          <EnabledCard
            start={s + 1.3}
            badge="ONBOARDING"
            badgeColor={CE.green}
            title="New engineers read the top six decisions on day one."
            body="Personalized starter brief: codebase map, top decisions for their service, recent context. First PR in one day."
            foot="day 1 · 6 decisions · 0 ramp questions"
            footIcon="◉"
          />
        </div>
      </div>
    </ISChrome>
  );
}

// ════════════════════════════════════════════════════════════════
// BEAT B — CALIBRATION INTELLIGENCE (48-84s)
// ════════════════════════════════════════════════════════════════

function CalibBars({ start, segments }) {
  // segments: [{label, skew, color, width%}]
  const time = useTime();
  return (
    <div>
      {segments.map((seg, i) => {
        const t = start + i * 0.18;
        const w = fade(time, t, 0.4) * seg.width;
        return (
          <div key={i} style={{ marginBottom:18, opacity: fade(time, t, 0.4) }}>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:6 }}>
              <span style={{ fontSize:13, color:CE.white, fontFamily:T.mono }}>{seg.label}</span>
              <span style={{ fontSize:14, color: seg.color, fontFamily:T.mono, fontWeight:500 }}>×{seg.skew.toFixed(2)}</span>
            </div>
            <div style={{ height:8, background:'rgba(255,255,255,0.04)', borderRadius:4, overflow:'hidden', position:'relative' }}>
              <div style={{ position:'absolute', left:'50%', top:0, bottom:0, width:1, background:CE.dim, opacity:0.4 }} />
              <div style={{ width: w + '%', height:'100%', background: seg.color, marginLeft: seg.skew >= 1 ? '50%' : (50 - w) + '%' }} />
            </div>
            <div style={{ fontSize:11, color:CE.dim, marginTop:4 }}>{seg.note}</div>
          </div>
        );
      })}
    </div>
  );
}

function BeatB({ s }) {
  const time = useTime();
  const t = time - s;

  // Phase B1: 0-18s reveal calibration story
  if (t < 18) {
    const histStart = s + 0.4;
    const skewStart = s + 4.5;
    const explainStart = s + 12;
    return (
      <ISChrome section="intelligence / calibration" sectionRight="142 stories · last 12 weeks">
        <BeatHeader beat="02" title="How this team estimates" start={s} hold={6} />
        <div style={{ position:'absolute', inset:0, padding:'70px 40px 24px', display:'flex', gap:36 }}>
          {/* Left: aggregate accuracy */}
          <div style={{ flex:'0 0 380px' }}>
            <div style={{ fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', marginBottom:14, opacity: fade(time, histStart, 0.4) }}>
              ACCURACY · 142 STORIES
            </div>
            <Card start={histStart} accent={CE.green} padding={20}>
              <div style={{ display:'flex', alignItems:'baseline', gap:14, marginBottom:18 }}>
                <div style={{ fontSize:54, color:CE.white, fontWeight:300, lineHeight:1 }}>±18%</div>
                <div style={{ fontSize:13, color:CE.green }}>median p50→p90 spread</div>
              </div>
              <div style={{ height:1, background:CE.line, margin:'14px 0' }} />
              <div style={{ display:'flex', justifyContent:'space-between', fontSize:12 }}>
                <div><span style={{ color:CE.gray }}>self-report</span><span style={{ color:CE.dim, marginLeft:8 }}>±62%</span></div>
                <div><span style={{ color:CE.green }}>→</span></div>
                <div><span style={{ color:CE.gray }}>calibrated</span><span style={{ color:CE.white, marginLeft:8, fontWeight:500 }}>±18%</span></div>
              </div>
            </Card>
            {time > explainStart - 0.1 && (
              <div style={{ marginTop:18, opacity: fade(time, explainStart, 0.4) }}>
                <AFChip skill="estimation-calibration" start={explainStart} />
                <div style={{ marginTop:12, fontSize:13, color:CE.gray, lineHeight:1.6 }}>
                  Re-trained continuously against shipped stories. Skew tracked per service, per risk class, per engineer.
                </div>
              </div>
            )}
          </div>
          {/* Right: skew-by-segment */}
          <div style={{ flex:1 }}>
            <div style={{ fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', marginBottom:14, opacity: fade(time, skewStart, 0.4) }}>
              CORRECTION FACTOR BY SEGMENT
            </div>
            <CalibBars start={skewStart} segments={[
              { label:'payment-service',     skew:1.36, color:CE.green, width:36, note:'p50: 3.4h · n=42 · stable 6w' },
              { label:'notifications',       skew:1.18, color:CE.green, width:18, note:'p50: 2.1h · n=31 · stable 8w' },
              { label:'billing (new)',       skew:1.62, color:CE.amber, width:62, note:'p50: 5.8h · n=14 · still drifting' },
              { label:'risk class: external',skew:1.45, color:CE.amber, width:45, note:'webhook + SDK + auth · n=22' },
              { label:'risk class: internal',skew:0.92, color:CE.green, width:8,  note:'pure refactor · n=33' },
            ]} />
          </div>
        </div>
      </ISChrome>
    );
  }
  return <BeatBCards s={s + 18} />;
}

function BeatBCards({ s }) {
  return (
    <ISChrome section="intelligence / calibration · enabled" sectionRight="4 of 12 capabilities">
      <BeatHeader beat="02" title="What this enables" start={s} hold={4} />
      <div style={{ position:'absolute', inset:0, padding:'70px 32px 24px' }}>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:18, height:'100%' }}>
          <EnabledCard start={s + 0.4} badge="QUARTERLY PLANNING" badgeColor={CE.green}
            title="Plans use this team's actual rate, not optimistic guesses."
            body="Roadmap dates are computed from the team's calibrated velocity per segment. No more re-baselining mid-quarter."
            foot="±18% confidence · 12-week horizon" footIcon="◉" />
          <EnabledCard start={s + 0.7} badge="DRIFT ALERTS" badgeColor={CE.green}
            title="When a service's skew shifts, the framework flags it."
            body="auth-flow trended 1.0× → 1.45× over 8 weeks. Probable cause: new engineers under 90d exposure. Auto-routed to manager."
            foot="3 drift alerts this quarter" footIcon="!" />
          <EnabledCard start={s + 1.0} badge="STORY-LEVEL ESTIMATE" badgeColor={CE.green}
            title="Every new story gets a calibrated estimate at intake."
            body="2.5h self-report → 3.4h calibrated based on 6 similar prior stories. p50 and p90 returned with the ticket."
            foot="auto-applied · 100% of stories" footIcon="◉" />
          <EnabledCard start={s + 1.3} badge="HIRING TARGETS" badgeColor={CE.green}
            title="Engineering capacity translates directly to roadmap commits."
            body="Calibration data tells the leadership team what one new engineer adds in shippable scope, by segment."
            foot="evidence-backed · 4 hiring decisions" footIcon="◉" />
        </div>
      </div>
    </ISChrome>
  );
}

// ════════════════════════════════════════════════════════════════
// BEAT C — SKILL / PATTERN CATALOG (84-120s)
// ════════════════════════════════════════════════════════════════

const PATTERNS = [
  { name:'idempotency keys',        usage:24, override:'2%',  status:'mature',  color:CE.green },
  { name:'webhook signing (HMAC)',  usage:18, override:'3%',  status:'mature',  color:CE.green },
  { name:'service-layer validation',usage:32, override:'4%',  status:'mature',  color:CE.green },
  { name:'retry · per-service',     usage:14, override:'6%',  status:'mature',  color:CE.green },
  { name:'event-sourced audit',     usage:9,  override:'9%',  status:'maturing',color:CE.green },
  { name:'feature-flag rollout',    usage:21, override:'7%',  status:'mature',  color:CE.green },
  { name:'OpenAPI-first contracts', usage:8,  override:'12%', status:'maturing',color:CE.amber },
  { name:'shared retry middleware', usage:0,  override:'rejected', status:'rejected',color:CE.red },
];

function BeatC({ s }) {
  const time = useTime();
  const t = time - s;
  if (t < 18) {
    const headerT = s + 0.3;
    const tableT = s + 1.0;
    const calloutT = s + 11;
    return (
      <ISChrome section="intelligence / skills · pattern-catalog" sectionRight="54 named skills · 47 patterns">
        <BeatHeader beat="03" title="Patterns the team chose" start={s} hold={6} />
        <div style={{ position:'absolute', inset:0, padding:'70px 40px 24px', display:'flex', gap:32 }}>
          <div style={{ flex:1 }}>
            <div style={{ display:'grid', gridTemplateColumns:'2fr 80px 90px 110px', gap:12, padding:'10px 16px', fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', borderBottom:`1px solid ${CE.line}`, opacity: fade(time, headerT, 0.4) }}>
              <div>PATTERN</div>
              <div style={{ textAlign:'right' }}>USES</div>
              <div style={{ textAlign:'right' }}>OVERRIDE</div>
              <div>STATUS</div>
            </div>
            {PATTERNS.map((p, i) => (
              <div key={i} style={{
                display:'grid', gridTemplateColumns:'2fr 80px 90px 110px', gap:12,
                padding:'12px 16px', fontSize:13, color:CE.white,
                borderBottom:`1px solid ${CE.line}`,
                opacity: fade(time, tableT + i*0.13, 0.3),
                transform:`translateY(${slideUp(time, tableT + i*0.13, 0.3, 6)}px)`,
                background: p.status === 'rejected' ? 'rgba(255,107,107,0.04)' : 'transparent',
              }}>
                <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                  <span style={{ width:6, height:6, borderRadius:3, background:p.color, flexShrink:0 }} />
                  <span style={{ color: p.status === 'rejected' ? CE.gray : '#fff' }}>{p.name}</span>
                </div>
                <div style={{ textAlign:'right', fontFamily:T.mono, color: p.usage === 0 ? CE.dim : CE.gray }}>{p.usage}</div>
                <div style={{ textAlign:'right', fontFamily:T.mono, color: p.color === CE.amber ? CE.amber : (p.color === CE.red ? CE.red : CE.gray) }}>{p.override}</div>
                <div style={{ fontFamily:T.mono, fontSize:11, color: p.color }}>{p.status}</div>
              </div>
            ))}
          </div>
          <div style={{ flex:'0 0 320px', display:'flex', flexDirection:'column', gap:18 }}>
            <Card start={headerT} padding={16}>
              <div style={{ fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', marginBottom:8 }}>SKILL VERSIONS</div>
              <div style={{ fontSize:34, color:CE.white, fontWeight:300, lineHeight:1 }}>54</div>
              <div style={{ fontSize:12, color:CE.gray, marginTop:4 }}>named skills · 12 agents</div>
            </Card>
            {time > calloutT - 0.1 && (
              <Card start={calloutT} accent={CE.amber} padding={16}>
                <AFChip skill="usage-pattern-analysis" start={calloutT + 0.1} />
                <div style={{ fontSize:13, color:'#fff', marginTop:10, fontWeight:500, lineHeight:1.4 }}>
                  OpenAPI-first override 12% &gt; threshold
                </div>
                <div style={{ fontSize:12, color:CE.gray, marginTop:8, lineHeight:1.5 }}>
                  Re-tuning rule weights from last 18 overrides
                </div>
              </Card>
            )}
          </div>
        </div>
      </ISChrome>
    );
  }
  return <BeatCCards s={s + 18} />;
}

function BeatCCards({ s }) {
  return (
    <ISChrome section="intelligence / skills · enabled" sectionRight="4 of 12 capabilities">
      <BeatHeader beat="03" title="What this enables" start={s} hold={4} />
      <div style={{ position:'absolute', inset:0, padding:'70px 32px 24px' }}>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:18, height:'100%' }}>
          <EnabledCard start={s + 0.4} badge="PATTERN RECOMMENDATION" badgeColor={CE.green}
            title="In a new service, the framework proposes the pattern this team chose."
            body="32/35 modules use service-layer validation. New module gets the same. No second-guessing the convention."
            foot="91% adherence · auto-cited" footIcon="◉" />
          <EnabledCard start={s + 0.7} badge="LIVING SKILLS" badgeColor={CE.green}
            title="When recommendations get overridden, the framework re-tunes."
            body="OpenAPI-first override at 12% triggered re-evaluation. Rule weights updated from 18 override events. Override rate dropped to 5%."
            foot="3 skill re-tunes this quarter" footIcon="◉" />
          <EnabledCard start={s + 1.0} badge="ANTI-PATTERN GUARD" badgeColor={CE.green}
            title="Rejected patterns can't quietly come back."
            body="Shared retry middleware was rejected with 8 reasons. Any PR or proposal touching it is automatically annotated with the original rejection."
            foot="0 re-introductions · 5 mo" footIcon="◉" />
          <EnabledCard start={s + 1.3} badge="REVIEW AUTOMATION" badgeColor={CE.green}
            title="Code review runs the same checks the team would manually."
            body="Each PR is auto-checked against acceptance criteria, governance rules, complexity, coverage, pattern conformance — five skills, milliseconds."
            foot="5/5 checks · 47 PRs · q2" footIcon="◉" />
        </div>
      </div>
    </ISChrome>
  );
}

// ════════════════════════════════════════════════════════════════
// BEAT D — OPPORTUNITY INTELLIGENCE (120-156s)
// ════════════════════════════════════════════════════════════════

const OPPS = [
  { id:'OPP-031', title:'Bundle 4 stories: notification preferences', kind:'pattern', impact:'$18K saved · 14h', evidence:'4 PRs touch same module · feature-flag rollout', color:CE.green, time:'2d ago' },
  { id:'OPP-029', title:'Promote payment retry to platform module',   kind:'pattern', impact:'reuse 3 services',   evidence:'24 uses across services · stable',          color:CE.green, time:'3d ago' },
  { id:'OPP-027', title:'Re-litigation watch: BullMQ → SQS',          kind:'guard',   impact:'avoid 80h migration', evidence:'DECISION-015 · 3 mentions in last 7d',     color:CE.amber,time:'4d ago' },
  { id:'OPP-024', title:'Debt cluster: payment-service auth (5 files)',kind:'debt',    impact:'+1.36× → +1.18×',     evidence:'cyclomatic 14 · grew 3w',                  color:CE.amber,time:'5d ago' },
  { id:'OPP-020', title:'Spec drift: STORY-038 acceptance widened',   kind:'guard',   impact:'scope +27%',           evidence:'criteria diff · 2 added',                  color:CE.red,  time:'1w ago' },
  { id:'OPP-018', title:'Calibration drift: auth-flow segment',       kind:'cal',     impact:'1.0×→1.45× / 8w',      evidence:'engineers <90d exposure',                  color:CE.amber,time:'1w ago' },
];

function BeatD({ s }) {
  const time = useTime();
  const t = time - s;
  if (t < 18) {
    const headerT = s + 0.3;
    const listT = s + 1.0;
    const sourceT = s + 11;
    return (
      <ISChrome section="intelligence / opportunities" sectionRight="6 active · 38 actioned this quarter">
        <BeatHeader beat="04" title="Opportunities surface themselves" start={s} hold={6} />
        <div style={{ position:'absolute', inset:0, padding:'70px 40px 24px', display:'flex', gap:32 }}>
          <div style={{ flex:1, display:'flex', flexDirection:'column', gap:10 }}>
            {OPPS.map((o, i) => (
              <div key={i} style={{ display:'flex', gap:14, padding:'14px 18px', background:CE.charcoal, border:`1px solid ${CE.line}`, borderLeft:`3px solid ${o.color}`, borderRadius:6, opacity: fade(time, listT + i*0.18, 0.3), transform:`translateY(${slideUp(time, listT + i*0.18, 0.3, 6)}px)` }}>
                <div style={{ flex:'0 0 90px', fontFamily:T.mono, fontSize:11, color:CE.gray, paddingTop:2 }}>{o.id}</div>
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:14, color:'#fff', fontWeight:500, marginBottom:4 }}>{o.title}</div>
                  <div style={{ fontSize:11, color:CE.dim, fontFamily:T.mono }}>{o.evidence}</div>
                </div>
                <div style={{ flex:'0 0 200px', textAlign:'right' }}>
                  <div style={{ fontSize:13, color:o.color, fontWeight:500 }}>{o.impact}</div>
                  <div style={{ fontSize:11, color:CE.dim, fontFamily:T.mono, marginTop:3 }}>{o.time}</div>
                </div>
              </div>
            ))}
          </div>
          <div style={{ flex:'0 0 290px', display:'flex', flexDirection:'column', gap:18 }}>
            <Card start={headerT} padding={16}>
              <div style={{ fontSize:11, color:CE.gray, fontFamily:T.mono, letterSpacing:'0.06em', marginBottom:8 }}>THIS QUARTER</div>
              <div style={{ fontSize:34, color:CE.white, fontWeight:300, lineHeight:1 }}>38</div>
              <div style={{ fontSize:12, color:CE.gray, marginTop:4 }}>opportunities actioned</div>
              <div style={{ height:1, background:CE.line, margin:'14px 0' }} />
              <div style={{ fontSize:24, color:CE.green, fontWeight:400 }}>$340K</div>
              <div style={{ fontSize:11, color:CE.gray, marginTop:2 }}>est. value preserved or saved</div>
            </Card>
            {time > sourceT - 0.1 && (
              <Card start={sourceT} accent={CE.green} padding={16}>
                <AFChip skill="opportunity-synthesis" start={sourceT + 0.1} />
                <div style={{ fontSize:12, color:CE.gray, marginTop:10, lineHeight:1.6 }}>
                  Cross-checks decision graph, calibration, pattern catalog, debt index, governance, demand intake
                </div>
              </Card>
            )}
          </div>
        </div>
      </ISChrome>
    );
  }
  return <BeatDCards s={s + 18} />;
}

function BeatDCards({ s }) {
  return (
    <ISChrome section="intelligence / opportunities · enabled" sectionRight="4 of 12 capabilities">
      <BeatHeader beat="04" title="What this enables" start={s} hold={4} />
      <div style={{ position:'absolute', inset:0, padding:'70px 32px 24px' }}>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:18, height:'100%' }}>
          <EnabledCard start={s + 0.4} badge="STORY BUNDLING" badgeColor={CE.green}
            title="Related work surfaces as one bundle, not four tickets."
            body="Four stories touching the same module merged into one effort: 14h instead of 22h. The framework spotted the overlap before sprint planning."
            foot="OPP-031 · $18K saved · q2" footIcon="◉" />
          <EnabledCard start={s + 0.7} badge="PROMOTION DETECTION" badgeColor={CE.green}
            title="When a pattern matures across services, it's promoted to platform."
            body="Payment retry stable across 24 uses, 3 services. Promoted to platform module — eliminates 3 future re-implementations."
            foot="OPP-029 · 3 services" footIcon="◉" />
          <EnabledCard start={s + 1.0} badge="DEBT INTELLIGENCE" badgeColor={CE.amber}
            title="Debt clusters surface with the calibration evidence."
            body="payment-service auth: 5 files, cyclomatic 14, growing 3 weeks. Skew rising 1.18× → 1.36×. The framework knows where remediation pays off."
            foot="OPP-024 · est. recovery 14h" footIcon="◉" />
          <EnabledCard start={s + 1.3} badge="EARLY WARNING" badgeColor={CE.red}
            title="Spec drift, scope creep, calibration drift — caught at the edge."
            body="STORY-038 acceptance criteria widened 27%. Surfaced to PM before sprint started. No mid-sprint surprise. No blame."
            foot="OPP-020 · pre-sprint catch" footIcon="!" />
        </div>
      </div>
    </ISChrome>
  );
}

// ════════════════════════════════════════════════════════════════
// SYNTHESIS + CLOSE (156-180s)
// ════════════════════════════════════════════════════════════════

function Synthesis({ s }) {
  const time = useTime();
  const t = time - s;
  // 156-170s: 4 columns synthesis · 170-180s: closing card
  if (t < 14) {
    const headerT = s + 0.3;
    const colT = s + 1.0;
    const bgO = fade(time, s, 0.6);
    const cols = [
      { kind:'01', title:'Decision graph',          metric:'38',    unit:'decisions',    sub:'62 connections · cited 47×',     color:'#00E87B' },
      { kind:'02', title:'Calibration intelligence',metric:'±18%',  unit:'accuracy',     sub:'down from ±62% · 142 stories',   color:'#C59DF8' },
      { kind:'03', title:'Skill / pattern catalog', metric:'54',    unit:'named skills', sub:'47 patterns · 3 retunes/q',      color:'#63EAFF' },
      { kind:'04', title:'Opportunity intelligence',metric:'38',    unit:'actioned',     sub:'$340K preserved · q2',           color:'#EAB4B4' },
    ];
    return (
      <div style={{ position:'absolute', inset:0, background:CE.carbon, color:'#fff', fontFamily:T.sans }}>
        <div style={{ position:'absolute', inset:0, background:'url(/assets/images/bg_arcs.jpg) center/cover no-repeat', opacity:bgO }} />
        <div style={{ position:'relative', padding:'80px 60px 40px', textShadow:'0 2px 12px rgba(0,0,0,0.7)' }}>
          <div style={{ opacity: fade(time, headerT, 0.5) }}>
            <div style={{ ...eyebrowStyle, justifyContent:'flex-start', marginBottom:14 }}>
              The compounding effect
            </div>
            <div style={{ fontSize:50, fontWeight:400, color:CE.white, lineHeight:1.2, maxWidth:1400, letterSpacing:'-0.005em' }}>
              Every decision, every estimate, every pattern, every opportunity —
              <span style={gradientStyle}> connected and re-tuned.</span>
            </div>
          </div>
          <div style={{ marginTop:60, display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:24 }}>
            {cols.map((c, i) => (
              <div key={i} style={{
                opacity: fade(time, colT + i*0.25, 0.4),
                transform:`translateY(${slideUp(time, colT + i*0.25, 0.4, 8)}px)`,
                background:'#0D1321',
                border:'1px solid rgba(250, 250, 250, 0.1)',
                borderRadius:6,
                padding:'56px 40px 64px',
                overflow:'hidden',
                boxShadow:'0 8px 32px rgba(0,0,0,0.3)',
                textShadow:'none',
              }}>
                <div style={{ fontSize:18, color:c.color, letterSpacing:'0.16em', fontWeight:600, marginBottom:10 }}>BEAT {c.kind}</div>
                <div style={{ fontSize:25, color:CE.white, fontWeight:500, marginBottom:18 }}>{c.title}</div>
                <div style={{ display:'flex', alignItems:'baseline', gap:10 }}>
                  <div style={{ fontSize:44, color:c.color, fontWeight:300, lineHeight:1 }}>{c.metric}</div>
                  <div style={{ fontSize:15, color:CE.gray }}>{c.unit}</div>
                </div>
                <div style={{ fontSize:14, color:CE.dim, marginTop:10 }}>{c.sub}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    );
  }
  // Close card 170-180
  const closeT = s + 14;
  const wmT = s + 18.5;
  const bgO = fade(time, s + 14, 0.6);
  return (
    <div style={{ position:'absolute', inset:0, background:CE.carbon, color:'#fff', fontFamily:T.sans, display:'flex', alignItems:'center', justifyContent:'center' }}>
      <div style={{ position:'absolute', inset:0, background:'url(/assets/images/bg_hero.jpg) center/cover no-repeat', opacity:bgO }} />
      <div style={{ position:'relative', textAlign:'center', maxWidth:1200, opacity: fade(time, closeT, 0.7), transform:`translateY(${(1-fade(time,closeT,0.7))*8}px)`, textShadow:'0 2px 12px rgba(0,0,0,0.7)' }}>
        <div style={{ fontSize:50, color:CE.white, fontWeight:300, lineHeight:1.3 }}>
          Every new question gets cheaper to answer.
        </div>
        <div style={{ fontSize:50, fontWeight:500, lineHeight:1.3, marginTop:18, ...gradientStyle }}>
          That's the compounding effect.
        </div>
      </div>
      <div style={{ position:'absolute', bottom:80, left:0, right:0, display:'flex', flexDirection:'column', alignItems:'center', gap:24, opacity: fade(time, wmT, 0.5) }}>
        <span style={{ fontSize:19, fontWeight:500, ...gradientStyle }}>Agentic Forge</span>
        <img src="/assets/logo.svg" alt="Quantivex" style={{ height:28, display:'block' }} />
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════
// APP — 180s
// ════════════════════════════════════════════════════════════════
function App() {
  return (
    <DemoStage duration={180} captions={[]}>
      <Sprite start={0}    end={12}  ><ColdOpen /></Sprite>
      {/* Beat A · 12-48s */}
      <Sprite start={12}   end={48}  ><BeatA s={12} /></Sprite>
      {/* Beat B · 48-84s */}
      <Sprite start={48}   end={84}  ><BeatB s={48} /></Sprite>
      {/* Beat C · 84-120s */}
      <Sprite start={84}   end={120} ><BeatC s={84} /></Sprite>
      {/* Beat D · 120-156s */}
      <Sprite start={120}  end={156} ><BeatD s={120} /></Sprite>
      {/* Synthesis · 156-180s */}
      <Sprite start={156}  end={180} ><Synthesis s={156} /></Sprite>
      {/* <Subtitles /> — disabled: no voiceover. Re-enable when audio lands. */}
    </DemoStage>
  );
}

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