// demo-scenes.jsx — The 120-second cursor-walk through a1..a10
// Chapters mount real screens into <ScreenFrame> and overlay cursor + SFX + captions.

const CHAPTERS = [
  { start: 0,   end: 4,   label: 'Intro' },
  { start: 4,   end: 16,  label: 'Landing' },     // A1
  { start: 16,  end: 25,  label: 'Login' },       // A2
  { start: 25,  end: 31,  label: 'Magic link' },  // A3
  { start: 31,  end: 47,  label: 'Chat' },        // A4
  { start: 47,  end: 56,  label: 'Citation' },    // A5
  { start: 56,  end: 66,  label: 'Upload' },      // A6
  { start: 66,  end: 78,  label: 'Onboarding' },  // A7
  { start: 78,  end: 90,  label: 'Dashboard' },   // A8
  { start: 90,  end: 100, label: 'Audit' },       // A9
  { start: 100, end: 112, label: 'Platform' },    // A10
  { start: 112, end: 120, label: 'Outro' },
];

// ── Shared frame geometry: the a1..a10 artboards render inside a browser
// frame at x=160,y=110 → 1600×860 (less 38px chrome = 1600×822 content).
const FRAME = { x: 160, y: 110, w: 1600, h: 860, contentY: 110 + 38 };
// Helper: absolute stage coords from artboard-local (0..1600, 0..822)
const atX = (lx) => FRAME.x + lx;
const atY = (ly) => FRAME.contentY + ly;

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 00 — INTRO (0..4s): logomark fades up, tagline
// ═══════════════════════════════════════════════════════════════════════════
function SceneIntro() {
  const { localTime } = useSprite();
  const logoOp = Easing.easeOutCubic(Math.min(1, localTime / 0.8));
  const line1Op = Math.max(0, Math.min(1, (localTime - 0.6) / 0.6));
  const line2Op = Math.max(0, Math.min(1, (localTime - 1.1) / 0.6));
  const exitOp = localTime > 3.3 ? 1 - Math.min(1, (localTime - 3.3) / 0.7) : 1;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      background: 'radial-gradient(ellipse at center, oklch(0.22 0.04 255) 0%, #0a0a0a 70%)',
      opacity: exitOp,
      fontFamily: 'IBM Plex Sans, system-ui, sans-serif',
    }}>
      <div style={{
        opacity: logoOp,
        transform: `scale(${0.9 + 0.1 * logoOp}) translateY(${(1-logoOp) * 12}px)`,
        marginBottom: 24,
      }}>
        <CoreMindLogotype size={180} tagline={false} productLabel="VAULT"/>
      </div>
      <div style={{
        opacity: line2Op,
        transform: `translateY(${(1-line2Op) * 8}px)`,
        fontSize: 22, color: 'rgba(246,244,239,0.7)',
        letterSpacing: '-0.005em',
        marginTop: 8,
      }}>AI der kender jeres dokumenter · 2-min tour</div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 01 — LANDING (4..16s): scroll hero, hover CTA, click "Kom i gang"
