// Ventrin promo — cinematic scenes
// Brand tokens lifted from prompt-security/landing/styles.css

const V = {
  bgPage:   '#f3f1ec',
  bg0:      '#faf8f4',
  bg1:      '#f1efe9',
  bg2:      '#e9e6df',
  ink:      '#1a1d21',
  ink2:     '#3a3f47',
  ink3:     '#5a6069',
  ink4:     '#808792',
  ink5:     '#a7acb4',
  line:     '#d8d3c8',
  lineSoft: '#e4e0d4',
  lineFirm: '#c4bfb3',
  blue:     '#2c4a6a',
  blue2:    '#4870a8',
  blueTint: '#dce5ef',
  amber:    '#a86e1a',
  amberTint:'#f6ead4',
  red:      '#8a2f2f',
  redTint:  '#f1dcdc',
  green:    '#2d5b3a',
  greenTint:'#dde7dc',
  dark:     '#0c1014',
  darkSoft: '#161b22',
  serif:    '"Source Serif 4", "Tiempos Text", Georgia, serif',
  sans:     'Inter, ui-sans-serif, system-ui, sans-serif',
  mono:     '"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace',
};

// ── Helpers ───────────────────────────────────────────────────────────────
function entry({ localTime, duration }, entryDur = 0.5, exitDur = 0.4, lift = 18) {
  const exitStart = Math.max(0, duration - exitDur);
  if (localTime < entryDur) {
    const t = Easing.easeOutCubic(clamp(localTime / entryDur, 0, 1));
    return { opacity: t, transform: `translateY(${(1 - t) * lift}px)` };
  }
  if (localTime > exitStart) {
    const t = Easing.easeInCubic(clamp((localTime - exitStart) / exitDur, 0, 1));
    return { opacity: 1 - t, transform: `translateY(${-t * lift * 0.5}px)` };
  }
  return { opacity: 1, transform: 'translateY(0)' };
}

function Typewriter({ text, progress, caret = true, time = 0, fontSize, color, font, weight, letterSpacing, lineHeight = 1.45 }) {
  const n = Math.floor(progress * text.length);
  const shown = text.slice(0, n);
  const caretOn = Math.floor(time * 2) % 2 === 0;
  return (
    <span style={{
      fontFamily: font, fontSize, color, fontWeight: weight,
      letterSpacing, lineHeight, whiteSpace: 'pre-wrap',
    }}>
      {shown}
      {caret && <span style={{
        display: 'inline-block', width: '0.55em', marginLeft: 1,
        background: caretOn ? color : 'transparent',
        height: '1em', verticalAlign: '-0.12em',
      }}/>}
    </span>
  );
}

function Logomark({ size = 24, fill }) {
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      width: size * 1.4, height: size * 1.4,
      borderRadius: 4, background: fill || V.ink, color: '#fff',
    }}>
      <svg viewBox="0 0 24 24" width={size * 0.7} height={size * 0.7} fill="none">
        <path d="M9 4H21V20H9V16H17V8H9V4ZM3 10H9V14H3V10ZM11 10H15V14H11V10Z" fill="currentColor"/>
      </svg>
    </span>
  );
}

function Eyebrow({ children, color = V.ink3, dotColor = V.blue }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 10,
      fontFamily: V.sans, fontSize: 14, fontWeight: 600,
      letterSpacing: '0.2em', textTransform: 'uppercase', color,
    }}>
      <span style={{ width: 8, height: 8, borderRadius: 4, background: dotColor }}/>
      <span>{children}</span>
    </div>
  );
}

