// Scenes 1-3: Hook → Setup → Generate
// All scenes assume the Stage canvas is 1920x1080 with cream bg #f6f4ef.

const FRAME = { x: 192, y: 96, w: 1536, h: 820 };
const SCENE_W = 1920;
const SCENE_H = 1080;

// ── Schedule data used by Scene 3 grid + Scenes 4-5 absent teacher ──────────
const DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
const SCHEDULE = [
  // Each: [subject, teacherName]
  [['Stem','Anita'], ['Math','Priya'], ['English','Sunita'], ['Library','Meera'], ['IT','Tarun'], ['Hindi','Neelam'], ['Hindi','Neelam'], ['Dance','Manish']],
  [['Art','Pooja'], ['Value','Latha'], ['Music','Devika'], ['Punjabi','Deepa'], ['Value','Latha'], ['Dance','Manish'], ['Music','Devika'], ['Hindi','Neelam']],
  [['French','Neelam'], ['Art','Pooja'], ['Social','Arjun'], ['Math','Priya'], ['IT','Tarun'], ['GK','Arjun'], ['French','Neelam'], ['Science','Anita']],
  [['Hindi','Neelam'], ['English','Tanvi'], ['Math','Priya'], ['PE','Hitesh'], ['Hindi','Neelam'], ['Social','Arjun'], ['Science','Anita'], ['English','Sunita']],
  [['Math','Priya'], ['Social','Arjun'], ['Science','Anita'], ['PE','Hitesh'], ['Math','Priya'], ['Punjabi','Deepa'], ['English','Sunita'], ['Social','Arjun']],
];

