// scenes.jsx — all five beats for the LeaderCoreAI hero video.
// Each scene is a self-contained Sprite window, positioned within a 1920x1080 canvas.

const PINK = '#AF6092';
const PINK_SOFT = 'oklch(62% 0.08 340)';
const BG = '#2E292B';
const CARD = '#363032';
const CARD_2 = '#3d3638';
const BORDER = '#443C3F';
const BORDER_SOFT = 'rgba(255,255,255,0.06)';
const FG = '#F2F2F2';
const MUTED = '#BCBCBC';
const DIM = '#8A8287';
const GREEN = 'oklch(72% 0.14 155)';
const AMBER = 'oklch(78% 0.13 75)';
const RED_SOFT = 'oklch(65% 0.14 25)';

const FONT = "Inter, 'Helvetica Neue', system-ui, sans-serif";
const MONO = "'JetBrains Mono', ui-monospace, SFMono-Regular, monospace";

// ────────────────────────────────────────────────────────────────────────────
// BEAT 1 — The Scenario Card (0:00 – 0:03)
// ────────────────────────────────────────────────────────────────────────────
function Beat1Scenario() {
  const { localTime, progress } = useSprite();

  // Card slides/fades in from top in first 0.6s; holds; pulses CTA ~2.0s.
  const cardIn = Easing.easeOutCubic(clamp(localTime / 0.6, 0, 1));
  const cardOut = localTime > 2.7 ? Easing.easeInCubic(clamp((localTime - 2.7) / 0.3, 0, 1)) : 0;
  const cardOpacity = cardIn * (1 - cardOut);
  const cardY = (1 - cardIn) * -30 + cardOut * -8;

  // CTA pulse at ~2.0s: scale 1 -> 1.05 -> 1 over 0.6s
  const pulseT = clamp((localTime - 2.0) / 0.6, 0, 1);
  const pulse = pulseT > 0 && pulseT < 1 ? Math.sin(pulseT * Math.PI) : 0;
  const ctaScale = 1 + pulse * 0.04;
  const ctaGlow = pulse;

  // Meta rows stagger in after card
  const metaIn = (i) => Easing.easeOutCubic(clamp((localTime - 0.4 - i * 0.1) / 0.4, 0, 1));

  // Subtle breathing background scale for the whole composition
  const bg = 1 + Math.sin(localTime * 0.6) * 0.004;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: BG,
    }}>
      {/* Ambient bg grid */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(1100px 700px at 50% 50%, ${CARD_2} 0%, ${BG} 70%)`,
        opacity: 0.9,
        transform: `scale(${bg})`,
      }}/>

      {/* Top chrome: breadcrumb/app header */}
      <div style={{
        position: 'absolute', top: 48, left: 96, right: 96,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        opacity: cardIn * 0.9,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, color: MUTED, fontFamily: MONO, fontSize: 15, letterSpacing: '0.04em' }}>
          <span style={{ width: 8, height: 8, borderRadius: 4, background: PINK }}/>
          SCENARIO LIBRARY
          <span style={{ color: DIM }}>/</span>
          <span style={{ color: FG }}>DELEGATION</span>
        </div>
        <div style={{ color: DIM, fontFamily: MONO, fontSize: 13, letterSpacing: '0.06em' }}>
          SESSION 01 · READY
        </div>
      </div>

      {/* Scenario card */}
      <div style={{
        position: 'relative',
        width: 1120,
        padding: '56px 64px 60px',
        background: CARD,
        border: `1px solid ${BORDER}`,
        borderRadius: 20,
        opacity: cardOpacity,
        transform: `translateY(${cardY}px)`,
        boxShadow: '0 30px 80px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.03)',
        fontFamily: FONT,
      }}>
        {/* Corner accent */}
        <div style={{
          position: 'absolute', top: 0, left: 0, width: 120, height: 4,
          background: PINK, borderTopLeftRadius: 20,
        }}/>

        {/* Eyebrow */}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 14,
          opacity: metaIn(0),
        }}>
          <div style={{
            padding: '6px 14px',
            background: PINK, color: '#fff',
            borderRadius: 999,
            fontSize: 14, fontWeight: 600, letterSpacing: '0.02em',
            fontFamily: FONT,
          }}>
            Scenario 02
          </div>
          <div style={{ color: MUTED, fontSize: 15, fontFamily: MONO, letterSpacing: '0.08em' }}>
            LEADERSHIP · DELEGATION
          </div>
        </div>

        {/* Title */}
        <div style={{
          marginTop: 24,
          fontSize: 72, fontWeight: 600, color: FG,
          letterSpacing: '-0.02em', lineHeight: 1.05,
          opacity: metaIn(1),
          transform: `translateY(${(1 - metaIn(1)) * 10}px)`,
        }}>
          The Delegation Challenge
        </div>

        {/* Body */}
        <div style={{
          marginTop: 28,
          fontSize: 26, color: MUTED,
          lineHeight: 1.45, maxWidth: 900,
          opacity: metaIn(2),
        }}>
          Two weeks before launch, a key team member is out indefinitely. Redistribute the work,
          hold the line, and keep the team together under pressure.
        </div>

        {/* Meta row */}
        <div style={{
          marginTop: 40,
          display: 'flex', alignItems: 'center', gap: 48,
          opacity: metaIn(3),
        }}>
          {/* Difficulty */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <div style={{ color: DIM, fontSize: 14, fontFamily: MONO, letterSpacing: '0.08em' }}>DIFFICULTY</div>
            <div style={{ display: 'flex', gap: 4 }}>
              {[0,1,2,3,4].map(i => (
                <div key={i} style={{
                  width: 10, height: 22,
                  background: i < 4 ? PINK : BORDER,
                  borderRadius: 2,
                }}/>
              ))}
            </div>
            <div style={{ color: FG, fontSize: 16, fontWeight: 600 }}>High</div>
          </div>

          {/* Team size */}
          <MetaItem label="TEAM" value="4 members" />
          {/* Duration */}
          <MetaItem label="EST." value="12 min" />
          {/* Archetype count */}
          <MetaItem label="ARCHETYPES" value="4 distinct" />
        </div>

        {/* CTA */}
        <div style={{
          marginTop: 48,
          display: 'flex', alignItems: 'center', gap: 24,
          opacity: metaIn(4),
        }}>
          <div style={{
            padding: '20px 40px',
            background: PINK,
            borderRadius: 12,
            color: '#fff',
            fontSize: 22, fontWeight: 600,
            fontFamily: FONT,
            transform: `scale(${ctaScale})`,
            transformOrigin: 'left center',
            boxShadow: ctaGlow > 0
              ? `0 0 ${30 * ctaGlow}px ${10 * ctaGlow}px rgba(175, 96, 146, ${0.35 * ctaGlow})`
              : 'none',
            transition: 'box-shadow 120ms',
            display: 'flex', alignItems: 'center', gap: 16,
          }}>
            Begin simulation
            <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
              <path d="M5 11h12M12 5l6 6-6 6" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </div>
          <div style={{ color: DIM, fontSize: 15, fontFamily: MONO, letterSpacing: '0.06em' }}>
            ⏎ ENTER
          </div>
        </div>
      </div>
    </div>
  );
}

function MetaItem({ label, value }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <div style={{ color: DIM, fontSize: 13, fontFamily: MONO, letterSpacing: '0.08em' }}>{label}</div>
      <div style={{ color: FG, fontSize: 16, fontWeight: 600 }}>{value}</div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// BEAT 2 — The Simulation (0:03 – 0:06)
// ────────────────────────────────────────────────────────────────────────────
function Beat2Chat() {
  const { localTime } = useSprite();

  // Sub-beat timings (local seconds within the 3s window):
  //  0.0–0.4  panel in
  //  0.3–0.9  manager bubble types/fades in
  //  1.0–1.4  typing indicator
  //  1.4–2.5  AI response appears (staggered lines)
  //  2.5–3.0  zoom/push toward response, then out
  const panelIn = Easing.easeOutCubic(clamp(localTime / 0.5, 0, 1));
  const managerIn = Easing.easeOutCubic(clamp((localTime - 0.35) / 0.55, 0, 1));

  const typingStart = 1.0, typingEnd = 1.45;
  const typingVisible = localTime >= typingStart && localTime < typingEnd;

  const aiIn = Easing.easeOutCubic(clamp((localTime - 1.45) / 0.45, 0, 1));
  const aiLine2 = Easing.easeOutCubic(clamp((localTime - 1.75) / 0.4, 0, 1));
  const aiLine3 = Easing.easeOutCubic(clamp((localTime - 2.05) / 0.4, 0, 1));

  const outFade = localTime > 2.75 ? Easing.easeInCubic(clamp((localTime - 2.75) / 0.25, 0, 1)) : 0;

  // Ken Burns zoom toward the AI response from ~1.4s onward
  const zoomT = Easing.easeInOutCubic(clamp((localTime - 1.3) / 1.4, 0, 1));
  const zoom = 1 + zoomT * 0.12;
  const panY = zoomT * -40;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: BG,
      opacity: 1 - outFade,
      overflow: 'hidden',
    }}>
      {/* App chrome */}
      <div style={{
        position: 'absolute', top: 48, left: 96, right: 96,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        opacity: panelIn,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 18, color: FG, fontFamily: FONT, fontSize: 20, fontWeight: 500 }}>
          <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
            <path d="M11 4L6 9l5 5" stroke={MUTED} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
          <span>The Delegation Challenge</span>
          <span style={{ color: DIM, fontFamily: MONO, fontSize: 14, letterSpacing: '0.06em' }}>· TURN 03 / 16</span>
        </div>
        <div style={{
          padding: '10px 18px',
          background: 'transparent',
          border: `1px solid ${BORDER}`,
          borderRadius: 10,
          color: MUTED, fontSize: 15, fontFamily: FONT,
          display: 'flex', alignItems: 'center', gap: 10,
        }}>
          <span style={{ width: 8, height: 8, borderRadius: 4, background: PINK }}/>
          Live session
        </div>
      </div>

      {/* Main layout: chat column (left) + cast (right) */}
      <div style={{
        position: 'absolute',
        left: 96, top: 120, right: 96, bottom: 80,
        display: 'grid',
        gridTemplateColumns: '1fr 360px',
        gap: 32,
        transform: `translateY(${panY}px) scale(${zoom})`,
        transformOrigin: '40% 60%',
        opacity: panelIn,
      }}>
        {/* Chat column */}
        <div style={{
          background: CARD,
          border: `1px solid ${BORDER}`,
          borderRadius: 20,
          padding: '40px 48px',
          display: 'flex', flexDirection: 'column', gap: 28,
          overflow: 'hidden',
          position: 'relative',
        }}>
          {/* Prompt line (faded, context) */}
          <div style={{ color: DIM, fontSize: 20, fontFamily: FONT, fontStyle: 'italic', lineHeight: 1.5 }}>
            How do you address the team and begin to tackle this crisis?
          </div>

          {/* Manager bubble (right-aligned) */}
          <div style={{
            alignSelf: 'flex-end',
            maxWidth: '78%',
            opacity: managerIn,
            transform: `translateY(${(1 - managerIn) * 14}px)`,
          }}>
            <div style={{
              padding: '22px 28px',
              background: PINK_SOFT,
              border: `1px solid ${PINK}40`,
              borderRadius: 18,
              color: FG,
              fontSize: 26, lineHeight: 1.4,
              fontFamily: FONT,
            }}>
              Team, I want to talk about how we redistribute Amanda's work.
              I have some thoughts, but I need yours first.
            </div>
            <div style={{
              marginTop: 8, textAlign: 'right',
              color: DIM, fontSize: 13, fontFamily: MONO, letterSpacing: '0.06em',
            }}>
              07:45 PM · YOU
            </div>
          </div>

          {/* Typing indicator */}
          {typingVisible && (
            <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
              <Avatar letter="M" color={GREEN} />
              <div style={{
                padding: '16px 22px',
                background: CARD_2,
                border: `1px solid ${BORDER}`,
                borderRadius: 16,
                display: 'flex', gap: 6, alignItems: 'center',
              }}>
                {[0,1,2].map(i => {
                  const pt = ((localTime * 2.5) + i * 0.18) % 1;
                  const o = 0.35 + 0.55 * Math.abs(Math.sin(pt * Math.PI));
                  return <div key={i} style={{
                    width: 8, height: 8, borderRadius: 4,
                    background: MUTED, opacity: o,
                  }}/>;
                })}
              </div>
            </div>
          )}

          {/* AI response bubble (left-aligned) */}
          {aiIn > 0 && (
            <div style={{
              display: 'flex', gap: 16, alignItems: 'flex-start',
              opacity: aiIn,
              transform: `translateY(${(1 - aiIn) * 14}px)`,
            }}>
              <Avatar letter="M" color={GREEN} />
              <div style={{ maxWidth: '82%' }}>
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10,
                }}>
                  <span style={{ color: FG, fontSize: 18, fontWeight: 600, fontFamily: FONT }}>Marcus</span>
                  <span style={{
                    padding: '3px 10px',
                    background: `${GREEN}1a`,
                    color: GREEN,
                    borderRadius: 999,
                    fontSize: 12, fontWeight: 600,
                    fontFamily: MONO, letterSpacing: '0.06em',
                  }}>
                    SKEPTIC
                  </span>
                  <span style={{ color: DIM, fontSize: 13, fontFamily: FONT }}>Senior Sales Rep</span>
                </div>
                <div style={{
                  padding: '22px 28px',
                  background: CARD_2,
                  border: `1px solid ${BORDER}`,
                  borderRadius: 18,
                  color: FG,
                  fontSize: 24, lineHeight: 1.45,
                  fontFamily: FONT,
                }}>
                  <div>"Redistribute how? My plate is already overflowing.</div>
                  <div style={{ opacity: aiLine2, marginTop: 6 }}>
                    What exactly is being 'redistributed' — because I'm not
                  </div>
                  <div style={{ opacity: aiLine3, marginTop: 6 }}>
                    carrying more for people who won't pull their weight."
                  </div>
                </div>
                <div style={{
                  marginTop: 8,
                  color: DIM, fontSize: 13, fontFamily: MONO, letterSpacing: '0.06em',
                }}>
                  07:46 PM
                </div>
              </div>
            </div>
          )}
        </div>

        {/* Cast column */}
        <div style={{
          background: CARD,
          border: `1px solid ${BORDER}`,
          borderRadius: 20,
          padding: '32px 24px',
          display: 'flex', flexDirection: 'column', gap: 14,
        }}>
          <div style={{ color: DIM, fontSize: 13, fontFamily: MONO, letterSpacing: '0.1em', marginBottom: 6 }}>
            CAST
          </div>
          <CastRow letter="R" name="Riley" role="Junior Rep" tag="Observer" color="oklch(72% 0.1 220)" active={false} />
          <CastRow letter="J" name="Jordan" role="Sales Ops" tag="Risk-Averse" color="oklch(74% 0.1 60)" active={false} />
          <CastRow letter="M" name="Marcus" role="Senior Rep" tag="Skeptic" color={GREEN} active={aiIn > 0.2} />
          <CastRow letter="C" name="Chen" role="Mid-level Rep" tag="Visionary" color="oklch(72% 0.13 330)" active={false} />
        </div>
      </div>
    </div>
  );
}

function Avatar({ letter, color }) {
  return (
    <div style={{
      width: 52, height: 52, borderRadius: 26,
      background: color, color: '#0f0f10',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: 22, fontWeight: 700, fontFamily: FONT,
      flexShrink: 0,
    }}>{letter}</div>
  );
}

function CastRow({ letter, name, role, tag, color, active }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14,
      padding: '14px 16px',
      background: active ? `${color}14` : 'transparent',
      border: active ? `1px solid ${color}55` : `1px solid transparent`,
      borderRadius: 12,
      transition: 'background 180ms, border 180ms',
    }}>
      <Avatar letter={letter} color={color} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 2, flex: 1 }}>
        <div style={{ color: FG, fontSize: 16, fontWeight: 600, fontFamily: FONT }}>{name}</div>
        <div style={{ color: DIM, fontSize: 12, fontFamily: FONT }}>{role}</div>
      </div>
      <div style={{
        padding: '3px 10px',
        background: `${color}1a`,
        color,
        borderRadius: 999,
        fontSize: 11, fontWeight: 600,
        fontFamily: MONO, letterSpacing: '0.06em',
      }}>
        {tag.toUpperCase()}
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// BEAT 3 — Score & Improvement (0:06 – 0:09)
// ────────────────────────────────────────────────────────────────────────────
function Beat3Score() {
  const { localTime } = useSprite();

  // 0.0–0.4  panel in
  // 0.4–1.6  session 1 holds (bars fill partway)
  // 1.6–2.5  morph: score climbs, bars extend, labels swap to green, session -> 4
  // 2.5–2.8  mastery badge pops in
  // 2.8–3.0  hold, subtle exit
  const panelIn = Easing.easeOutCubic(clamp(localTime / 0.45, 0, 1));

  // Bar fill starts at session-1 values, morphs to session-4 values between 1.6 and 2.5
  const morphT = Easing.easeInOutCubic(clamp((localTime - 1.6) / 0.9, 0, 1));

  // Initial fill of session-1 bars in first 0.8s
  const initialFill = Easing.easeOutCubic(clamp((localTime - 0.3) / 0.8, 0, 1));

  const overall = 5.8 + (8.7 - 5.8) * morphT;
  const sessionNum = morphT < 0.5 ? 1 : 4;
  const sessionFade = morphT < 0.5 ? (1 - morphT * 2) : ((morphT - 0.5) * 2);

  const comps = [
    { label: 'Communication',         s1: 0.58, s4: 0.90 },
    { label: 'Decision-Making',       s1: 0.52, s4: 0.87 },
    { label: 'Vision & Alignment',    s1: 0.50, s4: 0.85 },
    { label: 'Emotional Intelligence', s1: 0.62, s4: 0.91 },
    { label: 'Adaptability',          s1: 0.55, s4: 0.88 },
  ];

  const masteryIn = Easing.easeOutCubic(clamp((localTime - 2.45) / 0.35, 0, 1));
  const masteryScale = 0.9 + 0.1 * masteryIn;

  const outFade = localTime > 2.8 ? Easing.easeInCubic(clamp((localTime - 2.8) / 0.2, 0, 1)) : 0;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: BG,
      opacity: 1 - outFade,
      overflow: 'hidden',
    }}>
      {/* Chrome */}
      <div style={{
        position: 'absolute', top: 48, left: 96, right: 96,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        opacity: panelIn,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, color: MUTED, fontFamily: MONO, fontSize: 15, letterSpacing: '0.04em' }}>
          <span style={{ width: 8, height: 8, borderRadius: 4, background: PINK }}/>
          PERFORMANCE REVIEW
        </div>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 10,
          color: DIM, fontFamily: MONO, fontSize: 14, letterSpacing: '0.06em',
        }}>
          <span>SESSION</span>
          <span style={{ position: 'relative', display: 'inline-block', width: 20 }}>
            <span style={{
              color: FG, position: 'absolute', left: 0,
              opacity: morphT < 0.5 ? 1 - morphT * 2 : morphT * 2 - 1,
            }}>
              0{sessionNum}
            </span>
          </span>
        </div>
      </div>

      {/* Main panel */}
      <div style={{
        position: 'absolute',
        left: 96, top: 120, right: 96, bottom: 80,
        display: 'grid',
        gridTemplateColumns: '500px 1fr',
        gap: 32,
        opacity: panelIn,
      }}>
        {/* Score panel */}
        <div style={{
          background: CARD,
          border: `1px solid ${BORDER}`,
          borderRadius: 20,
          padding: '52px 48px',
          display: 'flex', flexDirection: 'column', gap: 22,
          position: 'relative',
        }}>
          <div style={{ color: DIM, fontSize: 16, fontFamily: MONO, letterSpacing: '0.1em' }}>
            OVERALL
          </div>
          <div style={{
            fontSize: 220, fontWeight: 600, lineHeight: 1,
            fontFamily: FONT, letterSpacing: '-0.05em',
            color: morphT > 0.5
              ? `color-mix(in oklch, ${AMBER}, ${GREEN} ${(morphT - 0.5) * 200}%)`
              : `color-mix(in oklch, ${RED_SOFT}, ${AMBER} ${morphT * 200}%)`,
            fontVariantNumeric: 'tabular-nums',
          }}>
            {overall.toFixed(1)}
          </div>
          <div style={{
            color: morphT > 0.5 ? GREEN : MUTED,
            fontSize: 22, fontFamily: FONT, fontWeight: 500,
          }}>
            {morphT > 0.5 ? 'Exceptional performance' : 'Developing'}
          </div>

          {/* Trend sparkline */}
          <div style={{
            marginTop: 16,
            display: 'flex', alignItems: 'flex-end', gap: 10, height: 56,
          }}>
            {[5.8, 6.4, 7.2, 8.7].map((v, i) => {
              const shown = i === 0 || (i === 1 && morphT > 0.2) || (i === 2 && morphT > 0.5) || (i === 3 && morphT > 0.75);
              const h = shown ? (v / 10) * 56 : 0;
              const active = i === (morphT < 0.5 ? 0 : 3);
              return (
                <div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, flex: 1 }}>
                  <div style={{
                    width: '100%', height: h,
                    background: active ? PINK : BORDER,
                    borderRadius: 4,
                    transition: 'height 200ms',
                  }}/>
                  <div style={{ color: DIM, fontSize: 11, fontFamily: MONO, letterSpacing: '0.06em' }}>
                    S{i + 1}
                  </div>
                </div>
              );
            })}
          </div>

          {/* Mastery badge */}
          {masteryIn > 0 && (
            <div style={{
              position: 'absolute',
              top: 32, right: 32,
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '10px 16px',
              background: `${GREEN}14`,
              border: `1px solid ${GREEN}66`,
              borderRadius: 999,
              opacity: masteryIn,
              transform: `scale(${masteryScale})`,
              transformOrigin: 'center',
            }}>
              <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
                <path d="M9 1l2.2 4.8 5.3.6-4 3.6 1.1 5.2L9 12.6 4.4 15.2l1.1-5.2-4-3.6 5.3-.6L9 1z" fill={GREEN}/>
              </svg>
              <span style={{ color: GREEN, fontSize: 14, fontWeight: 700, fontFamily: MONO, letterSpacing: '0.08em' }}>
                MASTERY
              </span>
            </div>
          )}
        </div>

        {/* Competencies */}
        <div style={{
          background: CARD,
          border: `1px solid ${BORDER}`,
          borderRadius: 20,
          padding: '40px 48px',
          display: 'flex', flexDirection: 'column', gap: 22,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <div style={{ color: FG, fontSize: 34, fontWeight: 600, fontFamily: FONT, letterSpacing: '-0.01em' }}>
              Performance by competency
            </div>
            <div style={{ color: DIM, fontSize: 15, fontFamily: MONO, letterSpacing: '0.08em' }}>
              SCORED ACROSS 23 TURNS
            </div>
          </div>

          {comps.map((c, i) => {
            const target = c.s1 + (c.s4 - c.s1) * morphT;
            const shown = target * initialFill;
            const score = (shown * 10).toFixed(1);
            const barColor = morphT > 0.6 ? GREEN : morphT > 0.2 ? AMBER : RED_SOFT;
            return (
              <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                  <div style={{ color: FG, fontSize: 28, fontFamily: FONT, fontWeight: 500, letterSpacing: '-0.01em' }}>{c.label}</div>
                  <div style={{
                    color: barColor,
                    fontSize: 30, fontWeight: 600, fontFamily: FONT,
                    fontVariantNumeric: 'tabular-nums',
                  }}>
                    {score}<span style={{ color: DIM, fontSize: 20, fontWeight: 400 }}> / 10</span>
                  </div>
                </div>
                <div style={{
                  width: '100%', height: 14, background: BORDER,
                  borderRadius: 7, overflow: 'hidden',
                }}>
                  <div style={{
                    width: `${shown * 100}%`, height: '100%',
                    background: barColor,
                    borderRadius: 7,
                    transition: 'background 400ms',
                  }}/>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// BEAT 4 — Capabilities (0:09 – 0:12)
// ────────────────────────────────────────────────────────────────────────────
function Beat4Capabilities() {
  const { localTime, duration } = useSprite();

  const lines = [
    'Practice with a team, not just one person.',
    'Scale difficulty from simple to extreme.',
    'Behavioral scoring.',
    'Earn certificates verified at mastery.',
    'Available in 42 languages.',
    'Cohort dashboard for L&D.',
    'Fail privately. Improve quickly.',
    'Compete with your cohort, anonymously.',
    'Practice your own scenarios.',
  ];

  // Each bullet enters at a uniform tick. We reserve a little lead-in and tail.
  const lead = 0.25;
  const tail = 0.5;
  const usable = Math.max(0.1, duration - lead - tail);
  const perTick = usable / lines.length; // time between each bullet's entry

  // Row geometry
  const ROW_H = 110;          // vertical spacing per row
  const VISIBLE = 3;          // always show up to 3 rows
  const BASE_TOP = 380;       // y of the top-most visible row

  // Eyebrow
  const eyebrowIn = Easing.easeOutCubic(clamp(localTime / 0.3, 0, 1));
  const eyebrowOut = localTime > (duration - 0.2) ? Easing.easeInCubic(clamp((localTime - (duration - 0.2)) / 0.2, 0, 1)) : 0;

  // Progress through the sequence (0..lines.length-1 plus fractional)
  // At p = 0 -> bullet 0 entering; at p = 2 -> bullets 0,1,2 fully visible;
  // at p = 3 -> bullet 3 fully in, bullet 0 fully out; etc.
  const pRaw = (localTime - lead) / perTick;
  const p = clamp(pRaw, -0.2, lines.length + 0.2);

  // For each bullet, compute:
  //   slot = p - i  (position within the window; 0 = just arrived at bottom, 2 = at top, >2 = off top)
  // We render bullets with slot in [-1, 3] window to handle entry (−1..0) and exit (2..3).
  const items = [];
  for (let i = 0; i < lines.length; i++) {
    const slot = p - i; // fractional "slots-from-bottom"
    if (slot < -0.4 || slot > 3.2) continue;

    // Eased slot transition for smooth scroll
    const easedSlot = slot; // already continuous
    // Base y = top + (VISIBLE - 1 - slot) * ROW_H  (slot 0 -> bottom row, slot 2 -> top row)
    const y = BASE_TOP + (VISIBLE - 1 - easedSlot) * ROW_H;

    // Opacity:
    //  slot < 0   -> fading in (entering from below)
    //  0..2       -> visible
    //  slot > 2   -> fading out (leaving the top)
    let opacity;
    if (slot < 0) {
      opacity = Easing.easeOutCubic(clamp(1 + slot / 0.4, 0, 1)); // slot in [-0.4,0]
    } else if (slot > 2) {
      opacity = Easing.easeInCubic(clamp(1 - (slot - 2) / 0.4, 0, 1));
    } else {
      opacity = 1;
    }

    // Emphasis: the newest bullet (slot closest to 0) is slightly brighter
    const emphasis = slot >= 0 && slot < 1 ? (1 - slot) : 0;

    items.push({ i, y, opacity, emphasis, text: lines[i] });
  }

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: BG,
      overflow: 'hidden',
    }}>
      {/* Ambient */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `
          radial-gradient(700px 400px at 15% 25%, ${PINK}1f, transparent),
          radial-gradient(900px 500px at 85% 75%, ${CARD_2}, transparent 70%)
        `,
      }}/>

      {/* Eyebrow */}
      <div style={{
        position: 'absolute', top: 120, left: 0, right: 0,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 18,
        color: MUTED, fontFamily: MONO, fontSize: 18, letterSpacing: '0.16em',
        opacity: eyebrowIn * (1 - eyebrowOut),
      }}>
        <span style={{ width: 28, height: 1, background: PINK }}/>
        WHAT THE PLATFORM DOES
        <span style={{ width: 28, height: 1, background: PINK }}/>
      </div>

      {/* Rolling window of bullets */}
      {items.map(({ i, y, opacity, emphasis, text }) => (
        <div key={i} style={{
          position: 'absolute',
          left: 0, right: 0,
          top: y,
          display: 'flex', alignItems: 'baseline', justifyContent: 'center',
          gap: 32,
          opacity,
          transition: 'opacity 120ms',
          pointerEvents: 'none',
        }}>
          <div style={{
            color: PINK,
            fontSize: 28, fontFamily: MONO, fontWeight: 500,
            fontVariantNumeric: 'tabular-nums',
            letterSpacing: '0.08em',
            minWidth: 64,
            textAlign: 'right',
          }}>
            {String(i + 1).padStart(2, '0')}
          </div>
          <div style={{
            color: `color-mix(in oklch, ${FG}, ${PINK} ${emphasis * 20}%)`,
            fontSize: 64,
            fontWeight: 600,
            letterSpacing: '-0.025em',
            lineHeight: 1.1,
            fontFamily: FONT,
            whiteSpace: 'nowrap',
          }}>
            {text}
          </div>
        </div>
      ))}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// BEAT 5 — The Close (0:12 – 0:15)
// ────────────────────────────────────────────────────────────────────────────
function Beat5Close({ parentTime, beatStart, beatEnd, totalDuration }) {
  // We receive absolute time info so the final sub-beat can cross-fade into Beat 1.
  const { localTime, duration } = useSprite();

  // Sub-beats (beat is 6s total):
  // 0.0–1.2  "Your managers don't need another course."
  // 1.2–2.4  "They need reps."
  // 2.4–5.6  Logo + CTA (pulse), holds ~3s longer than before
  // 5.6–6.0  Cross-fade back to beat 1 (seamless loop)
  const line1In = Easing.easeOutCubic(clamp(localTime / 0.45, 0, 1));
  const line1Out = localTime > 1.05 ? Easing.easeInCubic(clamp((localTime - 1.05) / 0.2, 0, 1)) : 0;

  const line2In = Easing.easeOutCubic(clamp((localTime - 1.25) / 0.45, 0, 1));
  const line2Out = localTime > 2.25 ? Easing.easeInCubic(clamp((localTime - 2.25) / 0.2, 0, 1)) : 0;

  const ctaIn = Easing.easeOutCubic(clamp((localTime - 2.45) / 0.55, 0, 1));
  // CTA pulse ~3.0s (first attention) and again ~4.6s (second nudge)
  const pulseA = (() => {
    const t = clamp((localTime - 2.9) / 0.6, 0, 1);
    return t > 0 && t < 1 ? Math.sin(t * Math.PI) : 0;
  })();
  const pulseB = (() => {
    const t = clamp((localTime - 4.6) / 0.6, 0, 1);
    return t > 0 && t < 1 ? Math.sin(t * Math.PI) : 0;
  })();
  const pulse = Math.max(pulseA, pulseB);

  // Cross-fade to beat 1 in the last 0.4s
  const fadeOut = localTime > (duration - 0.4) ? Easing.easeInOutCubic(clamp((localTime - (duration - 0.4)) / 0.4, 0, 1)) : 0;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: BG,
      opacity: 1 - fadeOut,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      overflow: 'hidden',
    }}>
      {/* Ambient */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(1100px 700px at 50% 50%, ${CARD_2} 0%, ${BG} 65%)`,
      }}/>

      {/* Line 1 */}
      {line1In > 0 && line1Out < 1 && (
        <div style={{
          position: 'absolute',
          left: 0, right: 0,
          top: '50%',
          transform: `translateY(calc(-50% + ${(1 - line1In) * 16 - line1Out * 12}px))`,
          textAlign: 'center',
          color: MUTED,
          fontSize: 104, fontWeight: 400, fontFamily: FONT,
          letterSpacing: '-0.03em', lineHeight: 1.08,
          opacity: line1In * (1 - line1Out),
          padding: '0 80px',
        }}>
          Your managers don't<br/>need another course.
        </div>
      )}

      {/* Line 2 */}
      {line2In > 0 && line2Out < 1 && (
        <div style={{
          position: 'absolute',
          left: 0, right: 0,
          top: '50%',
          transform: `translateY(calc(-50% + ${(1 - line2In) * 16 - line2Out * 12}px))`,
          textAlign: 'center',
          color: FG,
          fontSize: 180, fontWeight: 700, fontFamily: FONT,
          letterSpacing: '-0.04em', lineHeight: 1.02,
          opacity: line2In * (1 - line2Out),
        }}>
          They need reps.
        </div>
      )}

      {/* Logo + CTA */}
      {ctaIn > 0 && (
        <div style={{
          position: 'absolute', inset: 0,
          display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center',
          gap: 56,
          opacity: ctaIn,
          transform: `translateY(${(1 - ctaIn) * 14}px)`,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 28 }}>
            <img src="assets/logo.png" alt="" style={{
              width: 120, height: 120, objectFit: 'contain',
              filter: 'drop-shadow(0 6px 24px rgba(0,0,0,0.5))',
            }}/>
            <div style={{
              color: FG,
              fontSize: 96, fontWeight: 600, fontFamily: FONT,
              letterSpacing: '-0.03em',
            }}>
              LeaderCoreAI
            </div>
          </div>

          <div style={{
            padding: '30px 60px',
            background: PINK,
            borderRadius: 16,
            color: '#1a1a1a',
            fontSize: 40, fontWeight: 600, fontFamily: FONT,
            letterSpacing: '-0.01em',
            display: 'flex', alignItems: 'center', gap: 20,
            transform: `scale(${1 + pulse * 0.04})`,
            boxShadow: pulse > 0
              ? `0 0 ${50 * pulse}px ${14 * pulse}px rgba(175, 96, 146, ${0.45 * pulse})`
              : '0 12px 36px rgba(0,0,0,0.35)',
          }}>
            Start free trial
            <svg width="30" height="30" viewBox="0 0 24 24" fill="none">
              <path d="M5 12h14M13 5l7 7-7 7" stroke="#1a1a1a" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </div>

          <div style={{ color: DIM, fontSize: 20, fontFamily: FONT, letterSpacing: '0.02em' }}>
            GDPR compliant  ·  EU data hosting
          </div>
        </div>
      )}
    </div>
  );
}

// Expose everything
Object.assign(window, {
  Beat1Scenario, Beat2Chat, Beat3Score, Beat4Capabilities, Beat5Close,
});