// ═══════════════════════════════════════════════════════════════════════════
function SceneLanding() {
  const { localTime } = useSprite();
  // Cursor path in stage coords (1920×1080)
  const wp = [
    { t: 0,    x: 1700, y: 900 },
    { t: 0.6,  x: 1100, y: 620 },   // drift into hero
    { t: 2.8,  x: 1100, y: 620 },
    { t: 4.2,  x: 1260, y: 700 },   // hover "Se 2-min demo"
    { t: 6.5,  x: 1260, y: 700 },
    { t: 8.0,  x: 1505, y: 370 },   // up to "Kom i gang" in nav
    { t: 10.2, x: 1505, y: 370 },
    { t: 11.5, x: 870,  y: 700 },   // down to primary hero CTA
  ];
  const clicks = [
    { t: 11.6, x: 870, y: 700, color: 'oklch(0.78 0.12 250)' },
  ];

  // Mount A1 with a scroll offset that drifts slowly (parallax feel)
  const scrollRef = React.useRef(null);
  React.useEffect(() => {
    if (!scrollRef.current) return;
    const el = scrollRef.current.querySelector('.vault');
    if (el) {
      // Gentle scroll from 0 to ~180px over the scene
      const s = Math.max(0, Math.min(1, (localTime - 3) / 6));
      el.scrollTop = s * 220;
    }
  }, [localTime]);

  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com" glow={localTime < 0.6}>
        <div ref={scrollRef} style={{ width: '100%', height: '100%' }}>
          <A1Landing/>
        </div>
      </ScreenFrame>
      {/* Highlight demo card during hover */}
      <GlowPulse x={atX(870)} y={atY(380)} w={560} h={340} start={1.6} end={5.0}
        color="oklch(0.72 0.1 250)" radius={14}/>
      {/* Highlight primary CTA in hero ("Kom i gang") */}
      <GlowPulse x={atX(155)} y={atY(535)} w={200} h={52} start={10.5} end={12}
        color="oklch(0.78 0.12 250)" radius={10}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="01 · Landing"
        title="Kunderne lander på coremindvault.com"
        subtitle="Ét produkt, fire planer, én tenant pr. kunde — deres eget subdomæne, deres eget branding."
      />
      <SceneBadge num={1} label="Public"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 02 — LOGIN (16..25s): hover providers, pick magic link, type email
// ═══════════════════════════════════════════════════════════════════════════
function SceneLogin() {
  const { localTime } = useSprite();
  // Cursor coords are stage-absolute (1920×1080). Frame is at x=160,y=148 (content),
  // login card is 420px wide, centered in the ~1600px-wide frame content area.
  // Card horizontal center: atX(800) = 960. Input row y: atY(~560) ≈ 708.
  // "Send login-link" button y: atY(~620) ≈ 768.
  const wp = [
    { t: 0,   x: 870, y: 700 },
    { t: 0.8, x: 960, y: 500 },    // hover Microsoft row
    { t: 2.5, x: 960, y: 500 },
    { t: 3.3, x: 960, y: 555 },    // Google
    { t: 4.3, x: 960, y: 555 },
    { t: 5.2, x: 960, y: 710 },    // email input
    { t: 6.0, x: 960, y: 710 },
    { t: 7.2, x: 960, y: 770 },    // send login-link button
    { t: 8.4, x: 960, y: 770 },
  ];
  const clicks = [
    { t: 6.1, x: 960, y: 710, color: 'oklch(0.72 0.12 250)' },
    { t: 8.3, x: 960, y: 770, color: 'oklch(0.78 0.12 250)' },
  ];
  // Type email one char at a time, drive A2Login's internal state
  const emailStr = 'anders.n@horsens.dk';
  const typeStart = 6.2, typeEnd = 7.0;
  const charsShown = Math.max(0, Math.min(emailStr.length,
    Math.floor((localTime - typeStart) / (typeEnd - typeStart) * emailStr.length)));
  const typedEmail = localTime < typeStart ? '' : emailStr.slice(0, charsShown);
  const keyTimes = [];
  for (let i = 0; i < emailStr.length; i++) {
    keyTimes.push(typeStart + (i / emailStr.length) * (typeEnd - typeStart));
  }
  // After click at 8.3: flip A2 to 'sent' state via driven prop
  const drivenState = localTime > 8.5 ? 'sent' : 'default';

  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/login">
        <A2Login driven={{ email: typedEmail, state: drivenState }}/>
      </ScreenFrame>
      <GlowPulse x={atX(732)} y={atY(592)} w={456} h={44} start={5.0} end={7.2}
        color="oklch(0.72 0.12 250)" radius={8}/>
      <KeyFlashes times={keyTimes} x={960} y={710}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="02 · Login"
        title="Multi-provider auth — pr. tenant"
        subtitle="Entra SSO, Google Workspace eller magiske link. Konfigureret af tenant-admin, valgt af brugeren."
      />
      <SceneBadge num={2} label="Auth"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 03 — MAGIC CONFIRM (25..31s): click "Log ind nu"
// ═══════════════════════════════════════════════════════════════════════════
function SceneMagicConfirm() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,   x: 1100, y: 500 },
    { t: 1.2, x: 960,  y: 720 },   // onto "Log ind nu" button
    { t: 2.8, x: 960,  y: 720 },
    { t: 4.0, x: 1020, y: 620 },
  ];
  const clicks = [
    { t: 2.6, x: 960, y: 720, color: 'oklch(0.78 0.12 250)' },
  ];

  return (
    <>
      <ScreenFrame {...FRAME} url="coremindvault.com/m/link?t=••••••••">
        <A3MagicConfirm/>
      </ScreenFrame>
      <GlowPulse x={atX(732)} y={atY(620)} w={456} h={48} start={1.5} end={3.0}
        color="oklch(0.78 0.12 250)" radius={8}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="03 · Magic link"
        title="Et klik — og de er inde"
        subtitle="1-sekunds bekræftelse beskytter mod link-prefetch. Derefter: lige ind i deres egen chat-sti."
      />
      <SceneBadge num={3} label="Public"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 04 — CHAT (31..47s): question typed → streaming answer → mode switch
// Built from scratch (not mounting A4) for deterministic timing
// ═══════════════════════════════════════════════════════════════════════════
function SceneChat() {
  const { localTime } = useSprite();

  // Coordinates inside the 1600×822 frame content area
  const INPUT_Y = 740; // input field y (from top of frame content)
  const SEND_X_LOCAL = 1540; // send button x (local to frame)
  const MODE_Y = 158; // mode pill row y

  // Mode: green → blue → amber
  const mode = localTime > 14.2 ? 'amber' : localTime > 12.2 ? 'blue' : 'green';
  const modeColor = mode === 'green' ? 'oklch(0.74 0.14 150)' : mode === 'blue' ? 'oklch(0.68 0.14 240)' : 'oklch(0.78 0.14 75)';
  const modeLabel = mode === 'green' ? 'Foreslåede svar' : mode === 'blue' ? 'Fri chat' : 'Kun kilder';

  // Cursor waypoints (absolute stage coords)
  const wp = [
    { t: 0,    x: 1020, y: 620 },
    { t: 0.8,  x: 960,  y: atY(420) },                      // read curated card
    { t: 2.5,  x: 960,  y: atY(420) },
    { t: 3.5,  x: atX(200), y: atY(INPUT_Y) },              // to input field
    { t: 5.0,  x: atX(200), y: atY(INPUT_Y) },
    { t: 8.2,  x: atX(SEND_X_LOCAL), y: atY(INPUT_Y) },     // send button
    { t: 9.0,  x: atX(SEND_X_LOCAL), y: atY(INPUT_Y) },
    { t: 10.8, x: 960, y: atY(360) },                       // read streaming answer
    { t: 12.0, x: atX(300), y: atY(MODE_Y + 20) },          // blue mode pill (1/3)
    { t: 12.8, x: atX(300), y: atY(MODE_Y + 20) },
    { t: 13.8, x: atX(800), y: atY(MODE_Y + 20) },          // amber mode pill (2/3)
    { t: 14.5, x: atX(1300), y: atY(MODE_Y + 20) },         // wait... amber is 3/3
    { t: 15.5, x: atX(1300), y: atY(MODE_Y + 20) },
  ];
  const clicks = [
    { t: 8.9,  x: atX(SEND_X_LOCAL), y: atY(INPUT_Y), color: 'oklch(0.78 0.12 250)' },
    { t: 12.2, x: atX(800),  y: atY(MODE_Y + 20), color: 'oklch(0.68 0.14 240)' },
    { t: 14.2, x: atX(1300), y: atY(MODE_Y + 20), color: 'oklch(0.78 0.14 75)' },
  ];

  // Typed question timing
  const q = 'ATEX-alarm procedure?';
  const typeStart = 4.0, typeEnd = 8.0;
  const charsShown = localTime < typeStart ? 0
    : localTime >= typeEnd ? q.length
    : Math.floor(((localTime - typeStart) / (typeEnd - typeStart)) * q.length);
  const typedQ = q.slice(0, charsShown);
  const keyTimes = [];
  for (let i = 0; i < q.length; i++) keyTimes.push(typeStart + (i / q.length) * (typeEnd - typeStart));

  // Stream phase
  const streamStart = 9.2, streamEnd = 11.6;
  const streamText = 'Følg ATEX-alarmproceduren: evakuér zone, afbryd strøm via nødstop ved hoved-tavlen, ventilér minimum 15 minutter før nogen genindtræder. Brug ikke-gnistdannende værktøj ved inspektion.';
  const streamChars = localTime < streamStart ? 0
    : localTime >= streamEnd ? streamText.length
    : Math.floor(((localTime - streamStart) / (streamEnd - streamStart)) * streamText.length);
  const streamShown = streamText.slice(0, streamChars);
  const streaming = localTime >= streamStart && localTime < streamEnd;
  const answered = localTime >= streamEnd;
  const questionSent = localTime >= 8.9;

  // Curated suggestion cards visible while green & no question sent
  const showCurated = mode === 'green' && !questionSent;

  const modeBtns = [
    { k: 'green', label: 'Foreslåede svar', icon: 'sparkle' },
    { k: 'blue', label: 'Fri chat', icon: 'chat' },
    { k: 'amber', label: 'Kun kilder', icon: 'lock' },
  ];

  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/chat">
        <div className="vault" style={{ width: '100%', height: '100%', background: 'var(--bg-0)', display: 'flex', flexDirection: 'column' }}>
          {/* Top bar */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 20px', borderBottom: '1px solid var(--line-soft)' }}>
            <ShieldMark size={26}/>
            <div style={{ lineHeight: 1.2 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg-0)' }}>Demo Beredskab</div>
              <div style={{ fontSize: 11, color: 'var(--fg-3)' }}>Beredskabsassistent</div>
            </div>
            <span className="chip" style={{ marginLeft: 8, color: modeColor, background: `color-mix(in oklch, ${modeColor} 12%, transparent)`, borderColor: `color-mix(in oklch, ${modeColor} 30%, transparent)` }}>
              <I name="dot" className="icon-sm"/> {modeLabel}
            </span>
            <div style={{ marginLeft: 'auto', display: 'flex', gap: 6 }}>
              <button className="btn btn-ghost btn-sm"><I name="refresh" className="icon-sm"/> Ny session</button>
            </div>
          </div>

          {/* Mode switcher */}
          <div style={{ padding: '12px 20px 0' }}>
            <div style={{ background: 'var(--bg-2)', border: '1px solid var(--line-soft)', borderRadius: 10, padding: 4, display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 2 }}>
              {modeBtns.map(b => {
                const active = mode === b.k;
                const col = b.k === 'green' ? 'oklch(0.74 0.14 150)' : b.k === 'blue' ? 'oklch(0.68 0.14 240)' : 'oklch(0.78 0.14 75)';
                return (
                  <div key={b.k} style={{
                    padding: '10px 12px', borderRadius: 7, fontSize: 12, fontWeight: 500,
                    background: active ? col : 'transparent',
                    color: active ? 'oklch(0.15 0.02 80)' : 'var(--fg-2)',
                    display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'center',
                    transition: 'all 0.25s cubic-bezier(.5,1.6,.4,1)',
                  }}>
                    <I name={b.icon} className="icon-sm"/>
                    <span>{b.label}</span>
                  </div>
                );
              })}
            </div>
            <p style={{ fontSize: 11, color: 'var(--fg-3)', marginTop: 8, display: 'flex', alignItems: 'center', gap: 6 }}>
              <I name="info" className="icon-sm"/>
              {mode === 'green' ? 'Forslag fra godkendte dokumenter'
                : mode === 'blue' ? 'AI svarer frit med kilder'
                : 'Direkte citater — ingen AI-fortolkning'}
            </p>
          </div>

          {/* Chat area */}
          <div style={{ flex: 1, overflow: 'hidden', padding: '16px 20px 20px', display: 'flex', flexDirection: 'column', gap: 14 }}>
            {showCurated && (
              <div>
                <div className="label" style={{ marginBottom: 10 }}>Foreslåede spørgsmål</div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 8 }}>
                  {[
                    ['Kemi', 'Hvad gør jeg ved klor-udslip?'],
                    ['Sikkerhed', 'ATEX-alarm procedure'],
                    ['Ressourcer', 'Hvor finder jeg kemi-datablade?'],
                    ['Brand', 'Evakueringsprocedure for etageejendom'],
                  ].map(([cat, question]) => (
                    <div key={question} className="card" style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 6 }}>
                      <span style={{ fontSize: 10, color: 'var(--mode-green)', fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.06em' }}>{cat}</span>
                      <span style={{ fontSize: 13, color: 'var(--fg-0)', lineHeight: 1.4 }}>{question}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* User bubble (after send) */}
            {questionSent && (
              <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
                <div style={{ background: 'var(--primary)', color: 'var(--primary-fg)', padding: '10px 14px', borderRadius: '14px 14px 4px 14px', fontSize: 13, maxWidth: '75%', fontWeight: 500 }}>
                  {q}
                </div>
              </div>
            )}

            {/* Assistant streaming/answered bubble */}
            {(streaming || answered) && (
              <div style={{ alignSelf: 'flex-start', maxWidth: '80%' }}>
                <div style={{ background: 'var(--bg-2)', border: '1px solid var(--line-soft)', color: 'var(--fg-0)', padding: '12px 14px', borderRadius: '14px 14px 14px 4px', fontSize: 13, lineHeight: 1.55 }}>
                  {streaming ? streamShown : streamText}
                  {streaming && (
                    <span style={{ display: 'inline-block', width: 6, height: 14, background: 'var(--primary)', marginLeft: 2, verticalAlign: 'middle', animation: 'blinkcaret 0.9s steps(2) infinite' }}/>
                  )}
                </div>
                {answered && (
                  <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 8 }}>
                    <span className="chip" style={{ height: 24 }}>
                      <span className="mono" style={{ color: 'var(--primary-strong)', fontWeight: 600 }}>[1]</span>
                      <I name="filePdf" className="icon-sm"/> ATEX-vejledning § 2.1 · s. 8
                    </span>
                    <span className="chip" style={{ height: 24 }}>
                      <span className="mono" style={{ color: 'var(--primary-strong)', fontWeight: 600 }}>[2]</span>
                      <I name="filePdf" className="icon-sm"/> Nødstop-manual · s. 14
                    </span>
                  </div>
                )}
              </div>
            )}

            {mode === 'amber' && !questionSent && (
              <div style={{ border: '1px solid color-mix(in oklch, var(--mode-amber) 40%, transparent)', background: 'color-mix(in oklch, var(--mode-amber) 8%, transparent)', padding: 14, borderRadius: 10, fontSize: 13 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8, color: 'var(--mode-amber)', fontWeight: 500 }}>
                  <I name="warn" className="icon-sm"/> Sikkerheds-mode aktiv
                </div>
                <p style={{ color: 'var(--fg-1)' }}>Du modtager kun direkte citater fra godkendte kilder. AI tolker ikke.</p>
              </div>
            )}
          </div>

          {/* Input bar */}
          <div style={{ padding: '12px 20px 16px', borderTop: '1px solid var(--line-soft)' }}>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', background: 'var(--bg-2)', border: `1px solid ${streaming ? 'var(--primary)' : 'var(--line)'}`, borderRadius: 12, padding: 8 }}>
              <div style={{ flex: 1, color: 'var(--fg-0)', fontSize: 13, padding: '6px 8px', minHeight: 22, display: 'flex', alignItems: 'center' }}>
                {typedQ ? (
                  <>
                    <span>{typedQ}</span>
                    {localTime < 8.9 && <span style={{ display: 'inline-block', width: 2, height: 14, background: 'var(--primary)', marginLeft: 1, animation: 'blinkcaret 0.9s steps(2) infinite' }}/>}
                  </>
                ) : (
                  <span style={{ color: 'var(--fg-3)' }}>Spørg om procedurer, regler, dokumenter...</span>
                )}
              </div>
              <div className="btn btn-primary btn-sm" style={{ width: 32, height: 32, padding: 0, borderRadius: 7, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <I name="send" className="icon-sm"/>
              </div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: 'var(--fg-4)', marginTop: 6 }}>
              <span><span className="kbd">↵</span> Send · <span className="kbd">⇧↵</span> Linjeskift</span>
              <span>Svar genereres på baggrund af <span style={{ color: 'var(--fg-2)' }}>2.841</span> godkendte chunks</span>
            </div>
          </div>
        </div>
      </ScreenFrame>

      {/* Glow highlight on mode switcher */}
      <GlowPulse x={atX(20)} y={atY(138)} w={1560} h={56} start={11.8} end={15.5}
        color={modeColor} radius={10}/>
      {/* Glow on input while typing */}
      <GlowPulse x={atX(20)} y={atY(725)} w={1560} h={56} start={3.5} end={8.5}
        color="oklch(0.72 0.12 250)" radius={12}/>
      <KeyFlashes times={keyTimes} x={atX(220)} y={atY(INPUT_Y + 8)}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="04 · ChatView"
        title={localTime < 11 ? 'Spørg. Se svaret streame. Få kilder.' : `Mode: ${modeLabel}`}
        subtitle={localTime < 11
          ? 'Tre modes — grøn foreslår, blå svarer frit, gul citerer kun. Alle streames i realtid.'
          : mode === 'blue'
            ? 'Fri chat — AI må sammenfatte og forklare på tværs af kilder.'
            : mode === 'amber'
              ? 'Kun-kilder — rå citater, ingen AI-fortolkning. Til regel-verifikation.'
              : 'Foreslåede svar — kun fra godkendte dokumenter.'}
      />
      <SceneBadge num={4} label="Chat"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 05 — PDF MODAL (47..56s): click citation → PDF opens
// ═══════════════════════════════════════════════════════════════════════════
function ScenePdfModal() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,   x: 1150, y: 260 },
    { t: 1.2, x: 600,  y: 380 },   // hover citation chip
    { t: 2.5, x: 600,  y: 380 },
    { t: 4.5, x: 960,  y: 500 },   // read into highlighted chunk
    { t: 7.0, x: 960,  y: 500 },
    { t: 8.5, x: 1500, y: 700 },   // toward "Andre citerede steder"
  ];
  const clicks = [
    { t: 2.3, x: 600, y: 380, color: 'oklch(0.78 0.12 250)' },
  ];
  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/doc/Brandprocedure-2024">
        <A5PdfModal citation={{ n: 1, doc: 'Brandprocedure-2024', sec: '§ 4.2', page: 12 }} standalone/>
      </ScreenFrame>
      <GlowPulse x={atX(280)} y={atY(680)} w={720} h={160} start={2.6} end={7.5}
        color="oklch(0.78 0.12 250)" radius={4}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="05 · Citation → PDF"
        title="Klik [1] — se det i kilden"
        subtitle="Chunk fremhævet. Side. Version. Godkendt af hvem. Hver citation er falsifiérbar."
      />
      <SceneBadge num={5} label="Chat"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 06 — UPLOADER (56..66s): drag-drop, progress bars tick
// ═══════════════════════════════════════════════════════════════════════════
function SceneUploader() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,   x: 1500, y: 700 },
    { t: 1.0, x: 960,  y: 320 },   // into dropzone
    { t: 3.0, x: 960,  y: 320 },
    { t: 4.5, x: 960,  y: 620 },   // down to ingest row
    { t: 7.5, x: 960,  y: 620 },
    { t: 9.0, x: 1550, y: 300 },
  ];
  const clicks = [];
  // Animated dropzone pulse during 1.5..3.5
  const dropActive = localTime > 1.2 && localTime < 3.5;

  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/admin/dokumenter">
        <A6Uploader/>
        {dropActive && (
          <div style={{
            position: 'absolute', left: 20, right: 20, top: 120,
            height: 160,
            border: '2px dashed var(--primary)',
            borderRadius: 14,
            background: 'color-mix(in oklch, var(--primary) 8%, transparent)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            gap: 14,
            pointerEvents: 'none',
            zIndex: 10,
            animation: 'uploadpulse 1.2s ease-in-out infinite',
          }}>
            <div style={{
              width: 48, height: 48, borderRadius: 12,
              background: 'var(--primary)', color: 'var(--primary-fg)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <I name="upload" size={24}/>
            </div>
            <div style={{ color: 'var(--fg-0)', fontFamily: 'IBM Plex Sans' }}>
              <div style={{ fontSize: 15, fontWeight: 600 }}>Slip filerne her</div>
              <div style={{ fontSize: 12, color: 'var(--fg-2)' }}>PDF, Word, Excel, billeder · op til 50 MB pr. fil</div>
            </div>
          </div>
        )}
      </ScreenFrame>
      <GlowPulse x={atX(0)} y={atY(470)} w={1600} h={140} start={4.5} end={8.5}
        color="oklch(0.72 0.14 75)" radius={8}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="06 · Uploader"
        title="Træk. Drop. Indekseret."
        subtitle="Parse → chunk → embed → ACL pr. rolle. Hver fil er søgbar få sekunder efter drop."
      />
      <SceneBadge num={6} label="Tenant admin"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 07 — WIZARD (66..78s): step through onboarding
// ═══════════════════════════════════════════════════════════════════════════
function SceneWizard() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,    x: 1550, y: 300 },
    { t: 1.2,  x: 960,  y: 500 },
    { t: 3.5,  x: 960,  y: 500 },
    { t: 5.5,  x: 1470, y: 800 },   // next button
    { t: 6.5,  x: 1470, y: 800 },
    { t: 8.5,  x: 960,  y: 500 },   // back to content
    { t: 10.5, x: 960,  y: 500 },
    { t: 12,   x: 1470, y: 800 },
  ];
  const clicks = [
    { t: 6.3, x: 1470, y: 800, color: 'oklch(0.78 0.12 250)' },
  ];
  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/onboarding">
        <A7Wizard/>
      </ScreenFrame>
      <GlowPulse x={atX(0)} y={atY(0)} w={1600} h={64} start={0.8} end={3.5}
        color="oklch(0.78 0.12 250)" radius={0} intensity={0.6}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="07 · Onboarding-wizard"
        title="Seks trin til første svar"
        subtitle="Branding · auth-providers · kategorier · invitationer · første dokument · første chat. De fleste er live på under 10 min."
      />
      <SceneBadge num={7} label="Tenant admin"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 08 — DASHBOARD (78..90s): KPIs, hover chart