// ── SCENE 1 — OPENING / BRAND REVEAL (0-12s) ───────────────────────────────
// Beats:
//   0.0 – 2.0   "Schools evolved."
//   2.0 – 4.2   "Timetable scheduling hasn't." appears below
//   4.2 – 5.0   Both lines fade out
//   5.0 – 6.0   "Presenting" fades in (small, centered)
//   6.0 – 7.4   "Timetable Studio" wordmark drops in
//   7.4 – 8.2   Hold beat
//   8.2 – 9.0   Wordmark drifts upward, "Generate" button pops up below
//   9.0 – 10.2  Hand-drawn cursor enters and moves to the button
//  10.2 – 10.6  Click — button compresses, then pulses green
//  10.6 – 12.0  Button + wordmark fade, "Schedule the entire school in 5 simple steps." appears
function Scene1({ start = 0 }) {
  const tweaks = React.useContext(window.TweaksContext);
  const accent = (tweaks && tweaks.accent) || BRAND.green;
  const accentSoft = (tweaks && tweaks.accentSoft) || BRAND.greenSoft;
  const showEyebrow = !tweaks || tweaks.showPresenting !== false;
  const wordmarkWord = (tweaks && tweaks.wordmarkWord) || 'Studio';
  const cursorVariant = (tweaks && tweaks.cursorStyle) || 'dark';

  const t = useTime();
  const lt = t - start;
  // Scene 1 ends right after the Generate click pulse — the "Schedule
  // the whole school in 5 simple steps" tagline beat (Beat E) was
  // removed because it created a slow, redundant interstitial between
  // the click and the actual wizard. We now cut straight to Step 1.
  if (lt < -0.2 || lt > 10.8) return null;

  const sceneFade = interpolate([0, 0.3, 10.2, 10.6], [0, 1, 1, 0], Easing.easeOutCubic)(lt);

  // ── Beat A: "Schools evolved." word-by-word + "Timetable scheduling hasn't."
  const showA = lt < 5.0;
  const wordIn = (delay) => ({
    opacity: interpolate([delay, delay + 0.5], [0, 1], Easing.easeOutCubic)(lt),
    y: interpolate([delay, delay + 0.5], [28, 0], Easing.easeOutCubic)(lt),
  });
  const w1 = wordIn(0.25);  // "Schools"
  const w2 = wordIn(0.55);  // "evolved."
  const aFadeOut = interpolate([4.2, 5.0], [1, 0], Easing.easeInCubic)(lt);
  const aBlurOut = interpolate([4.2, 5.0], [0, 6], Easing.easeInCubic)(lt);

  const a2Op = interpolate([2.0, 3.0], [0, 1], Easing.easeOutCubic)(lt);
  const a2Y  = interpolate([2.0, 3.0], [28, 0], Easing.easeOutCubic)(lt);

  // ── Beat B: "Presenting" — slides in, holds, then drifts up as wordmark arrives
  const showB = lt >= 4.6 && lt < 7.4;
  const bOp = interpolate([4.6, 5.2, 6.4, 7.2], [0, 1, 1, 0], Easing.easeOutCubic)(lt);
  const bY  = interpolate([4.6, 5.2, 6.4, 7.2], [16, 0, 0, -30], Easing.easeOutCubic)(lt);
  // Letter-spacing expands slightly during hold for a cinematic feel
  const bLetterSpacing = interpolate([4.6, 6.0], [0.24, 0.42], Easing.easeOutCubic)(lt);

  // ── Beat C: "Timetable Studio" wordmark
  // Appears at 6.0, holds at center, then drifts up at 7.4 (BEFORE Generate)
  const showC = lt >= 5.8;
  const cOp = interpolate([5.8, 6.6, 10.2, 10.6], [0, 1, 1, 0], Easing.easeOutCubic)(lt);
  // Y travels: enters from below, lands centered, holds, then drifts upward
  const cY = interpolate(
    [5.8, 6.6,  7.4,  8.2],
    [60,  0,    0,    -130],
    [Easing.easeOutCubic, Easing.linear, Easing.easeInOutCubic]
  )(lt);
  const cScale = interpolate([5.8, 6.6], [0.92, 1], Easing.easeOutBack)(lt);

  // ── Beat D: Generate button — starts AFTER wordmark drift completes (8.2+)
  const showD = lt >= 8.2 && lt < 10.6;
  const dOp = interpolate([8.2, 9.0, 10.2, 10.6], [0, 1, 1, 0], Easing.easeOutCubic)(lt);
  const dY  = interpolate([8.2, 9.0], [40, 0], Easing.easeOutBack)(lt);
  const dScale = interpolate([8.2, 9.0], [0.7, 1], Easing.easeOutBack)(lt);
  // Click compression — subtle 6% squish at the moment of click
  const clickT = (lt - 10.35) / 0.18;
  const clickSquish = clickT > 0 && clickT < 1 ? 0.06 * Math.sin(clickT * Math.PI) : 0;
  // Pulse halo after click
  const haloOp = interpolate([10.45, 10.65, 11.1], [0, 0.7, 0], Easing.easeOutCubic)(lt);
  const haloScale = interpolate([10.45, 11.1], [1, 1.6], Easing.easeOutCubic)(lt);
  const buttonHot = lt > 9.8 && lt < 10.8;

  // ── Cursor — moves on an arc, lands ~10.3, settles
  const cursorOp = interpolate([9.0, 9.4, 10.4, 10.6], [0, 1, 1, 0], Easing.linear)(lt);
  const cursorT  = clamp((lt - 9.0) / 1.3, 0, 1);
  const cursorEase = Easing.easeOutCubic(cursorT);
  const cursorX = 1340 + (980 - 1340) * cursorEase;
  const arcLift = Math.sin(cursorEase * Math.PI) * 60;
  const cursorY = 880 + (680 - 880) * cursorEase - arcLift;
  const settle = lt > 10.3 && lt < 10.7 ? Math.sin((lt - 10.3) * 30) * 1.5 * Math.exp(-(lt - 10.3) * 8) : 0;

  // Beat E ("How it works / Schedule your whole school in 5 simple
  // steps.") was removed — see comment near the top of this scene.
  // The variables below are kept commented as a historical reference
  // in case someone wants to bring it back later.
  //
  //   const showE = lt >= 10.9;
  //   const eEyebrowOp = interpolate([10.9, 11.3], [0, 1], Easing.easeOutCubic)(lt);
  //   const e1Op = interpolate([11.05, 11.5], [0, 1], Easing.easeOutCubic)(lt);
  //   const e1Y  = interpolate([11.05, 11.5], [20, 0], Easing.easeOutCubic)(lt);
  //   const e2Op = interpolate([11.25, 11.85], [0, 1], Easing.easeOutBack)(lt);
  //   const e2Y  = interpolate([11.25, 11.85], [28, 0], Easing.easeOutBack)(lt);
  //   const e2Scale = interpolate([11.25, 11.85], [0.92, 1], Easing.easeOutBack)(lt);

  return (
    <div style={{ position: 'absolute', inset: 0, opacity: sceneFade }}>
      {/* Beat A */}
      {showA && (
        <React.Fragment>
          <div style={{
            position: 'absolute', left: 0, right: 0, top: 420,
            textAlign: 'center',
            opacity: aFadeOut,
            filter: `blur(${aBlurOut}px)`,
            fontSize: 110, fontWeight: 700, color: BRAND.ink,
            letterSpacing: '-0.04em', lineHeight: 1,
            fontFamily: BRAND.font,
          }}>
            <span style={{
              display: 'inline-block',
              opacity: w1.opacity,
              transform: `translateY(${w1.y}px)`,
            }}>Schools</span>
            {' '}
            <span style={{
              display: 'inline-block',
              opacity: w2.opacity,
              transform: `translateY(${w2.y}px)`,
              color: accent,
            }}>evolved.</span>
          </div>
          <div style={{
            position: 'absolute', left: 0, right: 0, top: 560,
            textAlign: 'center',
            opacity: a2Op * aFadeOut,
            transform: `translateY(${a2Y}px)`,
            filter: `blur(${aBlurOut}px)`,
            fontSize: 64, fontWeight: 500, color: BRAND.inkSoft,
            letterSpacing: '-0.02em', lineHeight: 1.1,
            fontFamily: BRAND.font,
          }}>
            Timetable scheduling hasn't.
          </div>
        </React.Fragment>
      )}

      {/* Beat B — "Presenting" */}
      {showB && showEyebrow && (
        <div style={{
          position: 'absolute', left: 0, right: 0, top: 440,
          textAlign: 'center',
          opacity: bOp,
          transform: `translateY(${bY}px)`,
          fontSize: 26, fontWeight: 700, color: accent,
          letterSpacing: `${bLetterSpacing}em`, textTransform: 'uppercase',
          fontFamily: BRAND.font,
        }}>
          Presenting
        </div>
      )}

      {/* Beat C — wordmark (with soft glow behind) */}
      {showC && (
        <React.Fragment>
          <div style={{
            position: 'absolute', left: '50%', top: 520,
            width: 1100, height: 220,
            transform: `translate(-50%, ${cY}px)`,
            background: `radial-gradient(ellipse at center, ${accentSoft} 0%, rgba(255,255,255,0) 60%)`,
            opacity: cOp * 0.6,
            pointerEvents: 'none',
          }}/>
          <div style={{
            position: 'absolute', left: 0, right: 0, top: 500,
            textAlign: 'center',
            opacity: cOp,
            transform: `translateY(${cY}px) scale(${cScale})`,
            transformOrigin: 'center',
            fontSize: 132, fontWeight: 700, color: BRAND.ink,
            letterSpacing: '-0.04em', lineHeight: 1,
            fontFamily: BRAND.font,
          }}>
            Timetable <span style={{ color: accent, fontStyle: 'italic' }}>{wordmarkWord}</span>
          </div>
        </React.Fragment>
      )}

      {/* Beat D — Generate button */}
      {showD && (
        <div style={{
          position: 'absolute', left: 0, right: 0, top: 600,
          display: 'flex', justifyContent: 'center',
          opacity: dOp,
          transform: `translateY(${dY}px)`,
        }}>
          <div style={{ position: 'relative' }}>
            {/* Halo pulse */}
            <div style={{
              position: 'absolute', inset: 0,
              borderRadius: 18,
              background: accentSoft,
              opacity: haloOp,
              transform: `scale(${haloScale})`,
              pointerEvents: 'none',
            }}/>
            <div style={{
              position: 'relative',
              display: 'inline-flex', alignItems: 'center', gap: 14,
              padding: '24px 40px', borderRadius: 18,
              background: accent, color: '#fff',
              fontSize: 36, fontWeight: 700,
              fontFamily: BRAND.font,
              letterSpacing: '-0.01em',
              transform: `scale(${dScale * (1 - clickSquish)})`,
              transformOrigin: 'center',
              boxShadow: buttonHot
                ? `0 0 0 10px ${accentSoft}, 0 18px 40px rgba(15,23,42,0.32)`
                : '0 8px 24px rgba(15,23,42,0.20)',
              transition: 'box-shadow 200ms',
            }}>
              <svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M12 3l2 5 5 2-5 2-2 5-2-5-5-2 5-2z"/>
              </svg>
              Generate
            </div>
          </div>
        </div>
      )}

      {/* Cursor */}
      {showD && (
        <Cursor x={cursorX} y={cursorY + settle} opacity={cursorOp} variant={cursorVariant}/>
      )}

      {/* Beat E — tagline */}
      {/* Beat E (the "Schedule your whole school in 5 simple steps."
       *  tagline) was removed — it created a 1.5s pause between the
       *  Generate-button click and the actual wizard, breaking flow.
       *  The scene now exits straight after the click pulse and Step 1
       *  cross-fades in. */}
    </div>
  );
}

