/* Regably product demo video — "From setup to sold out."
   24s looping timeline built on the animations.jsx starter (Stage/Sprite).
   Mounted by demo-video.html; embedded on the marketing home page. */

const { Stage, Sprite, useTime, useSprite, Easing, animate, interpolate, clamp } = window;

const V = {
  blue: '#2563EB', blueDark: '#1D4ED8', ink: '#0F172A',
  text: '#0F172A', sub: '#64748B', faint: '#94A3B8',
  border: '#E2E8F0', subtle: '#F1F5F9', bg: '#F8FAFC',
  green: '#059669', greenSoft: '#ECFDF5', greenText: '#047857',
  org: '#1F7A4D',
  amber: '#B45309', amberSoft: '#FFFBEB',
  sans: "'Inter', system-ui, sans-serif",
  disp: "'Inter Tight','Inter',sans-serif",
  mono: "'JetBrains Mono', monospace",
  badge: "'Saira Condensed','Inter',sans-serif",
};

/* ---------- helpers ---------- */

function TypeText({ text, start, cps = 16, style }) {
  const t = useTime();
  const n = clamp(Math.floor((t - start) * cps), 0, text.length);
  const typing = t >= start && n < text.length;
  return (
    <span style={style}>
      {text.slice(0, n)}
      {typing && <span style={{ borderRight: `2px solid ${V.blue}`, marginLeft: 1 }} />}
    </span>
  );
}

function Counter({ from, to, start, end, prefix = '', style }) {
  const t = useTime();
  const v = animate({ from, to, start, end, ease: Easing.easeOutCubic })(t);
  return <span style={style}>{prefix}{Math.round(v).toLocaleString('en-US')}</span>;
}

function Cursor({ frames, clicks = [] }) {
  const t = useTime();
  if (t < frames[0].t - 0.01 || t > frames[frames.length - 1].t + 1.2) return null;
  const xs = interpolate(frames.map(f => f.t), frames.map(f => f.x), Easing.easeInOutCubic);
  const ys = interpolate(frames.map(f => f.t), frames.map(f => f.y), Easing.easeInOutCubic);
  const x = xs(t), y = ys(t);
  const click = clicks.find(c => t >= c && t <= c + 0.45);
  const cp = click ? (t - click) / 0.45 : 0;
  return (
    <div style={{ position: 'absolute', left: x, top: y, zIndex: 50, pointerEvents: 'none' }}>
      {click && (
        <div style={{
          position: 'absolute', left: -14, top: -14, width: 28, height: 28, borderRadius: 99,
          border: `2px solid ${V.blue}`, opacity: 1 - cp, transform: `scale(${0.4 + cp * 1.1})`,
        }} />
      )}
      <svg width="22" height="22" viewBox="0 0 24 24" style={{ filter: 'drop-shadow(0 2px 3px rgba(15,23,42,0.35))', transform: click && cp < 0.3 ? 'scale(0.86)' : 'scale(1)' }}>
        <path d="M5.5 3.2v17.6c0 .45.54.67.85.35l4.4-4.4a.5.5 0 0 1 .36-.15h6.2c.45 0 .67-.54.35-.85L6.35 2.85a.5.5 0 0 0-.85.35Z" fill="#0F172A" stroke="#fff" strokeWidth="1.4" />
      </svg>
    </div>
  );
}

function Rise({ start, dur = 0.5, dy = 14, children, style }) {
  const t = useTime();
  const p = Easing.easeOutCubic(clamp((t - start) / dur, 0, 1));
  return <div style={{ opacity: p, transform: `translateY(${(1 - p) * dy}px)`, ...style }}>{children}</div>;
}

/* ---------- browser frame + camera ---------- */