function BrowserChrome({ url, ventrinActive = true, highlight = false }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14,
      padding: '14px 20px',
      borderBottom: `1px solid ${V.lineSoft}`,
      background: V.bg0,
    }}>
      <span style={{ display: 'flex', gap: 7 }}>
        <span style={{ width: 11, height: 11, borderRadius: 6, background: '#e5c1c1' }}/>
        <span style={{ width: 11, height: 11, borderRadius: 6, background: '#e6d6a8' }}/>
        <span style={{ width: 11, height: 11, borderRadius: 6, background: '#bcd6c3' }}/>
      </span>
      <span style={{
        flex: 1,
        fontFamily: V.mono, fontSize: 14, color: V.ink3,
        background: V.bg1,
        border: `1px solid ${V.lineSoft}`,
        padding: '6px 14px', borderRadius: 4, textAlign: 'left',
      }}>{url}</span>
      {ventrinActive && (
        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          fontFamily: V.sans, fontSize: 12, fontWeight: 600, letterSpacing: '0.16em',
          color: V.blue, background: V.blueTint,
          padding: '5px 10px', borderRadius: 999,
          textTransform: 'uppercase',
          boxShadow: highlight ? `0 0 0 3px ${V.blue}33` : 'none',
          transition: 'box-shadow 200ms',
        }}>
          <svg viewBox="0 0 24 24" width="11" height="11" fill="currentColor">
            <path d="M9 4H21V20H9V16H17V8H9V4ZM3 10H9V14H3V10ZM11 10H15V14H11V10Z"/>
          </svg>
          Ventrin
        </span>
      )}
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 1 — Cold open: the pain
// A frantic moment. A user has just hit send. Notifications cascade in.
// ═══════════════════════════════════════════════════════════════════════════
function SceneColdOpen({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;
        const e = entry(ctx, 0.3, 0.4, 0);

        return (
          <div style={{ position: 'absolute', inset: 0, ...e, background: V.bgPage }}>
            {/* Darkened context: a chat with a prompt that just got sent */}
            <div style={{
              position: 'absolute',
              left: 100, top: 110,
              width: 1100, height: 720,
              background: V.bg0,
              border: `1px solid ${V.line}`,
              borderRadius: 12,
              overflow: 'hidden',
              opacity: 0.86,
              filter: t > 1.4 ? 'blur(0.6px)' : 'none',
              transition: 'filter 400ms',
            }}>
              <BrowserChrome url="chat.openai.com" ventrinActive={false}/>
              <div style={{ padding: '32px 40px' }}>
                <div style={{ fontFamily: V.sans, fontSize: 12, fontWeight: 600, letterSpacing: '0.18em', color: V.ink4, textTransform: 'uppercase', marginBottom: 12 }}>
                  You · sent 11:42 AM
                </div>
                <div style={{
                  fontFamily: V.sans, fontSize: 24, color: V.ink, lineHeight: 1.5,
                  background: V.bg1, border: `1px solid ${V.line}`,
                  padding: '20px 24px', borderRadius: 10,
                }}>
                  Here's the full client roster — Sarah Chen (DOB 03/11/1984),
                  Marcus Webb (NHS 778 234 9911), Anya Volkov (passport
                  K9871234). Draft me a status memo for each, the matter is{' '}
                  <span style={{ color: V.red, fontWeight: 600 }}>Northgate v. Hensley</span>.
                  Use AWS key AKIA7QH3K9F8MRTZX2VL to pull their case files.
                </div>
                <div style={{
                  marginTop: 22,
                  display: 'flex', alignItems: 'center', gap: 10,
                  fontFamily: V.sans, fontSize: 14, color: V.ink4,
                }}>
                  <span style={{
                    display: 'inline-block', width: 14, height: 14, borderRadius: 2,
                    border: `2px solid ${V.ink4}`,
                    borderTopColor: 'transparent',
                    animation: 'vt-spin 0.8s linear infinite',
                  }}/>
                  ChatGPT is thinking…
                </div>
              </div>
            </div>

            {/* Red pulse around the chat once "sent" lands */}
            {t > 0.6 && t < 2.5 && (() => {
              const p = clamp((t - 0.6) / 1.4, 0, 1);
              return (
                <div style={{
                  position: 'absolute',
                  left: 100 - 8, top: 110 - 8,
                  width: 1100 + 16, height: 720 + 16,
                  borderRadius: 14,
                  border: `2px solid ${V.red}`,
                  opacity: (1 - p) * 0.6,
                  pointerEvents: 'none',
                  transform: `scale(${1 + p * 0.01})`,
                }}/>
              );
            })()}

            {/* Cascade of notifications top-right */}
            <Toast start={1.1} end={4.8} x={1320} y={140}
              variant="slack" icon="slack" source="Slack · #legal-ops"
              title="@you — wait, did you just paste the Northgate roster into ChatGPT?"
              subtitle="Mia · 11:42 AM"
            />
            <Toast start={1.8} end={4.8} x={1320} y={300}
              variant="compliance" icon="alert" source="Compliance · outbound monitor"
              title="PII leak suspected · client matter Northgate v. Hensley"
              subtitle="3 names · 1 NHS · 1 passport · 1 AWS key"
            />
            <Toast start={2.5} end={4.8} x={1320} y={460}
              variant="alert" icon="shield" source="SecOps"
              title="AWS credential exfiltration alert"
              subtitle="AKIA…RTZX2VL flagged 2 seconds ago"
            />

            {/* Caption */}
            <Caption start={2.8} end={4.8} y={920}
              text={<>By the time you notice, <em style={{ color: V.red, fontStyle: 'italic' }}>it&rsquo;s already sent.</em></>}
            />

            {/* Persistent timestamp ticker */}
            <div style={{
              position: 'absolute', top: 32, left: 56,
              fontFamily: V.mono, fontSize: 13, color: V.ink4, letterSpacing: '0.1em',
            }}>
              11:42:{String(Math.floor(t * 3) + 17).padStart(2, '0')} · TUE
            </div>
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 2 — Stat + Headline hook
// ═══════════════════════════════════════════════════════════════════════════
function SceneStatHook({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;

        return (
          <div style={{ position: 'absolute', inset: 0, background: V.bgPage,
            display: 'flex', flexDirection: 'column', justifyContent: 'center',
            padding: '0 160px',
          }}>
            {/* Big stat ticks up */}
            <div style={{
              opacity: clamp(t / 0.5, 0, 1),
              transform: `translateY(${(1 - clamp(t / 0.5, 0, 1)) * 18}px)`,
              marginBottom: 32,
            }}>
              <Eyebrow>The everyday reality</Eyebrow>
            </div>

            <div style={{
              display: 'flex', alignItems: 'baseline', gap: 32,
              opacity: clamp((t - 0.3) / 0.5, 0, 1),
              transform: `translateY(${(1 - clamp((t - 0.3) / 0.5, 0, 1)) * 24}px)`,
            }}>
              <div style={{
                fontFamily: V.serif, fontWeight: 500,
                fontSize: 260, lineHeight: 1, letterSpacing: '-0.04em',
                color: V.ink, fontVariantNumeric: 'tabular-nums',
              }}>
                <StatCounter from={0} to={73} start={0.4} end={2.0} suffix="%"/>
              </div>
              <div style={{
                fontFamily: V.sans, fontSize: 24, color: V.ink3,
                maxWidth: 540, lineHeight: 1.45, paddingBottom: 30,
              }}>
                of employees paste sensitive data into AI tools.
                <div style={{
                  fontFamily: V.mono, fontSize: 13, color: V.ink4,
                  letterSpacing: '0.1em', marginTop: 18, textTransform: 'uppercase',
                }}>Source · Internal survey, 2025</div>
              </div>
            </div>

            {/* Transition: shrink stat, reveal headline */}
            <div style={{
              marginTop: 80,
              opacity: clamp((t - 2.4) / 0.6, 0, 1),
              transform: `translateY(${(1 - clamp((t - 2.4) / 0.6, 0, 1)) * 24}px)`,
            }}>
              <h1 style={{
                margin: 0, fontFamily: V.serif, fontWeight: 500,
                fontSize: 100, lineHeight: 1.02, letterSpacing: '-0.025em',
                color: V.ink,
              }}>
                It&rsquo;s time to <em style={{ color: V.blue, fontStyle: 'italic' }}>control what ships.</em>
              </h1>
            </div>
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 3 — Cursor + typing, the user composes a risky prompt
// Camera starts wide on the chat, then dollies in on the input as Ventrin engages.
// ═══════════════════════════════════════════════════════════════════════════
const RISKY = "Summarise this contract for John Smith\n(DOB 14/06/1987, NHS 943 476 5919) at Acme Legal Ltd.\nKey terms, liabilities, AWS key AKIA7QH3K9F8MRTZX2VL.";

function SceneRisky({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;
        const e = entry(ctx, 0.4, 0.5, 0);

        // Typing 0.8s → 4.5s
        const typeProg = clamp((t - 0.8) / 3.7, 0, 1);
        // Camera dolly: start neutral, zoom into the input around t=2.5
        const cam = [
          { at: 0,   x: 0, y: 0, scale: 1.0 },
          { at: 1.8, x: 0, y: 0, scale: 1.0 },
          { at: 3.0, x: 60, y: -100, scale: 1.18 },
          { at: 5.5, x: 60, y: -100, scale: 1.18 },
        ];

        return (
          <div style={{ position: 'absolute', inset: 0, ...e, background: V.bgPage }}>
            <Camera keyframes={cam} origin="50% 60%">
              {/* Chat mock */}
              <div style={{
                position: 'absolute',
                left: '50%', top: 200,
                width: 1400, height: 800,
                transform: 'translateX(-50%)',
                background: V.bg0,
                border: `1px solid ${V.lineFirm}`,
                borderRadius: 14,
                boxShadow: '0 30px 80px -30px rgba(26,29,33,0.35)',
                overflow: 'hidden',
                display: 'flex', flexDirection: 'column',
              }}>
                <BrowserChrome url="chat.openai.com" highlight={t > 3.6}/>
                <div style={{ position: 'relative', flex: 1, padding: '48px 56px', display: 'flex', flexDirection: 'column' }}>
                  <div style={{
                    fontFamily: V.sans, fontSize: 13, fontWeight: 600,
                    letterSpacing: '0.18em', textTransform: 'uppercase',
                    color: V.ink4, marginBottom: 18,
                  }}>You · drafting</div>
                  <div style={{ minHeight: 320 }}>
                    <Typewriter
                      text={RISKY}
                      progress={typeProg}
                      time={t}
                      fontSize={34}
                      color={V.ink}
                      font={V.sans}
                      weight={400}
                      letterSpacing="-0.005em"
                    />
                  </div>
                  <div style={{
                    marginTop: 'auto',
                    display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                  }}>
                    <KeyHint keys={['⌘', '⇧', 'Enter']}/>
                    <button style={{
                      background: V.ink, color: '#fff',
                      border: 'none', borderRadius: 6,
                      padding: '14px 26px',
                      fontFamily: V.sans, fontSize: 16, fontWeight: 500,
                    }}>Send →</button>
                  </div>

                  {/* Ventrin "waking up" pill near input — activates as it detects risk */}
                  {t > 3.4 && (() => {
                    const p = clamp((t - 3.4) / 0.6, 0, 1);
                    return (
                      <div style={{
                        position: 'absolute',
                        right: 56, top: 56,
                        opacity: p,
                        transform: `translateY(${(1 - p) * -8}px)`,
                        background: V.dark, color: '#f3f1ec',
                        borderRadius: 8, padding: '14px 18px',
                        display: 'flex', alignItems: 'center', gap: 14,
                        fontFamily: V.sans, fontSize: 14, fontWeight: 500,
                        boxShadow: '0 18px 40px -16px rgba(0,0,0,0.4)',
                        border: `1px solid ${V.darkSoft}`, minWidth: 320,
                      }}>
                        <span style={{
                          width: 8, height: 8, borderRadius: 4,
                          background: V.amber, boxShadow: `0 0 10px ${V.amber}`,
                        }}/>
                        <div>
                          <div style={{ fontWeight: 600, letterSpacing: '0.04em' }}>VENTRIN — WATCHING</div>
                          <div style={{ fontSize: 12, color: '#a7acb4', marginTop: 2, fontFamily: V.mono }}>
                            Local model scanning before send…
                          </div>
                        </div>
                      </div>
                    );
                  })()}

                  {/* Cursor moves toward Send, gets close, hesitates */}
                  <Cursor
                    color={V.ink}
                    path={[
                      { at: 0,   x: 220, y: 220 },
                      { at: 0.6, x: 380, y: 280 },
                      { at: 0.9, x: 380, y: 280 },
                      { at: 4.6, x: 380, y: 280 },
                      { at: 5.2, x: 1200, y: 640 },
                    ]}
                  />
                </div>
              </div>
            </Camera>

            <Caption start={0.4} end={2.4} y={70}
              text={<>A real prompt, mid-thought.</>}
            />
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 4 — Intercept: the dramatic redaction beat
// ═══════════════════════════════════════════════════════════════════════════
const REDACTIONS = [
  { match: 'John Smith',              label: 'NAME',    kind: 'name' },
  { match: '14/06/1987',              label: 'DOB',     kind: 'dob' },
  { match: '943 476 5919',            label: 'NHS_ID',  kind: 'health' },
  { match: 'Acme Legal Ltd',          label: 'ORG',     kind: 'org' },
  { match: 'AKIA7QH3K9F8MRTZX2VL',    label: 'AWS_KEY', kind: 'secret' },
];

function RedactingText({ text, revealed, stage }) {
  let cursor = 0;
  const segs = [];
  while (cursor < text.length) {
    let next = null;
    for (let i = 0; i < REDACTIONS.length; i++) {
      if (i >= revealed) break;
      const r = REDACTIONS[i];
      const idx = text.indexOf(r.match, cursor);
      if (idx >= 0 && (next == null || idx < next.idx)) next = { idx, r };
    }
    if (!next) { segs.push({ kind: 'text', value: text.slice(cursor) }); break; }
    if (next.idx > cursor) segs.push({ kind: 'text', value: text.slice(cursor, next.idx) });
    segs.push({ kind: 'redact', r: next.r });
    cursor = next.idx + next.r.match.length;
  }

  return (
    <div style={{
      fontFamily: V.sans, fontSize: 34, color: V.ink, lineHeight: 1.45,
      whiteSpace: 'pre-wrap', letterSpacing: '-0.005em',
    }}>
      {segs.map((s, i) => {
        if (s.kind === 'text') return <span key={i}>{s.value}</span>;
        if (stage === 'redact' || stage === 'sanitized') {
          return (
            <span key={i} style={{
              display: 'inline-flex', alignItems: 'baseline', gap: 6,
              background: V.blueTint, color: V.blue,
              padding: '2px 12px', margin: '0 2px',
              borderRadius: 4,
              fontFamily: V.mono, fontWeight: 500, fontSize: 24,
              letterSpacing: '0.04em',
              border: `1px solid ${V.blue2}33`,
              transform: 'translateY(-2px)',
            }}>
              [{s.r.label}]
            </span>
          );
        }
        return (
          <span key={i} style={{
            background: V.amberTint, color: V.ink,
            padding: '2px 4px', borderRadius: 3,
            boxShadow: `inset 0 -2px 0 ${V.amber}`,
          }}>{s.r.match}</span>
        );
      })}
    </div>
  );
}

function SceneIntercept({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;
        const e = entry(ctx, 0.4, 0.5, 0);

        // Scan sweep 0.0 → 1.4
        // Highlights resolve at 1.5 → 2.5 (one per ~0.2s)
        // Collapse to [REDACTED] pills at 2.8
        const scanProg = t < 1.4 ? clamp(t / 1.4, 0, 1) : -1;
        const highlights = Math.min(REDACTIONS.length, Math.max(0, Math.floor((t - 1.5) / 0.2)));
        const stage = t < 2.8 ? 'highlight' : 'redact';
        const revealed = stage === 'highlight' ? highlights : REDACTIONS.length;
        const flash = t > 2.7 && t < 2.95 ? (1 - (t - 2.7) / 0.25) : 0;

        return (
          <div style={{ position: 'absolute', inset: 0, ...e, background: V.bgPage }}>
            {/* Chat mock anchored just below caption strip */}
            <div style={{
              position: 'absolute',
              left: '50%', top: 200,
              width: 1400, height: 800,
              transform: 'translateX(-50%) scale(1.04)',
              transformOrigin: '50% 0%',
              background: V.bg0,
              border: `1px solid ${V.lineFirm}`,
              borderRadius: 14,
              boxShadow: '0 30px 80px -30px rgba(26,29,33,0.35)',
              overflow: 'hidden',
              display: 'flex', flexDirection: 'column',
            }}>
              <BrowserChrome url="chat.openai.com" highlight={true}/>
              <div style={{ position: 'relative', flex: 1, padding: '48px 56px', display: 'flex', flexDirection: 'column' }}>
                <div style={{
                  fontFamily: V.sans, fontSize: 13, fontWeight: 600,
                  letterSpacing: '0.18em', textTransform: 'uppercase',
                  color: V.ink4, marginBottom: 18,
                }}>You · drafting</div>
                <div style={{ minHeight: 320, position: 'relative' }}>
                  <RedactingText text={RISKY} revealed={revealed} stage={stage}/>
                  {/* Scan line */}
                  {scanProg >= 0 && (
                    <div style={{
                      position: 'absolute',
                      left: -20, right: -20,
                      top: scanProg * 320,
                      height: 3,
                      background: `linear-gradient(90deg, transparent, ${V.blue2}, transparent)`,
                      boxShadow: `0 0 28px 4px ${V.blue2}66`,
                      pointerEvents: 'none',
                    }}/>
                  )}
                </div>

                <div style={{
                  marginTop: 'auto',
                  display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                }}>
                  <div style={{
                    display: 'inline-flex', alignItems: 'center', gap: 10,
                    fontFamily: V.mono, fontSize: 14, color: V.ink3,
                    background: V.bg2, padding: '8px 14px', borderRadius: 4,
                    border: `1px solid ${V.line}`,
                  }}>
                    <span style={{
                      width: 8, height: 8, borderRadius: 4,
                      background: stage === 'redact' ? V.green : V.amber,
                    }}/>
                    {stage === 'highlight'
                      ? `${highlights} identifier${highlights === 1 ? '' : 's'} found`
                      : `${REDACTIONS.length} identifiers removed locally`}
                  </div>
                  <button style={{
                    background: stage === 'redact' ? V.ink : V.bg2,
                    color: stage === 'redact' ? '#fff' : V.ink4,
                    border: 'none', borderRadius: 6,
                    padding: '14px 26px',
                    fontFamily: V.sans, fontSize: 16, fontWeight: 500,
                  }}>{stage === 'redact' ? 'Send safely →' : 'Hold'}</button>
                </div>
              </div>
            </div>

            {/* Side panel: detected items live ticker */}
            {t > 0.7 && (() => {
              const panelE = clamp((t - 0.7) / 0.5, 0, 1);
              return (
                <div style={{
                  position: 'absolute',
                  right: 100, top: 220,
                  width: 320,
                  opacity: panelE,
                  transform: `translateX(${(1 - panelE) * 16}px)`,
                  background: V.dark, color: '#f3f1ec',
                  borderRadius: 10, padding: '20px 22px',
                  boxShadow: '0 24px 60px -20px rgba(0,0,0,0.45)',
                  border: `1px solid ${V.darkSoft}`,
                  fontFamily: V.sans,
                  zIndex: 30,
                }}>
                  <div style={{
                    fontSize: 11, letterSpacing: '0.2em', fontWeight: 600,
                    color: V.blue2, textTransform: 'uppercase',
                  }}>Detected locally</div>
                  <div style={{
                    fontFamily: V.serif, fontSize: 22, fontWeight: 500,
                    marginTop: 8, marginBottom: 16, color: '#fff',
                  }}>Nothing leaves your device.</div>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                    {REDACTIONS.map((r, i) => {
                      const itemP = clamp((t - 1.5 - i * 0.2) / 0.35, 0, 1);
                      if (itemP <= 0) return null;
                      return (
                        <div key={r.label} style={{
                          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                          fontFamily: V.mono, fontSize: 13,
                          color: '#cfd6df',
                          opacity: itemP,
                          transform: `translateX(${(1 - itemP) * 8}px)`,
                          paddingBottom: 8,
                          borderBottom: i < REDACTIONS.length - 1 ? `1px solid ${V.darkSoft}` : 'none',
                        }}>
                          <span style={{ color: V.blue2, letterSpacing: '0.06em' }}>{r.label}</span>
                          <span style={{ color: '#8a929c' }}>{stage === 'redact' ? '✓ removed' : 'flagged'}</span>
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })()}

            {/* Flash on collapse */}
            {flash > 0 && (
              <div style={{
                position: 'absolute', inset: 0,
                background: '#fff', opacity: flash * 0.35, pointerEvents: 'none',
              }}/>
            )}

            <Caption start={0.2} end={2.6} y={70}
              text={<>Ventrin <em style={{ color: V.blue, fontStyle: 'italic' }}>intercepts</em> before send.</>}
            />
            <Caption start={3.0} end={5.4} y={70}
              text={<>Identifiers stripped <em style={{ color: V.blue, fontStyle: 'italic' }}>on your machine.</em></>}
            />
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 5 — Safe send to multiple AI tools
// ═══════════════════════════════════════════════════════════════════════════
function SceneSafeSend({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;
        const e = entry(ctx, 0.4, 0.5, 0);
        const fly = clamp(t / 1.8, 0, 1);

        return (
          <div style={{ position: 'absolute', inset: 0, ...e, background: V.bgPage,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            padding: '120px 100px 60px',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 60, width: '100%' }}>
              <div style={{
                flex: '0 0 580px',
                background: V.bg0,
                border: `1px solid ${V.lineFirm}`,
                borderRadius: 12,
                padding: '28px 32px',
                boxShadow: '0 18px 40px -18px rgba(26,29,33,0.25)',
              }}>
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  fontSize: 12, fontWeight: 600, letterSpacing: '0.18em',
                  color: V.green, textTransform: 'uppercase', marginBottom: 16,
                }}>
                  <span style={{ width: 8, height: 8, borderRadius: 4, background: V.green }}/>
                  Safe to send
                </div>
                <div style={{ fontFamily: V.sans, fontSize: 22, color: V.ink, lineHeight: 1.45 }}>
                  Summarise this contract for{' '}
                  {['NAME', 'DOB', 'NHS_ID', 'ORG', 'AWS_KEY'].map((l, i) => null)}
                  <span style={{ background: V.blueTint, color: V.blue, padding: '1px 8px', borderRadius: 3, fontFamily: V.mono, fontSize: 16, letterSpacing: '0.04em' }}>[NAME]</span>{' '}
                  (DOB <span style={{ background: V.blueTint, color: V.blue, padding: '1px 8px', borderRadius: 3, fontFamily: V.mono, fontSize: 16, letterSpacing: '0.04em' }}>[DOB]</span>, NHS{' '}
                  <span style={{ background: V.blueTint, color: V.blue, padding: '1px 8px', borderRadius: 3, fontFamily: V.mono, fontSize: 16, letterSpacing: '0.04em' }}>[NHS_ID]</span>) at{' '}
                  <span style={{ background: V.blueTint, color: V.blue, padding: '1px 8px', borderRadius: 3, fontFamily: V.mono, fontSize: 16, letterSpacing: '0.04em' }}>[ORG]</span>. Key terms, liabilities, AWS key{' '}
                  <span style={{ background: V.blueTint, color: V.blue, padding: '1px 8px', borderRadius: 3, fontFamily: V.mono, fontSize: 16, letterSpacing: '0.04em' }}>[AWS_KEY]</span>.
                </div>
              </div>

              <div style={{ flex: '0 0 180px', position: 'relative', height: 80 }}>
                <div style={{
                  position: 'absolute', top: '50%', left: 0, right: 0, height: 2,
                  background: `linear-gradient(90deg, ${V.line}, ${V.ink3})`,
                  transform: 'translateY(-50%)',
                }}/>
                <div style={{
                  position: 'absolute', top: '50%', left: `${fly * 100}%`,
                  width: 14, height: 14, borderRadius: 8,
                  background: V.blue, transform: 'translate(-50%, -50%)',
                  boxShadow: `0 0 18px ${V.blue2}`,
                }}/>
                <div style={{
                  position: 'absolute', top: '50%', right: -4,
                  width: 0, height: 0,
                  borderLeft: `12px solid ${V.ink3}`,
                  borderTop: '8px solid transparent',
                  borderBottom: '8px solid transparent',
                  transform: 'translateY(-50%)',
                }}/>
                <div style={{
                  position: 'absolute', top: -32, left: 0, right: 0,
                  textAlign: 'center', fontFamily: V.mono, fontSize: 13, color: V.ink3,
                  letterSpacing: '0.06em', textTransform: 'uppercase',
                }}>Sanitised prompt</div>
                <div style={{
                  position: 'absolute', bottom: -28, left: 0, right: 0,
                  textAlign: 'center', fontFamily: V.mono, fontSize: 12, color: V.ink4,
                }}>encrypted · over TLS</div>
              </div>

              <div style={{ flex: '0 0 360px', display: 'flex', flexDirection: 'column', gap: 14 }}>
                {[
                  { name: 'ChatGPT',  host: 'chat.openai.com' },
                  { name: 'Claude',   host: 'claude.ai' },
                  { name: 'Gemini',   host: 'gemini.google.com' },
                  { name: 'Copilot',  host: 'copilot.microsoft.com' },
                ].map((p, i) => {
                  const arrived = fly > 0.4 + i * 0.08;
                  return (
                    <div key={p.name} style={{
                      display: 'flex', alignItems: 'center', gap: 14,
                      background: V.bg0,
                      border: `1px solid ${arrived ? V.green : V.lineSoft}`,
                      borderRadius: 8,
                      padding: '14px 18px',
                      transition: 'border-color 200ms',
                      boxShadow: arrived ? `0 0 0 3px ${V.greenTint}` : 'none',
                    }}>
                      <span style={{
                        width: 32, height: 32, borderRadius: 6,
                        background: V.bg2,
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontFamily: V.serif, fontSize: 18, fontWeight: 600, color: V.ink2,
                      }}>{p.name[0]}</span>
                      <div style={{ flex: 1 }}>
                        <div style={{ fontFamily: V.sans, fontSize: 16, fontWeight: 500, color: V.ink }}>{p.name}</div>
                        <div style={{ fontFamily: V.mono, fontSize: 12, color: V.ink4 }}>{p.host}</div>
                      </div>
                      <span style={{
                        fontFamily: V.sans, fontSize: 11, fontWeight: 600,
                        letterSpacing: '0.16em', textTransform: 'uppercase',
                        color: arrived ? V.green : V.ink5,
                      }}>{arrived ? '✓ Protected' : '...'}</span>
                    </div>
                  );
                })}
              </div>
            </div>

            <Caption start={0.4} end={2.4} x={120} y={70}
              text={<>One control layer, <em style={{ color: V.blue, fontStyle: 'italic' }}>every AI tool.</em></>}
            />
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 6 — Dashboard glimpse: counters tick up
// ═══════════════════════════════════════════════════════════════════════════
function SceneDashboard({ start, end }) {
  const stats = [
    { label: 'Prompts protected this week',  from: 0,    to: 1247, suffix: '' },
    { label: 'Identifiers removed locally',  from: 0,    to: 3892, suffix: '' },
    { label: 'Sent to ChatGPT · Claude · Gemini', from: 0, to: 100, suffix: '%' },
    { label: 'Data that left your network',  from: 0,    to: 0,    suffix: '' },
  ];
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;
        const e = entry(ctx, 0.4, 0.5, 0);
        return (
          <div style={{ position: 'absolute', inset: 0, ...e, background: V.bgPage,
            display: 'flex', flexDirection: 'column',
            justifyContent: 'center', padding: '0 140px',
          }}>
            <div style={{
              marginBottom: 56,
              opacity: clamp(t / 0.5, 0, 1),
              transform: `translateY(${(1 - clamp(t / 0.5, 0, 1)) * 16}px)`,
            }}>
              <Eyebrow>Your team, this week</Eyebrow>
              <h2 style={{
                fontFamily: V.serif, fontWeight: 500,
                fontSize: 72, lineHeight: 1.06, letterSpacing: '-0.022em',
                color: V.ink, margin: '20px 0 0',
              }}>
                What you'd see <em style={{ color: V.blue, fontStyle: 'italic' }}>by Friday.</em>
              </h2>
            </div>

            <div style={{
              display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
              gap: 28,
            }}>
              {stats.map((s, i) => {
                const cp = clamp((t - 0.5 - i * 0.14) / 0.5, 0, 1);
                return (
                  <div key={s.label} style={{
                    background: V.bg0,
                    border: `1px solid ${V.line}`,
                    borderRadius: 10,
                    padding: '28px 28px 32px',
                    opacity: cp,
                    transform: `translateY(${(1 - cp) * 18}px)`,
                  }}>
                    <div style={{
                      fontFamily: V.serif, fontWeight: 500,
                      fontSize: 72, lineHeight: 1, letterSpacing: '-0.03em',
                      color: i === 3 ? V.green : V.ink,
                      fontVariantNumeric: 'tabular-nums',
                    }}>
                      <StatCounter from={s.from} to={s.to} start={0.6 + i * 0.14} end={2.0 + i * 0.14} suffix={s.suffix}/>
                    </div>
                    <div style={{
                      fontFamily: V.sans, fontSize: 16, color: V.ink3,
                      marginTop: 18, lineHeight: 1.4,
                    }}>{s.label}</div>
                  </div>
                );
              })}
            </div>

            <div style={{
              marginTop: 48,
              opacity: clamp((t - 2.4) / 0.5, 0, 1),
              fontFamily: V.mono, fontSize: 14, color: V.ink4,
              letterSpacing: '0.1em',
            }}>
              SHIPPED · v0.9 · Chrome, Edge, Arc · audit log exports as CSV
            </div>
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 7 — Value pillars
// ═══════════════════════════════════════════════════════════════════════════
function SceneValue({ start, end }) {
  const cards = [
    { eyebrow: 'LEGAL',   title: 'Client privilege, intact.', copy: 'Names, matter numbers, contract terms stay on-device.' },
    { eyebrow: 'HEALTH',  title: 'PHI never leaves the browser.', copy: 'NHS / MRN identifiers redacted before send. Audit-ready.' },
    { eyebrow: 'SECRETS', title: 'API keys can\u2019t slip out.', copy: 'AWS, GCP, OpenAI keys intercepted at the input field.' },
  ];
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const t = ctx.localTime;
        const e = entry(ctx, 0.4, 0.5, 0);
        return (
          <div style={{ position: 'absolute', inset: 0, ...e, background: V.bgPage,
            display: 'flex', flexDirection: 'column',
            alignItems: 'center', justifyContent: 'flex-start',
            padding: '140px 120px 80px',
          }}>
            <div style={{ marginBottom: 80, textAlign: 'center' }}>
              <Eyebrow>Built for regulated teams</Eyebrow>
              <h2 style={{
                fontFamily: V.serif, fontWeight: 500,
                fontSize: 64, lineHeight: 1.1, letterSpacing: '-0.022em',
                color: V.ink, margin: '22px 0 0', whiteSpace: 'nowrap',
              }}>
                Three kinds of data, <em style={{ color: V.blue, fontStyle: 'italic' }}>one control layer.</em>
              </h2>
            </div>
            <div style={{
              display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)',
              gap: 28, width: '100%', maxWidth: 1500,
            }}>
              {cards.map((c, i) => {
                const cp = clamp((t - 0.6 - i * 0.16) / 0.6, 0, 1);
                const ce = Easing.easeOutCubic(cp);
                return (
                  <div key={c.eyebrow} style={{
                    background: V.bg0, border: `1px solid ${V.line}`, borderRadius: 10,
                    padding: '32px 32px 36px',
                    opacity: ce, transform: `translateY(${(1 - ce) * 24}px)`,
                  }}>
                    <div style={{
                      display: 'inline-block', fontFamily: V.sans, fontSize: 13, fontWeight: 700,
                      letterSpacing: '0.18em', background: V.blueTint, color: V.blue,
                      padding: '5px 10px', borderRadius: 4,
                    }}>{c.eyebrow}</div>
                    <div style={{
                      fontFamily: V.serif, fontSize: 36, fontWeight: 500,
                      letterSpacing: '-0.018em', lineHeight: 1.15,
                      color: V.ink, marginTop: 22,
                    }}>{c.title}</div>
                    <div style={{
                      fontFamily: V.sans, fontSize: 19, color: V.ink3,
                      lineHeight: 1.5, marginTop: 16,
                    }}>{c.copy}</div>
                  </div>
                );
              })}
            </div>
          </div>
        );
      }}
    </Sprite>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// SCENE 8 — Close
// ═══════════════════════════════════════════════════════════════════════════
function SceneClose({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {(ctx) => {
        const e1 = entry(ctx, 0.5, 0.4, 24);
        const e2 = entry({ ...ctx, localTime: ctx.localTime - 0.25 }, 0.6, 0.4, 24);
        const e3 = entry({ ...ctx, localTime: ctx.localTime - 0.5 }, 0.5, 0.4, 18);
        const e4 = entry({ ...ctx, localTime: ctx.localTime - 0.75 }, 0.5, 0.4, 12);
        return (
          <div style={{
            position: 'absolute', inset: 0,
            background: V.dark,
            display: 'flex', flexDirection: 'column',
            alignItems: 'center', justifyContent: 'center',
            padding: '0 120px',
          }}>
            <div style={{
              position: 'absolute', inset: 0,
              background: `repeating-linear-gradient(0deg, transparent 0 24px, rgba(255,255,255,0.015) 24px 25px)`,
              pointerEvents: 'none',
            }}/>

            <div style={{
              ...e1,
              display: 'flex', alignItems: 'center', gap: 22, marginBottom: 52,
            }}>
              <svg viewBox="0 0 24 24" width="56" height="56" aria-hidden style={{ display: 'block' }}>
                <path d="M9 4H21V20H9V16H17V8H9V4ZM3 10H9V14H3V10ZM11 10H15V14H11V10Z" fill="#f3f1ec"/>
              </svg>
              <span style={{
                fontFamily: V.serif, fontWeight: 500, fontSize: 64,
                letterSpacing: '-0.025em', color: '#f3f1ec',
                lineHeight: 1,
              }}>Ventrin</span>
            </div>

            <h1 style={{
              ...e2,
              margin: 0, fontFamily: V.serif, fontWeight: 500,
              fontSize: 96, lineHeight: 1.06, letterSpacing: '-0.025em',
              color: '#f3f1ec', textAlign: 'center', maxWidth: 1400,
            }}>
              Control what your team{' '}
              <em style={{ color: V.blue2, fontStyle: 'italic' }}>sends to AI.</em>
            </h1>

            <div style={{ ...e3, display: 'flex', gap: 16, marginTop: 56 }}>
              <a href="/download.html" style={{
                background: '#f3f1ec', color: V.dark,
                padding: '18px 32px', borderRadius: 6,
                fontFamily: V.sans, fontSize: 20, fontWeight: 500,
                display: 'inline-flex', alignItems: 'center', gap: 12,
                textDecoration: 'none', cursor: 'pointer',
              }}>
                <svg viewBox="0 0 16 16" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M8 2v9"/><path d="M4 7l4 4 4-4"/><path d="M3 14h10"/>
                </svg>
                Download for Chrome
              </a>
              <a href="https://app.ventrin.com/sign-in" style={{
                background: 'transparent', color: '#f3f1ec',
                border: '1px solid rgba(255,255,255,0.15)',
                padding: '18px 32px', borderRadius: 6,
                fontFamily: V.sans, fontSize: 20, fontWeight: 500,
                textDecoration: 'none', cursor: 'pointer',
              }}>Request early access</a>
            </div>

            <div style={{
              ...e4, position: 'absolute', bottom: 56,
              fontFamily: V.mono, fontSize: 14,
              color: '#8a929c', letterSpacing: '0.16em',
              textTransform: 'uppercase',
            }}>ventrin.com</div>
          </div>
        );
      }}
    </Sprite>
  );
}

// ── Persistent UI: Ventrin pill + filename ────────────────────────────────
function PersistentChrome({ duration }) {
  const time = useTime();
  // Hide during cold open (0-5s) and close (last 5s)
  const inCold = time < 5;
  const closeStart = duration - 4.5;
  const inClose = time > closeStart;
  const opacity = (inCold || inClose) ? 0 : 1;
  return (
    <>
      <div style={{
        position: 'absolute', top: 36, right: 56,
        opacity, transition: 'opacity 400ms',
        display: 'inline-flex', alignItems: 'center', gap: 10,
        fontFamily: V.sans, fontSize: 13, fontWeight: 600,
        letterSpacing: '0.18em', textTransform: 'uppercase',
        color: V.blue, background: V.blueTint,
        padding: '8px 14px', borderRadius: 999,
      }}>
        <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
          <path d="M9 4H21V20H9V16H17V8H9V4ZM3 10H9V14H3V10ZM11 10H15V14H11V10Z"/>
        </svg>
        Ventrin
      </div>
    </>
  );
}

// CSS keyframes for spinner
const _styleNode = document.createElement('style');
_styleNode.textContent = `@keyframes vt-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`;
document.head.appendChild(_styleNode);

Object.assign(window, {
  V,
  SceneColdOpen, SceneStatHook, SceneRisky, SceneIntercept,
  SceneSafeSend, SceneDashboard, SceneValue, SceneClose,
  PersistentChrome,
});