// ── SCENE 2 — SETUP WIZARD (4.5-9.5s) ──────────────────────────────────────
function Scene2({ start = 4.5 }) {
  const t = useTime();
  const lt = t - start;
  if (lt < -0.2 || lt > 5.2) return null;

  const sceneFade = interpolate([0, 0.3, 4.8, 5.2], [0, 1, 1, 0], Easing.easeOutCubic)(lt);
  const frameY = interpolate([0, 0.4], [40, 0], Easing.easeOutCubic)(lt);

  // Steps tick on 0.6, 1.05, 1.5, 1.95, 2.4, 2.85 — completion at each
  const tickTimes = [0.7, 1.15, 1.6, 2.05, 2.5, 2.95];
  const completed = tickTimes.map((tt, i) => lt > tt ? i : -1).filter(i => i >= 0);
  const active = Math.min(5, completed.length);

  // After all done, big check + "Setup ready"
  const doneOp = interpolate([3.3, 3.8], [0, 1], Easing.easeOutCubic)(lt);
  const doneScale = interpolate([3.3, 3.9], [0.7, 1], Easing.easeOutBack)(lt);

  return (
    <div style={{ position: 'absolute', inset: 0, opacity: sceneFade, transform: `translateY(${frameY}px)` }}>
      <AppFrame x={FRAME.x} y={FRAME.y} width={FRAME.w} height={FRAME.h}>
        <TopChrome/>
        <div style={{ padding: '40px 56px' }}>
          <SectionLabel>Setup wizard</SectionLabel>
          <div style={{
            fontSize: 44, fontWeight: 700, color: BRAND.ink,
            letterSpacing: '-0.02em', marginTop: 8, marginBottom: 8,
          }}>
            Let's build your timetable.
          </div>
          <div style={{ fontSize: 17, color: BRAND.inkSoft, marginBottom: 36, maxWidth: 720 }}>
            Five quick steps. School, classes, periods, subjects, teachers — then generate.
          </div>

          <StepStrip active={active} completed={completed}/>

          {/* Below the strip: a check-burst + "Ready to generate" */}
          <div style={{
            marginTop: 64,
            display: 'flex', alignItems: 'center', gap: 24,
            opacity: doneOp,
            transform: `scale(${doneScale})`,
            transformOrigin: 'left center',
          }}>
            <div style={{
              width: 88, height: 88, borderRadius: 22,
              background: BRAND.greenSoft,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round">
                <path d="M4 12l5 5 11-12"/>
              </svg>
            </div>
            <div>
              <div style={{ fontSize: 32, fontWeight: 700, color: BRAND.ink, letterSpacing: '-0.02em' }}>
                Pre-flight check passed
              </div>
              <div style={{ fontSize: 17, color: BRAND.inkSoft, marginTop: 6 }}>
                13 classes · 29 teachers · 269 assignments · 0 conflicts
              </div>
            </div>
          </div>
        </div>
      </AppFrame>

      <Caption x={192} y={960} size={32} weight={500} color={BRAND.inkSoft}>
        <span style={{ color: BRAND.ink, fontWeight: 700 }}>Set it up once.</span>{' '}
        <span style={{ color: BRAND.inkSoft }}>Classes, periods, subjects, teachers — done.</span>
      </Caption>
    </div>
  );
}

// ── SCENE 3 — GENERATE TIMETABLE (9.5-17s) ──────────────────────────────────
function Scene3({ start = 9.5 }) {
  const t = useTime();
  const lt = t - start;
  if (lt < -0.2 || lt > 7.7) return null;

  const sceneFade = interpolate([0, 0.3, 7.3, 7.7], [0, 1, 1, 0], Easing.easeOutCubic)(lt);

  // Two phases:
  //  0.0 – 1.6 : "Ready to generate" card with pulsing button + cursor click
  //  1.6 – 7.3 : Timetable grid fills in cell by cell

  const showButton = lt < 2.1;
  const showGrid   = lt >= 1.5;

  // Cursor moves to button between 0.6 and 1.4, button pulses 1.0+
  const cursorX = interpolate([0.4, 1.4], [1300, 1180], Easing.easeOutCubic)(lt);
  const cursorY = interpolate([0.4, 1.4], [880, 590], Easing.easeOutCubic)(lt);
  const buttonHot = lt > 1.1 && lt < 1.7;
  const buttonScale = lt > 1.45 && lt < 1.6 ? 0.96 : 1;
  const buttonOp = interpolate([1.5, 2.0], [1, 0], Easing.easeInCubic)(lt);

  // Grid fill: 5 days × 8 periods = 40 cells. Fill from lt=1.8 to lt=5.5 (3.7s)
  const fillStart = 1.8;
  const fillEnd   = 5.6;
  const cellStagger = (r, c) => (r * 0.13) + (c * 0.07);
  const maxStagger = cellStagger(4, 7); // ~1.01
  const cellTotalTime = fillEnd - fillStart;

  // 100% pill after grid fills
  const filledPillOp = interpolate([5.7, 6.1], [0, 1], Easing.easeOutBack)(lt);
  const filledPillScale = interpolate([5.7, 6.1], [0.6, 1], Easing.easeOutBack)(lt);

  // Grid geometry — fits inside FRAME (1536 wide minus padding)
  const gridX = 56;
  const gridY = 200;
  const dayLabelW = 80;
  const periodH = 44;
  const cellW = (FRAME.w - 56 - 56 - dayLabelW) / 8; // ~150
  const cellH = 78;
  const gap = 6;

  return (
    <div style={{ position: 'absolute', inset: 0, opacity: sceneFade }}>
      <AppFrame x={FRAME.x} y={FRAME.y} width={FRAME.w} height={FRAME.h}>
        <TopChrome/>
        <div style={{ padding: '36px 56px' }}>
          <SectionLabel>Schedule</SectionLabel>
          <div style={{
            fontSize: 44, fontWeight: 700, color: BRAND.ink,
            letterSpacing: '-0.02em', marginTop: 8,
          }}>
            Generate timetable
          </div>

          {/* Phase 1: Ready-to-generate card with button + cursor */}
          {showButton && (
            <div style={{ marginTop: 36, opacity: buttonOp }}>
              <Card style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '28px 32px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
                  <div style={{
                    width: 56, height: 56, borderRadius: 14,
                    background: BRAND.greenSoft,
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                  }}>
                    <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M12 3l2 5 5 2-5 2-2 5-2-5-5-2 5-2z"/>
                    </svg>
                  </div>
                  <div>
                    <div style={{ fontSize: 24, fontWeight: 700, color: BRAND.ink }}>Ready to generate</div>
                    <div style={{ fontSize: 15, color: BRAND.inkSoft, marginTop: 4 }}>
                      269 assignments · 13 classes · 0 conflicts
                    </div>
                  </div>
                </div>
                <div style={{
                  transform: `scale(${buttonScale})`,
                  transition: 'transform 100ms',
                }}>
                  <PrimaryButton hot={buttonHot}>
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M12 3l2 5 5 2-5 2-2 5-2-5-5-2 5-2z"/>
                    </svg>
                    Generate timetable
                  </PrimaryButton>
                </div>
              </Card>
            </div>
          )}

          {/* Phase 2: Grid */}
          {showGrid && (
            <div style={{
              marginTop: 36,
              opacity: interpolate([1.5, 2.0], [0, 1], Easing.easeOutCubic)(lt),
            }}>
              <div style={{
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                marginBottom: 14,
              }}>
                <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
                  <Pill tone="ink">Class 4 · A</Pill>
                  <span style={{ fontSize: 13, color: BRAND.inkSoft }}>45 cells · 5 days</span>
                </div>
                <div style={{
                  opacity: filledPillOp,
                  transform: `scale(${filledPillScale})`,
                  transformOrigin: 'right center',
                  display: 'flex', alignItems: 'center', gap: 6,
                  padding: '6px 14px', borderRadius: 999,
                  background: BRAND.greenSoft, color: BRAND.green,
                  fontSize: 14, fontWeight: 700,
                }}>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M4 12l5 5 11-12"/></svg>
                  100% filled
                </div>
              </div>

              {/* Period header row */}
              <div style={{ display: 'flex', alignItems: 'center', gap, marginLeft: dayLabelW + gap, marginBottom: gap }}>
                {Array.from({length: 8}).map((_, c) => (
                  <div key={c} style={{
                    width: cellW, height: periodH,
                    background: '#fff', border: `1px solid ${BRAND.border}`,
                    borderRadius: 6,
                    display: 'flex', flexDirection: 'column',
                    justifyContent: 'center', alignItems: 'center',
                    fontFamily: BRAND.font,
                  }}>
                    <div style={{ fontSize: 9, fontWeight: 700, color: BRAND.inkSub, letterSpacing: '0.1em' }}>PERIOD</div>
                    <div style={{ fontSize: 15, fontWeight: 700, color: BRAND.ink }}>{c + 1}</div>
                  </div>
                ))}
              </div>

              {/* Day rows with cells */}
              {DAYS.map((day, r) => (
                <div key={day} style={{ display: 'flex', alignItems: 'center', gap, marginBottom: gap }}>
                  <div style={{
                    width: dayLabelW, height: cellH,
                    background: '#fff', border: `1px solid ${BRAND.border}`,
                    borderRadius: 6,
                    display: 'flex', flexDirection: 'column',
                    justifyContent: 'center', alignItems: 'center',
                  }}>
                    <div style={{ fontSize: 9, fontWeight: 700, color: BRAND.inkSub, letterSpacing: '0.1em' }}>DAY</div>
                    <div style={{ fontSize: 16, fontWeight: 700, color: BRAND.ink }}>{day}</div>
                  </div>
                  {SCHEDULE[r].map(([subj, teacher], c) => {
                    const cellStart = fillStart + cellStagger(r, c);
                    const cellEnd   = cellStart + 0.35;
                    const cellOp    = interpolate([cellStart, cellEnd], [0, 1], Easing.easeOutCubic)(lt);
                    const cellSc    = interpolate([cellStart, cellEnd], [0.7, 1], Easing.easeOutBack)(lt);
                    return (
                      <div key={c} style={{
                        opacity: cellOp,
                        transform: `scale(${cellSc})`,
                        transformOrigin: 'center',
                      }}>
                        <Cell subject={subj} teacher={teacher} w={cellW} h={cellH}/>
                      </div>
                    );
                  })}
                </div>
              ))}
            </div>
          )}
        </div>

        {/* Phase 1 cursor */}
        {showButton && (
          <Cursor x={cursorX} y={cursorY} opacity={interpolate([0.2, 0.45], [0, 1], Easing.easeOutCubic)(lt) * buttonOp}/>
        )}
      </AppFrame>

      <Caption x={192} y={960} size={32} weight={500} color={BRAND.inkSoft}>
        <span style={{ color: BRAND.ink, fontWeight: 700 }}>Conflict-free, by construction.</span>{' '}
        One click. The whole school, scheduled.
      </Caption>
    </div>
  );
}

// ── Helper: animated cursor ─────────────────────────────────────────────────
function Cursor({ x, y, opacity = 1, variant = 'dark' }) {
  const fill = variant === 'light' ? '#ffffff' : '#0f172a';
  const stroke = variant === 'light' ? '#0f172a' : '#ffffff';
  return (
    <svg
      width="36" height="42" viewBox="0 0 24 28"
      style={{
        position: 'absolute', left: x, top: y, opacity,
        filter: 'drop-shadow(0 4px 8px rgba(15,23,42,0.25))',
        pointerEvents: 'none',
      }}
    >
      <path d="M3 2L3 22 8.5 17 12 24 15 22.5 11.5 15.5 19 15.5 Z" fill={fill} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
    </svg>
  );
}

Object.assign(window, {
  FRAME, SCENE_W, SCENE_H, DAYS, SCHEDULE,
  Scene1, Scene2, Scene3, Cursor,
});