function Browser({ url, children }) {
  return (
    <div style={{
      position: 'absolute', left: 180, top: 70, width: 920, height: 580,
      background: '#fff', borderRadius: 14, border: `1px solid ${V.border}`,
      boxShadow: '0 24px 60px -12px rgba(15,23,42,0.18)', overflow: 'hidden',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '12px 16px', borderBottom: `1px solid ${V.subtle}`, background: V.bg }}>
        {[0, 1, 2].map(i => <span key={i} style={{ width: 10, height: 10, borderRadius: 99, background: '#CBD5E1' }} />)}
        <span style={{ marginLeft: 12, fontFamily: V.mono, fontSize: 12, color: V.sub, background: '#fff', border: `1px solid ${V.border}`, borderRadius: 99, padding: '4px 14px', whiteSpace: 'nowrap' }}>{url}</span>
      </div>
      <div style={{ position: 'relative', height: 535 }}>{children}</div>
    </div>
  );
}

const camScale = interpolate(
  [2.4, 3.2, 4.2, 7.8, 8.6, 9.0, 9.8, 12.3, 12.6, 14.4, 14.6, 15.4, 17.4, 18.2, 20.6, 20.9, 21.8, 26.2, 26.9, 27.8, 32.2, 32.7, 33.6, 38.0, 38.6],
  [0.94, 1.0, 1.0, 1.16, 1.16, 1.0, 1.18, 1.18, 1.3, 1.3, 1.0, 1.12, 1.12, 1.06, 1.06, 1.0, 1.1, 1.1, 1.0, 1.14, 1.14, 1.0, 1.08, 1.08, 0.98],
  Easing.easeInOutCubic
);
const camX = interpolate(
  [2.4, 4.2, 7.8, 9.0, 9.8, 14.4, 14.6, 15.4, 17.4, 18.2, 21.0],
  [0, 0, -40, 0, 0, 0, 0, 30, 30, 10, 0],
  Easing.easeInOutCubic
);
const camY = interpolate(
  [2.4, 4.2, 7.8, 9.0, 9.8, 12.6, 14.4, 14.6, 15.4, 17.8, 18.2, 21.0],
  [0, 0, -30, 0, -20, 30, 30, 0, 50, -20, -10, 0],
  Easing.easeInOutCubic
);

function Camera({ children }) {
  const t = useTime();
  const fade = Math.min(
    animate({ from: 0, to: 1, start: 2.4, end: 3.0 })(t),
    animate({ from: 1, to: 0, start: 38.2, end: 38.8 })(t)
  );
  return (
    <div style={{
      position: 'absolute', inset: 0, opacity: fade,
      transform: `scale(${camScale(t)}) translate(${camX(t)}px, ${camY(t)}px)`,
      transformOrigin: '640px 360px', willChange: 'transform, opacity',
    }}>
      {children}
    </div>
  );
}

/* ---------- shared mini-UI ---------- */

function Field({ label, width = '100%', children }) {
  return (
    <div style={{ width }}>
      <div style={{ fontSize: 12, fontWeight: 600, color: V.text, marginBottom: 6, fontFamily: V.sans }}>{label}</div>
      <div style={{ height: 38, border: `1px solid ${V.border}`, borderRadius: 6, display: 'flex', alignItems: 'center', padding: '0 12px', fontSize: 14, fontFamily: V.sans, background: '#fff', whiteSpace: 'nowrap', overflow: 'hidden' }}>
        {children}
      </div>
    </div>
  );
}

/* ---------- Scene 1 · title ---------- */

function TitleScene() {
  return (
    <Sprite start={0} end={2.5}>
      {({ localTime }) => {
        const out = animate({ from: 1, to: 0, start: 2.0, end: 2.45 })(localTime);
        return (
          <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', opacity: out }}>
            <div style={{ textAlign: 'center' }}>
              <Rise start={0.15} dur={0.6}><img src="../../assets/wordmark.svg" style={{ height: 52 }} alt="Regably" /></Rise>
              <Rise start={0.55} dur={0.6}>
                <div style={{ fontFamily: V.disp, fontSize: 30, fontWeight: 600, letterSpacing: '-0.02em', color: V.sub, marginTop: 22, whiteSpace: 'nowrap' }}>
                  From setup to sold out.
                </div>
              </Rise>
            </div>
          </div>
        );
      }}
    </Sprite>
  );
}

/* ---------- Scene 2 · admin setup (2.4–8.6) ---------- */