// ═══════════════════════════════════════════════════════════════════════════
function SceneDashboard() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,    x: 1470, y: 800 },
    { t: 1.2,  x: 700,  y: 300 },   // KPI 1
    { t: 2.8,  x: 1050, y: 300 },   // KPI 2
    { t: 4.0,  x: 1400, y: 300 },   // KPI 3
    { t: 5.5,  x: 1700, y: 300 },   // KPI 4 (low-confidence warning)
    { t: 7.5,  x: 1700, y: 300 },
    { t: 9.0,  x: 1000, y: 620 },   // chart area
    { t: 11.0, x: 1200, y: 620 },
  ];
  const clicks = [];
  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/admin">
        <A8Dashboard/>
      </ScreenFrame>
      {/* KPI glow sweep */}
      <GlowPulse x={atX(540)} y={atY(200)} w={270} h={120} start={0.9} end={2.4}
        color="oklch(0.74 0.14 150)" radius={10}/>
      <GlowPulse x={atX(860)} y={atY(200)} w={270} h={120} start={2.4} end={3.9}
        color="oklch(0.74 0.14 150)" radius={10}/>
      <GlowPulse x={atX(1180)} y={atY(200)} w={270} h={120} start={3.9} end={5.4}
        color="oklch(0.74 0.14 150)" radius={10}/>
      <GlowPulse x={atX(1500)} y={atY(200)} w={270} h={120} start={5.4} end={8.0}
        color="oklch(0.78 0.14 75)" radius={10}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="08 · Dashboard"
        title="Tenant-admin ser brugen — ikke indholdet"
        subtitle="Aggregerede KPI'er som standard. Individuel chat-indsigt kræver aktivt samtykke fra brugeren eller eksplicit tilsyns-årsag (logges særskilt)."
      />
      <SceneBadge num={8} label="Tenant admin"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 09 — AUDIT (90..100s): filter, expand row