function SetupScene() {
  const t = useTime();
  const published = t >= 7.5;
  return (
    <Sprite start={2.4} end={8.6}>
      <Browser url="app.regably.com/conferences/new">
        <div style={{ position: 'absolute', left: 230, top: 30, width: 460 }}>
          <Rise start={2.7}>
            <div style={{ fontFamily: V.disp, fontSize: 22, fontWeight: 700, letterSpacing: '-0.01em', color: V.text }}>New conference</div>
            <div style={{ fontSize: 13, color: V.sub, marginTop: 3, fontFamily: V.sans }}>Set it up once. Registration runs itself.</div>
          </Rise>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginTop: 20 }}>
            <Rise start={3.0}><Field label="Conference name"><TypeText text="2026 Grid Summit" start={3.3} /></Field></Rise>
            <Rise start={3.2}><Field label="Dates"><TypeText text="Sep 15 – 17, 2026" start={4.5} cps={22} /></Field></Rise>
            <Rise start={5.3} dur={0.4}>
              <div style={{ border: `1px solid ${V.border}`, borderRadius: 6, padding: '11px 12px', display: 'flex', justifyContent: 'space-between', fontSize: 14, fontFamily: V.sans, background: '#fff' }}>
                <span style={{ fontWeight: 500 }}>Full conference</span><span style={{ fontFamily: V.mono, fontSize: 13 }}>$1,295</span>
              </div>
            </Rise>
            <Rise start={5.7} dur={0.4}>
              <div style={{ border: `1px solid ${V.border}`, borderRadius: 6, padding: '11px 12px', display: 'flex', justifyContent: 'space-between', fontSize: 14, fontFamily: V.sans, background: '#fff' }}>
                <span style={{ fontWeight: 500 }}>Day pass</span><span style={{ fontFamily: V.mono, fontSize: 13 }}>$495</span>
              </div>
            </Rise>
            <Rise start={6.0} dur={0.4} style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, alignItems: 'center' }}>
              {published ? (
                <span style={{ background: V.greenSoft, color: V.greenText, fontSize: 13, fontWeight: 600, padding: '9px 16px', borderRadius: 99, fontFamily: V.sans, whiteSpace: 'nowrap' }}>● Registration is live</span>
              ) : (
                <span style={{ background: t >= 7.3 ? V.blueDark : V.blue, color: '#fff', fontSize: 14, fontWeight: 500, padding: '10px 18px', borderRadius: 6, fontFamily: V.sans, whiteSpace: 'nowrap' }}>Publish event</span>
              )}
            </Rise>
          </div>
        </div>
      </Browser>
      <Cursor
        frames={[{ t: 6.2, x: 1010, y: 640 }, { t: 7.2, x: 838, y: 556 }, { t: 8.4, x: 852, y: 570 }]}
        clicks={[7.35]}
      />
    </Sprite>
  );
}

/* ---------- Scene 3 · attendee registers (8.6–14.6) ---------- */

function RegisterScene() {
  const t = useTime();
  const confirmed = t >= 12.65;
  return (
    <Sprite start={8.6} end={14.6}>
      <Browser url="register.gridsummit.org">
        <div style={{ position: 'absolute', left: 280, top: 26, width: 360 }}>
          <Rise start={8.9} dur={0.45}>
            <div style={{ background: '#fff', border: `1px solid ${V.border}`, borderRadius: 10, boxShadow: '0 4px 14px rgba(15,23,42,0.06)', overflow: 'hidden' }}>
              <div style={{ padding: '14px 20px', borderBottom: `1px solid ${V.subtle}`, display: 'flex', justifyContent: 'space-between', alignItems: 'center', whiteSpace: 'nowrap' }}>
                <span style={{ fontFamily: V.disp, fontWeight: 800, fontSize: 13, letterSpacing: '0.06em', color: V.org }}>GRID SUMMIT</span>
                <span style={{ fontSize: 10.5, color: V.faint, fontFamily: V.sans }}>Powered by Regably</span>
              </div>
              {!confirmed ? (
                <div style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 13 }}>
                  <Field label="Full name"><TypeText text="Dana Okafor" start={9.4} /></Field>
                  <Field label="Work email"><TypeText text="dana@northwind.org" start={10.4} cps={22} /></Field>
                  <div style={{ background: t >= 12.4 ? '#175C3A' : V.org, color: '#fff', borderRadius: 6, height: 44, display: 'grid', placeItems: 'center', fontSize: 14.5, fontWeight: 500, fontFamily: V.sans, marginTop: 4, whiteSpace: 'nowrap' }}>
                    Complete registration — $1,295
                  </div>
                  <div style={{ fontSize: 11, color: V.faint, textAlign: 'center', fontFamily: V.sans }}>Secured by Stripe</div>
                </div>
              ) : (
                <div style={{ padding: '26px 20px 24px', textAlign: 'center' }}>
                  <CheckPop start={12.7} />
                  <Rise start={13.0}><div style={{ fontFamily: V.disp, fontSize: 20, fontWeight: 700, color: V.text, marginTop: 12 }}>You're confirmed</div></Rise>
                  <Rise start={13.25}><div style={{ fontSize: 12.5, color: V.sub, marginTop: 5, fontFamily: V.sans, whiteSpace: 'nowrap' }}>Confirmation sent to dana@northwind.org</div></Rise>
                  <Rise start={13.5}>
                    <div style={{ display: 'inline-block', fontFamily: V.mono, fontSize: 14, letterSpacing: '0.05em', border: `1px dashed #CBD5E1`, borderRadius: 6, padding: '7px 14px', marginTop: 13, color: V.text, background: V.bg, whiteSpace: 'nowrap' }}>CONF-7K4M2P</div>
                  </Rise>
                </div>
              )}
            </div>
          </Rise>
        </div>
      </Browser>
      <Cursor
        frames={[{ t: 11.4, x: 980, y: 620 }, { t: 12.3, x: 640, y: 388 }, { t: 13.0, x: 700, y: 430 }]}
        clicks={[12.45]}
      />
    </Sprite>
  );
}

function CheckPop({ start }) {
  const t = useTime();
  const p = Easing.easeOutBack(clamp((t - start) / 0.5, 0, 1));
  return (
    <div style={{ width: 56, height: 56, margin: '0 auto', borderRadius: 99, background: V.greenSoft, display: 'grid', placeItems: 'center', transform: `scale(${p})` }}>
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={V.greenText} strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round">
        <polyline points="20 6 9 17 4 12" style={{ strokeDasharray: 26, strokeDashoffset: 26 * (1 - clamp((t - start - 0.15) / 0.4, 0, 1)) }} />
      </svg>
    </div>
  );
}

/* ---------- Scene 4 · dashboard (14.6–20.8) ---------- */

const ROWS = [
  ['Dana Okafor', 'Full conference', '$1,295'],
  ['Marcus Lee', 'Full conference', '$1,295'],
  ['Priya Nair', 'Day pass', '$495'],
  ['Lena Petrov', 'Sponsor', '$5,000'],
];