// ═══════════════════════════════════════════════════════════════════════════
function SceneAudit() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,   x: 1200, y: 620 },
    { t: 1.2, x: 960,  y: 440 },
    { t: 3.0, x: 960,  y: 440 },
    { t: 4.5, x: 1550, y: 300 },   // export button
    { t: 6.0, x: 1550, y: 300 },
    { t: 7.5, x: 500,  y: 500 },
  ];
  const clicks = [];
  return (
    <>
      <ScreenFrame {...FRAME} url="demo.coremindvault.com/admin/audit">
        <A9Audit/>
      </ScreenFrame>
      <GlowPulse x={atX(20)} y={atY(180)} w={1560} h={340} start={1.2} end={7.5}
        color="oklch(0.72 0.12 250)" radius={12} intensity={0.7}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="09 · Audit log"
        title="Hver handling — metadata, ikke indhold"
        subtitle="Hvem, hvornår, hvilket dokument. Ikke hvad chat'en sagde. Brugere ser deres eget log; admins ser tenant-niveau. GDPR-klar."
      />
      <SceneBadge num={9} label="Tenant admin"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 10 — PLATFORM (100..112s): zero-trust drilldown
// ═══════════════════════════════════════════════════════════════════════════
function ScenePlatform() {
  const { localTime } = useSprite();
  const wp = [
    { t: 0,   x: 500, y: 500 },
    { t: 1.5, x: 960, y: 300 },   // ZT-beskyttet chip
    { t: 3.5, x: 960, y: 300 },
    { t: 5.0, x: 960, y: 620 },   // metadata-only content
    { t: 9.0, x: 960, y: 620 },
    { t: 11.0, x: 1000, y: 400 },
  ];
  const clicks = [];
  return (
    <>
      <ScreenFrame {...FRAME} url="admin.coremindvault.com/tenants/horsens">
        <A10Platform/>
      </ScreenFrame>
      <GlowPulse x={atX(240)} y={atY(30)} w={180} h={30} start={1.3} end={4.5}
        color="oklch(0.78 0.14 75)" radius={6}/>
      <Cursor waypoints={wp} clicks={clicks}/>
      <Caption
        chapter="10 · Platform admin"
        title="Zero-trust — også for os"
        subtitle="CoreMind-medarbejdere ser kun metadata. Kunde-data kræver signeret, tidsbegrænset support-grant."
      />
      <SceneBadge num={10} label="Platform"/>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 11 — OUTRO (112..120s): tagline + CTA
// ═══════════════════════════════════════════════════════════════════════════
function SceneOutro() {
  const { localTime } = useSprite();
  const op1 = Easing.easeOutCubic(Math.min(1, localTime / 0.8));
  const op2 = Math.max(0, Math.min(1, (localTime - 0.8) / 0.6));
  const op3 = Math.max(0, Math.min(1, (localTime - 1.6) / 0.6));
  const op4 = Math.max(0, Math.min(1, (localTime - 2.6) / 0.6));

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      background: 'radial-gradient(ellipse at center, oklch(0.22 0.04 255) 0%, #0a0a0a 70%)',
      fontFamily: 'IBM Plex Sans, system-ui, sans-serif',
    }}>
      <div style={{
        opacity: op1,
        transform: `scale(${0.92 + 0.08 * op1}) translateY(${(1-op1) * 10}px)`,
        marginBottom: 32,
      }}>
        <CoreMindLogotype size={170} tagline={false} productLabel="VAULT"/>
      </div>
      <div style={{
        opacity: op2,
        transform: `translateY(${(1-op2) * 10}px)`,
        fontSize: 58, fontWeight: 600, letterSpacing: '-0.025em',
        color: '#f6f4ef', marginBottom: 16, textAlign: 'center',
        lineHeight: 1.05,
      }}>AI der kender<br/>
        <span style={{ color: 'oklch(0.78 0.14 250)' }}>jeres dokumenter.</span>
      </div>
      <div style={{
        opacity: op3,
        fontSize: 19, color: 'rgba(246,244,239,0.72)',
        marginBottom: 36, letterSpacing: '-0.005em',
      }}>
        EU-only · Zero-trust · Citater pr. svar · 3 min til første svar
      </div>
      <div style={{
        opacity: op4, display: 'flex', gap: 16, alignItems: 'center',
      }}>
        <div style={{
          background: 'oklch(0.78 0.14 250)',
          color: '#0a0a0a',
          padding: '18px 34px',
          borderRadius: 10,
          fontSize: 18, fontWeight: 600,
          boxShadow: '0 0 50px color-mix(in oklch, oklch(0.78 0.14 250) 60%, transparent)',
        }}>Kom i gang →</div>
        <div style={{
          padding: '18px 28px',
          fontFamily: 'IBM Plex Mono, monospace',
          fontSize: 16, color: '#f6f4ef',
          borderRadius: 10,
          border: '1px solid rgba(255,255,255,0.22)',
          background: 'rgba(255,255,255,0.04)',
        }}>coremindvault.com</div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// MAIN COMPOSER
// ═══════════════════════════════════════════════════════════════════════════
function DemoScenes() {
  return (
    <>
      {/* Keyframes for local overlays */}
      <style>{`
        @keyframes blinkcaret { 0%,49%{opacity:1} 50%,100%{opacity:0} }
        @keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
        @keyframes uploadpulse {
          0%,100% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--primary) 35%, transparent); }
          50%     { box-shadow: 0 0 0 14px color-mix(in oklch, var(--primary) 0%, transparent); }
        }
      `}</style>

      <ChapterProgress chapters={CHAPTERS}/>

      <Sprite start={0}    end={4.2}><SceneIntro/></Sprite>
      <Sprite start={4}    end={16.2}><SceneLanding/></Sprite>
      <Sprite start={16}   end={25.2}><SceneLogin/></Sprite>
      <Sprite start={25}   end={31.2}><SceneMagicConfirm/></Sprite>
      <Sprite start={31}   end={47.2}><SceneChat/></Sprite>
      <Sprite start={47}   end={56.2}><ScenePdfModal/></Sprite>
      <Sprite start={56}   end={66.2}><SceneUploader/></Sprite>
      <Sprite start={66}   end={78.2}><SceneWizard/></Sprite>
      <Sprite start={78}   end={90.2}><SceneDashboard/></Sprite>
      <Sprite start={90}   end={100.2}><SceneAudit/></Sprite>
      <Sprite start={100}  end={112.2}><ScenePlatform/></Sprite>
      <Sprite start={112}  end={120}><SceneOutro/></Sprite>
    </>
  );
}

window.DemoScenes = DemoScenes;