function DashScene() {
  return (
    <Sprite start={14.6} end={20.8}>
      <Browser url="app.regably.com/grid-summit/overview">
        <div style={{ position: 'absolute', left: 36, top: 26, right: 36 }}>
          <div style={{ display: 'flex', gap: 14 }}>
            {[
              ['Registrations', <Counter key="r" from={1180} to={1284} start={15.2} end={17.4} />, '86% of capacity'],
              ['Revenue collected', <Counter key="v" from={761480} to={842310} start={15.2} end={17.6} prefix="$" />, '+12% this week'],
              ['Pending', <Counter key="p" from={31} to={18} start={15.2} end={17.0} />, 'auto-reminded'],
            ].map((s, i) => (
              <Rise key={i} start={14.9 + i * 0.15} style={{ flex: 1 }}>
                <div style={{ border: `1px solid ${V.border}`, borderRadius: 10, padding: '14px 18px', background: '#fff', whiteSpace: 'nowrap' }}>
                  <div style={{ fontSize: 12, color: V.sub, fontFamily: V.sans }}>{s[0]}</div>
                  <div style={{ fontFamily: V.disp, fontSize: 28, fontWeight: 700, letterSpacing: '-0.02em', color: V.text, margin: '4px 0 2px', fontVariantNumeric: 'tabular-nums' }}>{s[1]}</div>
                  <div style={{ fontSize: 11.5, color: V.greenText, fontWeight: 600, fontFamily: V.sans }}>{s[2]}</div>
                </div>
              </Rise>
            ))}
          </div>
          <Rise start={15.6} style={{ marginTop: 16 }}>
            <div style={{ border: `1px solid ${V.border}`, borderRadius: 10, overflow: 'hidden', background: '#fff' }}>
              <div style={{ padding: '10px 16px', fontSize: 12, color: V.sub, background: V.bg, borderBottom: `1px solid ${V.border}`, fontFamily: V.sans, display: 'flex', whiteSpace: 'nowrap' }}>
                <span style={{ flex: 2 }}>Attendee</span><span style={{ flex: 2 }}>Tier</span><span style={{ flex: 1 }}>Status</span><span style={{ width: 70, textAlign: 'right' }}>Amount</span>
              </div>
              {ROWS.map((r, i) => (
                <Rise key={r[0]} start={16.0 + i * 0.35} dy={10}>
                  <div style={{ padding: '11px 16px', display: 'flex', alignItems: 'center', fontSize: 13.5, fontFamily: V.sans, borderBottom: i < 3 ? `1px solid ${V.subtle}` : 'none', whiteSpace: 'nowrap' }}>
                    <span style={{ flex: 2, fontWeight: 500, color: V.text }}>{r[0]}</span>
                    <span style={{ flex: 2, color: V.sub }}>{r[1]}</span>
                    <span style={{ flex: 1 }}><span style={{ background: V.greenSoft, color: V.greenText, fontSize: 11.5, fontWeight: 600, padding: '3px 10px', borderRadius: 99 }}>● Confirmed</span></span>
                    <span style={{ width: 70, textAlign: 'right', fontFamily: V.mono, fontSize: 12.5, color: V.text }}>{r[2]}</span>
                  </div>
                </Rise>
              ))}
            </div>
          </Rise>
        </div>
      </Browser>
    </Sprite>
  );
}

/* ---------- Scene 5 · speakers & sponsors (20.8–26.8) ---------- */

const SPEAKERS = [
  ['AV', 'Dr. Alina Voss', 'CTO, Meridian Grid', 'Keynote'],
  ['JM', 'James Maldonado', 'Chair, Western Energy Board', 'Panel'],
  ['KO', 'Kemi Olatunji', 'VP Storage, Borealis Power', 'Workshop'],
];
const SPONSORS = [['PLATINUM', 'Helios Energy'], ['GOLD', 'Atlas Group'], ['GOLD', 'Cedar Labs']];

function SpeakersScene() {
  return (
    <Sprite start={20.8} end={26.8}>
      <Browser url="app.regably.com/grid-summit/speakers">
        <div style={{ position: 'absolute', left: 60, top: 30, right: 60 }}>
          <Rise start={21.1}>
            <div style={{ fontFamily: V.disp, fontSize: 21, fontWeight: 700, color: V.text, whiteSpace: 'nowrap' }}>Speakers <span style={{ fontFamily: V.sans, fontSize: 12, fontWeight: 600, color: V.blue, background: '#EFF4FE', borderRadius: 99, padding: '3px 10px', verticalAlign: 'middle', marginLeft: 6 }}>82 confirmed</span></div>
          </Rise>
          <div style={{ display: 'flex', gap: 14, marginTop: 16 }}>
            {SPEAKERS.map((s, i) => (
              <Rise key={s[0]} start={21.5 + i * 0.3} style={{ flex: 1 }}>
                <div style={{ border: `1px solid ${V.border}`, borderRadius: 10, padding: '18px 16px', background: '#fff', textAlign: 'center', whiteSpace: 'nowrap' }}>
                  <div style={{ width: 48, height: 48, borderRadius: 99, background: '#EFF4FE', color: V.blueDark, display: 'grid', placeItems: 'center', fontWeight: 700, fontSize: 16, margin: '0 auto 10px', fontFamily: V.sans }}>{s[0]}</div>
                  <div style={{ fontSize: 14, fontWeight: 600, color: V.text, fontFamily: V.sans }}>{s[1]}</div>
                  <div style={{ fontSize: 11.5, color: V.sub, marginTop: 2, fontFamily: V.sans }}>{s[2]}</div>
                  <div style={{ display: 'inline-block', fontSize: 10.5, fontWeight: 600, color: V.greenText, background: V.greenSoft, borderRadius: 99, padding: '2px 9px', marginTop: 8, fontFamily: V.sans }}>{s[3]}</div>
                </div>
              </Rise>
            ))}
          </div>
          <Rise start={23.4}>
            <div style={{ fontFamily: V.disp, fontSize: 17, fontWeight: 700, color: V.text, margin: '22px 0 10px' }}>Sponsors</div>
          </Rise>
          <div style={{ display: 'flex', gap: 12 }}>
            {SPONSORS.map((s, i) => (
              <Rise key={s[1]} start={23.8 + i * 0.3} style={{ flex: 1 }}>
                <div style={{ border: `1px solid ${V.border}`, borderRadius: 8, padding: '12px 14px', background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'space-between', whiteSpace: 'nowrap' }}>
                  <span style={{ fontSize: 13.5, fontWeight: 600, color: V.text, fontFamily: V.sans }}>{s[1]}</span>
                  <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.06em', color: s[0] === 'PLATINUM' ? V.blueDark : V.amber, fontFamily: V.sans }}>{s[0]}</span>
                </div>
              </Rise>
            ))}
          </div>
        </div>
      </Browser>
    </Sprite>
  );
}

/* ---------- Scene 6 · reminders + discount (26.8–32.6) ---------- */

function RemindScene() {
  const t = useTime();
  const sent = t >= 30.85;
  return (
    <Sprite start={26.8} end={32.6}>
      <Browser url="app.regably.com/grid-summit/emails/reminders">
        <div style={{ position: 'absolute', left: 250, top: 34, width: 420 }}>
          <Rise start={27.1}>
            <div style={{ fontFamily: V.disp, fontSize: 20, fontWeight: 700, color: V.text, whiteSpace: 'nowrap' }}>Incomplete registrations <span style={{ fontFamily: V.sans, fontSize: 12, fontWeight: 600, color: V.amber, background: V.amberSoft, borderRadius: 99, padding: '3px 10px', verticalAlign: 'middle', marginLeft: 6 }}>18 saved carts</span></div>
          </Rise>
          <Rise start={27.6}>
            <div style={{ border: `1px solid ${V.border}`, borderRadius: 10, background: '#fff', marginTop: 14, overflow: 'hidden' }}>
              <div style={{ padding: '12px 18px', borderBottom: `1px solid ${V.subtle}`, fontSize: 12.5, color: V.sub, fontFamily: V.sans, whiteSpace: 'nowrap' }}>Subject · <span style={{ color: V.text, fontWeight: 600 }}>Finish your Grid Summit registration</span></div>
              <div style={{ padding: '16px 18px' }}>
                <div style={{ fontSize: 13.5, color: V.sub, fontFamily: V.sans, lineHeight: 1.55, whiteSpace: 'nowrap' }}>Your saved registration expires Friday.</div>
                <Rise start={28.6}>
                  <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, border: `1px dashed ${V.amber}`, background: V.amberSoft, borderRadius: 6, padding: '7px 12px', marginTop: 12, whiteSpace: 'nowrap' }}>
                    <span style={{ fontFamily: V.mono, fontSize: 12.5, fontWeight: 500, color: V.amber }}>EARLYBIRD</span>
                    <span style={{ fontSize: 11.5, color: V.sub, fontFamily: V.sans }}>saves 20% through June 30</span>
                  </div>
                </Rise>
              </div>
              <div style={{ padding: '12px 18px', borderTop: `1px solid ${V.subtle}`, display: 'flex', justifyContent: 'flex-end', background: V.bg }}>
                {sent ? (
                  <span style={{ background: V.greenSoft, color: V.greenText, fontSize: 13, fontWeight: 600, padding: '9px 16px', borderRadius: 99, fontFamily: V.sans, whiteSpace: 'nowrap' }}>● 18 reminders sent</span>
                ) : (
                  <span style={{ background: t >= 30.7 ? V.blueDark : V.blue, color: '#fff', fontSize: 13.5, fontWeight: 500, padding: '9px 16px', borderRadius: 6, fontFamily: V.sans, whiteSpace: 'nowrap' }}>Send 18 reminders</span>
                )}
              </div>
            </div>
          </Rise>
        </div>
      </Browser>
      <Cursor
        frames={[{ t: 29.6, x: 1000, y: 620 }, { t: 30.6, x: 800, y: 470 }, { t: 31.6, x: 818, y: 486 }]}
        clicks={[30.75]}
      />
    </Sprite>
  );
}

/* ---------- Scene 7 · badges (32.6–38.6) ---------- */

const BADGES = [
  ['Marcus Lee', 'Helios Energy', 'ATTENDEE', V.sub, -5],
  ['Dana Okafor', 'Northwind Assoc.', 'SPEAKER', V.blueDark, 0],
  ['Lena Petrov', 'Borealis Co.', 'SPONSOR', V.amber, 5],
];

function BadgeCard({ name, org, role, roleColor, rot, big }) {
  return (
    <div style={{ width: big ? 220 : 196, background: '#fff', border: `1px solid ${V.border}`, borderRadius: 12, boxShadow: '0 14px 30px -8px rgba(15,23,42,0.18)', padding: '14px 18px 18px', textAlign: 'center', transform: `rotate(${rot}deg)`, whiteSpace: 'nowrap' }}>
      <div style={{ width: 34, height: 7, borderRadius: 99, background: V.subtle, border: `1px solid ${V.border}`, margin: '0 auto 14px' }}></div>
      <div style={{ fontFamily: V.badge, fontWeight: 700, fontSize: big ? 27 : 23, textTransform: 'uppercase', letterSpacing: '0.01em', color: V.text, lineHeight: 1.05 }}>{name}</div>
      <div style={{ fontFamily: V.sans, fontSize: 11.5, color: V.sub, marginTop: 4 }}>{org}</div>
      <div style={{ fontFamily: V.badge, fontWeight: 600, fontSize: 13, letterSpacing: '0.14em', color: roleColor, marginTop: 10 }}>{role}</div>
    </div>
  );
}

function BadgesScene() {
  return (
    <Sprite start={32.6} end={38.6}>
      <Browser url="app.regably.com/grid-summit/badges">
        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 26 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
            {BADGES.map((b, i) => (
              <Rise key={b[0]} start={33.1 + i * 0.35} dur={0.55} dy={22}>
                <BadgeCard name={b[0]} org={b[1]} role={b[2]} roleColor={b[3]} rot={b[4]} big={i === 1} />
              </Rise>
            ))}
          </div>
          <Rise start={34.8}>
            <div style={{ fontSize: 14, color: V.sub, fontFamily: V.sans, whiteSpace: 'nowrap' }}><b style={{ color: V.text, fontVariantNumeric: 'tabular-nums' }}>1,284</b> badges ready · print-ready PDF, generated from the roster</div>
          </Rise>
        </div>
      </Browser>
    </Sprite>
  );
}

/* ---------- Scene 8 · end card (38.6–42.5) ---------- */

function EndScene() {
  const t = useTime();
  const inP = animate({ from: 0, to: 1, start: 38.6, end: 39.2 })(t);
  return (
    <Sprite start={38.6} end={42.5}>
      <div style={{ position: 'absolute', inset: 0, background: V.ink, opacity: inP, display: 'grid', placeItems: 'center' }}>
        <div style={{ textAlign: 'center' }}>
          <Rise start={39.1} dur={0.6}><img src="../../assets/wordmark-inverse.svg" style={{ height: 46 }} alt="Regably" /></Rise>
          <Rise start={39.6} dur={0.6}>
            <div style={{ fontFamily: V.disp, fontSize: 26, fontWeight: 600, letterSpacing: '-0.02em', color: '#CBD5E1', marginTop: 20, whiteSpace: 'nowrap' }}>Dependable registration.</div>
          </Rise>
          <Rise start={40.2} dur={0.6}>
            <div style={{ fontFamily: V.mono, fontSize: 14, color: '#64748B', marginTop: 14 }}>regably.com</div>
          </Rise>
        </div>
      </div>
    </Sprite>
  );
}

/* ---------- root ---------- */

/* Lets the host page drive the player: dispatch
   `new CustomEvent('rgb-video-control', { detail: { t: 8.6, play: true } })`
   on window to seek/play. Current time is mirrored to window.__rgbVideoTime. */
function SeekBridge() {
  const { setTime, setPlaying } = window.useTimeline();
  const t = useTime();
  React.useEffect(() => { window.__rgbVideoTime = t; });
  React.useEffect(() => {
    const h = (e) => {
      const d = e.detail || {};
      if (typeof d.t === 'number') setTime(clamp(d.t, 0, 42.5));
      if (typeof d.play === 'boolean') setPlaying(d.play);
    };
    window.addEventListener('rgb-video-control', h);
    return () => window.removeEventListener('rgb-video-control', h);
  }, [setTime, setPlaying]);
  return null;
}

function TimestampLabel({ children }) {
  const t = useTime();
  return <div data-screen-label={`Demo video · t=${Math.floor(t)}s`} style={{ position: 'absolute', inset: 0 }}>{children}</div>;
}

/* Timeline-synced audio: plays/pauses with the Stage, follows seeks, and
   handles browser autoplay blocking (first click enables sound). */
function AudioTrack({ src }) {
  const { time, playing } = window.useTimeline();
  const ref = React.useRef(null);
  const [blocked, setBlocked] = React.useState(false);
  const [muted, setMuted] = React.useState(false);

  React.useEffect(() => {
    const a = ref.current; if (!a) return;
    if (playing && !muted) {
      const p = a.play();
      if (p && p.catch) p.then(() => setBlocked(false)).catch(() => setBlocked(true));
    } else {
      a.pause();
    }
  }, [playing, muted]);

  React.useEffect(() => {
    const a = ref.current; if (!a) return;
    const dur = a.duration;
    const target = isFinite(dur) ? Math.min(time, dur) : time;
    if (Math.abs(a.currentTime - target) > 0.35) {
      try { a.currentTime = target; } catch (e) {}
    }
  }, [time]);

  React.useEffect(() => {
    if (!blocked) return;
    const h = () => {
      setBlocked(false);
      const a = ref.current;
      if (a && playing && !muted) a.play().catch(() => {});
    };
    window.addEventListener('pointerdown', h, { once: true });
    return () => window.removeEventListener('pointerdown', h);
  }, [blocked, playing, muted]);

  const label = blocked ? 'Click for sound' : muted ? 'Sound off' : 'Sound on';
  return (
    <React.Fragment>
      <video ref={ref} src={src} preload="auto" playsInline style={{ display: 'none' }} />
      <button
        onClick={() => setMuted((m) => !m)}
        title={label}
        style={{
          position: 'absolute', top: 14, right: 14, zIndex: 90,
          display: 'flex', alignItems: 'center', gap: 7,
          background: 'rgba(15,23,42,0.72)', color: '#F8FAFC',
          border: 'none', borderRadius: 99, padding: '7px 13px',
          fontFamily: V.sans, fontSize: 12, fontWeight: 500,
          cursor: 'pointer', whiteSpace: 'nowrap', opacity: 0.9,
        }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M11 5 6 9H2v6h4l5 4V5z" fill="currentColor" stroke="none" />
          {(muted || blocked)
            ? <g><line x1="16" y1="9" x2="22" y2="15" /><line x1="22" y1="9" x2="16" y2="15" /></g>
            : <g><path d="M15.5 8.5a5 5 0 0 1 0 7" /><path d="M18.5 5.5a9 9 0 0 1 0 13" /></g>}
        </svg>
        {label}
      </button>
    </React.Fragment>
  );
}

function DemoVideo({ controls = true }) {
  return (
    <Stage width={1280} height={720} duration={42.5} background={V.bg} persistKey="rgb-demo-video" controls={controls}>
      <TimestampLabel>
        <SeekBridge />
        <TitleScene />
        <Camera>
          <SetupScene />
          <RegisterScene />
          <DashScene />
          <SpeakersScene />
          <RemindScene />
          <BadgesScene />
        </Camera>
        <EndScene />
      </TimestampLabel>
    </Stage>
  );
}

window.DemoVideo = DemoVideo;
