// Froid&Air animated product video — 60s story in 7 scenes

const { useState, useEffect, useMemo } = React;

// ============ Palette ============
const C = {
  bg:      '#fbfbfa',
  bg2:     '#f5f4f1',
  bg3:     '#efeeea',
  ink:     '#15150f',
  ink2:    '#33332a',
  muted:   '#6b6b60',
  muted2:  '#9a9a8e',
  line:    '#e7e5df',
  line2:   '#d9d7cf',
  hair:    '#f0efe9',
  accent:  '#0e8f84',
  accentInk: '#0a564f',
  accentSoft: '#def4f1',
  accentSoft2: '#c9ede9',
  cite:    '#fff3c7',
  citeInk: '#6b4e00',
  citeEdge:'#ecd585',
  ok:      '#197a4e',
  surface: '#ffffff',
};
const F = {
  sans: '"Inter Tight", -apple-system, sans-serif',
  serif: '"Instrument Serif", serif',
  mono: '"JetBrains Mono", monospace',
};

// ============ Little primitives ============
const Icon = ({ name, size = 16, color = 'currentColor', stroke = 1.75 }) => {
  const p = {
    search: <><circle cx="11" cy="11" r="7"/><path d="m21 21-4.35-4.35"/></>,
    sparkles: <><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.64 5.64l2.83 2.83M15.54 15.54l2.83 2.83M5.64 18.36l2.83-2.83M15.54 8.46l2.83-2.83"/></>,
    doc: <><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></>,
    book: <><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></>,
    shield: <path d="M12 2 4 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5z"/>,
    clock: <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>,
    bolt: <path d="M13 2 3 14h9l-1 8 10-12h-9z"/>,
    check: <path d="m5 12 5 5L20 7"/>,
    arrow: <path d="M5 12h14m0 0-6-6m6 6-6 6"/>,
    mic: <><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2M12 19v3"/></>,
    folder: <path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>,
  }[name];
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round">{p}</svg>;
};

// ============ Scene 1 — Problem (0–9s) ============
// A technician overwhelmed by PDFs
function ScenePaperChaos() {
  const { localTime, duration, progress } = useSprite();
  const papers = [
    { x: 180, y: 120, rot: -8, title: "Manuel MSZ-AP50VG", ref: "MSZ-AP_IM · 56 p.", color: "#fff" },
    { x: 520, y: 90,  rot: 4,  title: "Fiche PUHZ-ZRP250", ref: "2025 · 12 p.", color: "#fff" },
    { x: 900, y: 140, rot: -3, title: "NF EN 378-2", ref: "Norme · 84 p.", color: "#fff" },
    { x: 1320, y: 110, rot: 7, title: "Directive F-Gas 517/2014", ref: "Régl. · 142 p.", color: "#fff" },
    { x: 280, y: 480, rot: 6, title: "SAV-PR-014", ref: "Procédure", color: "#fff" },
    { x: 680, y: 500, rot: -5, title: "Codes erreur série MSZ", ref: "Interne", color: "#fff" },
    { x: 1080, y: 470, rot: 3, title: "NF EN 14511", ref: "Norme", color: "#fff" },
    { x: 1440, y: 500, rot: -8, title: "Manuel MSZ-LN", ref: "rev. D", color: "#fff" },
    { x: 120, y: 780, rot: -4, title: "Fiche produit MSZ-HR", ref: "2024", color: "#fff" },
    { x: 560, y: 820, rot: 5, title: "Bulletin technique BT-219", ref: "avril 2025", color: "#fff" },
    { x: 980, y: 800, rot: -7, title: "Norme acoustique", ref: "EN 12102", color: "#fff" },
    { x: 1400, y: 830, rot: 4, title: "Procédure purge R-32", ref: "SAV", color: "#fff" },
  ];

  // Papers spread from center outward during entry
  const spread = Easing.easeOutCubic(clamp(localTime / 1.2, 0, 1));
  // Title appears at 1.5s
  const titleT = clamp((localTime - 1.2) / 0.7, 0, 1);
  // Question appears at 4s
  const qT = clamp((localTime - 3.2) / 0.6, 0, 1);
  // Frustration animation - papers gently wobble
  const wobble = Math.sin(localTime * 2) * 2;

  return (
    <div style={{position:'absolute', inset:0, background:C.bg2, overflow:'hidden'}}>
      {/* subtle grid */}
      <svg style={{position:'absolute', inset:0, opacity:0.35}} width="1920" height="1080">
        <defs>
          <pattern id="grid1" width="48" height="48" patternUnits="userSpaceOnUse">
            <path d="M 48 0 L 0 0 0 48" fill="none" stroke={C.line} strokeWidth="1"/>
          </pattern>
        </defs>
        <rect width="1920" height="1080" fill="url(#grid1)"/>
      </svg>

      {papers.map((p, i) => {
        const cx = 960, cy = 540;
        const x = cx + (p.x - cx) * spread;
        const y = cy + (p.y - cy) * spread;
        const exitT = clamp((localTime - 6.0) / 1.5, 0, 1);
        const exitY = Easing.easeInCubic(exitT) * 1200;
        const exitOp = 1 - exitT;
        return (
          <div key={i} style={{
            position:'absolute',
            left: x, top: y + exitY,
            width: 260, height: 180,
            background: p.color,
            border: '1px solid '+C.line,
            borderRadius: 6,
            boxShadow: '0 8px 30px rgba(20,20,10,0.12), 0 2px 4px rgba(20,20,10,0.06)',
            transform: `rotate(${p.rot + wobble*0.3}deg)`,
            padding: '20px 22px',
            opacity: exitOp * spread,
            transition: 'opacity 200ms',
          }}>
            <div style={{
              width:38, height:46, borderRadius:3,
              background: 'linear-gradient(180deg, #fbe6e1, #f5cfc4)',
              color: '#a6301f', fontFamily: F.mono, fontSize: 9, fontWeight: 700,
              display:'grid', placeItems:'center', marginBottom: 12,
            }}>PDF</div>
            <div style={{fontSize: 13, fontWeight: 600, color: C.ink, marginBottom: 4, letterSpacing:'-0.005em'}}>
              {p.title}
            </div>
            <div style={{fontSize: 11, color: C.muted, fontFamily: F.mono}}>{p.ref}</div>
            <div style={{position:'absolute', right: 14, top: 14, fontSize: 10, color: C.muted2, fontFamily: F.mono}}>p. {(i%40)+1}</div>
          </div>
        );
      })}

      {/* Title overlay */}
      <div style={{
        position:'absolute',
        left:'50%', top: '38%',
        transform: `translate(-50%, ${-(1-Easing.easeOutCubic(titleT))*20}px)`,
        textAlign:'center',
        opacity: titleT * (1 - Easing.easeInCubic(clamp((localTime-6.8)/1.5, 0, 1))),
        pointerEvents: 'none',
      }}>
        <div style={{
          display:'inline-block',
          padding: '16px 36px',
          background: C.ink, color: '#fbfbfa',
          borderRadius: 12,
          fontFamily: F.serif,
          fontSize: 84,
          fontWeight: 400,
          letterSpacing: '-0.02em',
          lineHeight: 1,
          boxShadow: '0 30px 80px rgba(0,0,0,0.3)',
        }}>
          4 821 documents.
        </div>
      </div>

      {/* Question */}
      <div style={{
        position:'absolute',
        left:'50%', top: '58%',
        transform: `translate(-50%, ${-(1-Easing.easeOutCubic(qT))*16}px)`,
        textAlign:'center',
        opacity: qT * (1 - Easing.easeInCubic(clamp((localTime-6.8)/1.5, 0, 1))),
        fontFamily: F.serif,
        fontSize: 54,
        fontStyle: 'italic',
        color: C.ink2,
        letterSpacing: '-0.01em',
      }}>
        Où est la bonne réponse ?
      </div>
    </div>
  );
}

// ============ Scene 2 — Solution reveal: search bar (9–15s) ============
function SceneSearchReveal() {
  const { localTime } = useSprite();
  const fullQ = "charge R-32 pour MSZ-AP50VG avec liaison 22 m ?";
  // typing starts at 1s, 35 cps
  const typeT = clamp((localTime - 0.8) * 22, 0, fullQ.length);
  const typed = fullQ.slice(0, Math.floor(typeT));
  const showCursor = Math.floor(localTime * 2) % 2 === 0;

  // bar fades in immediately
  const barT = Easing.easeOutCubic(clamp(localTime / 0.7, 0, 1));
  // label fades before bar
  const labelT = clamp((localTime) / 0.4, 0, 1);
  // exit
  const exitT = clamp((localTime - 5.0) / 1.0, 0, 1);
  const exitOp = 1 - exitT;

  return (
    <div style={{position:'absolute', inset:0, background:C.bg, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap: 40, opacity: exitOp}}>
      <div style={{
        opacity: labelT,
        transform: `translateY(${(1-labelT)*10}px)`,
        fontFamily: F.mono, fontSize: 14, color: C.muted,
        textTransform: 'uppercase', letterSpacing: '0.12em',
        display:'flex', alignItems:'center', gap: 10,
      }}>
        <span style={{width:8, height:8, borderRadius:'50%', background:C.accent, boxShadow:`0 0 0 6px ${C.accentSoft}`}}/>
        Base technique Froid&Air · prête en 1,8 s
      </div>

      <div style={{
        width: 1100,
        background: C.surface,
        border: '1.5px solid '+C.ink,
        borderRadius: 16,
        padding: 10,
        boxShadow: '0 40px 100px rgba(20,20,10,0.15), 0 0 0 10px rgba(14,143,132,0.06)',
        opacity: barT,
        transform: `scale(${0.95 + barT*0.05})`,
      }}>
        <div style={{display:'flex', alignItems:'center', gap: 16, padding: '22px 24px'}}>
          <Icon name="search" size={26} color={C.muted}/>
          <div style={{
            flex: 1, fontFamily: F.sans, fontSize: 32, letterSpacing:'-0.01em',
            color: C.ink, minHeight: 40,
          }}>
            {typed}
            {showCursor && typeT < fullQ.length && <span style={{
              display:'inline-block', width: 3, height: 34, background: C.accent,
              verticalAlign: '-6px', marginLeft: 2,
            }}/>}
          </div>
          <div style={{
            display:'inline-flex', alignItems:'center', gap: 8,
            padding: '8px 14px', borderRadius: 999,
            background: C.bg2, color: C.ink2,
            fontSize: 15, border: '1px solid '+C.line,
          }}>
            <Icon name="folder" size={14} color={C.muted}/>
            Tous les documents
          </div>
        </div>
        <div style={{
          borderTop: '1px solid '+C.hair,
          padding: '10px 14px',
          display: 'flex', gap: 8, alignItems: 'center',
        }}>
          <div style={{display:'inline-flex', alignItems:'center', gap: 7, padding:'8px 14px', background:C.accentSoft, color:C.accentInk, borderRadius: 8, fontSize: 14, fontWeight: 500}}>
            <Icon name="sparkles" size={15}/> IA
          </div>
          <div style={{color: C.muted, fontSize: 14, padding:'8px 12px'}}>Filtres</div>
          <div style={{color: C.muted, fontSize: 14, padding:'8px 12px'}}>Source précise</div>
          <div style={{flex:1}}/>
          <div style={{
            background: C.ink, color: '#fbfbfa',
            padding: '10px 20px', borderRadius: 8,
            fontSize: 14, fontWeight: 500,
            display:'inline-flex', alignItems:'center', gap: 8,
          }}>
            Rechercher <Icon name="arrow" size={14}/>
          </div>
        </div>
      </div>

      {/* suggestions row */}
      <div style={{display:'flex', gap:10, opacity: barT * (typeT < 3 ? 1 : 1 - clamp((typeT-3)/8, 0, 1))}}>
        {["Procédure tirage au vide R-32", "Norme F-Gas >3 kg", "Code erreur E6 MSZ-HR35"].map((s, i) => (
          <div key={i} style={{
            padding: '10px 16px',
            background: C.surface, border: '1px solid '+C.line,
            borderRadius: 999, fontSize: 13, color: C.ink2,
          }}>{s}</div>
        ))}
      </div>
    </div>
  );
}

// ============ Scene 3 — Retrieval animation (15–23s) ============
function SceneRetrieval() {
  const { localTime } = useSprite();

  // query at top
  const qT = Easing.easeOutCubic(clamp(localTime / 0.5, 0, 1));

  // docs enter in cascade
  const docs = [
    { title: "Manuel MSZ-AP50VG",   ref: "p. 24",     score: 94, color: C.accent },
    { title: "Fiche produit MSZ-AP",   ref: "§3.2",      score: 88, color: C.accent },
    { title: "Norme NF EN 378-2",    ref: "Art. 6.2",  score: 76, color: C.muted },
    { title: "Procédure SAV-PR-014", ref: "§4",        score: 71, color: C.muted },
    { title: "BT-219 · liaisons",    ref: "p. 3",      score: 58, color: C.muted },
    { title: "Manuel MSZ-HR35",      ref: "p. 41",     score: 42, color: C.muted },
  ];

  // "scanning" progress bar
  const scanT = clamp((localTime - 0.4) / 2.0, 0, 1);

  return (
    <div style={{position:'absolute', inset:0, background:C.bg, padding: 60, display:'flex', flexDirection:'column', gap: 28}}>
      {/* Query chip */}
      <div style={{
        opacity: qT,
        display:'flex', alignItems:'center', gap: 14,
        padding: '16px 22px',
        background: C.surface, border: '1px solid '+C.line2,
        borderRadius: 12,
        maxWidth: 900,
        boxShadow: '0 4px 16px rgba(20,20,10,0.04)',
      }}>
        <div style={{width: 36, height: 36, borderRadius: 10, background: C.ink, color: '#fbfbfa', display:'grid', placeItems:'center'}}>
          <Icon name="search" size={16}/>
        </div>
        <div style={{fontFamily: F.serif, fontSize: 24, letterSpacing:'-0.01em'}}>
          charge R-32 pour MSZ-AP50VG avec liaison 22 m ?
        </div>
      </div>

      {/* Scanning indicator */}
      <div style={{
        opacity: qT,
        display:'flex', alignItems:'center', gap: 14,
        fontSize: 14, color: C.muted, fontFamily: F.mono,
      }}>
        <div style={{
          width:10, height:10, borderRadius:'50%',
          background: C.accent, boxShadow:`0 0 0 6px ${C.accentSoft}`,
          animation: 'pulse 1s infinite',
        }}/>
        Lecture sémantique de 4 821 documents…
        <div style={{flex:1, height: 3, background: C.bg3, borderRadius: 2, overflow:'hidden', maxWidth: 400}}>
          <div style={{width: (scanT*100)+'%', height:'100%', background: C.accent, transition:'width 60ms'}}/>
        </div>
        <span style={{color: C.ink2}}>{Math.floor(scanT * 4821).toLocaleString('fr-FR')}</span>
      </div>

      {/* Doc scan cards */}
      <div style={{display:'grid', gridTemplateColumns:'repeat(6, 1fr)', gap: 14, marginTop: 8}}>
        {docs.map((d, i) => {
          const enterAt = 0.8 + i * 0.15;
          const eT = Easing.easeOutBack(clamp((localTime - enterAt) / 0.5, 0, 1));
          const selected = d.score >= 71;
          const selectAt = 3.5 + i * 0.1;
          const selT = clamp((localTime - selectAt) / 0.5, 0, 1);

          // relevant docs float up and glow; irrelevant fade
          const lift = selected ? -selT * 20 : 0;
          const opacity = selected ? 1 : 1 - selT * 0.55;

          return (
            <div key={i} style={{
              background: C.surface,
              border: '1.5px solid ' + (selected && selT > 0.3 ? C.accent : C.line),
              borderRadius: 12,
              padding: 16,
              opacity: eT * opacity,
              transform: `translateY(${(1-eT)*30 + lift}px) scale(${eT})`,
              boxShadow: selected && selT > 0.3 ? `0 10px 30px rgba(14,143,132,0.2), 0 0 0 4px ${C.accentSoft}` : '0 2px 4px rgba(20,20,10,0.03)',
              transition: 'all 200ms',
            }}>
              <div style={{
                width: 30, height: 38, borderRadius: 3,
                background: 'linear-gradient(180deg, #fbe6e1, #f5cfc4)',
                color: '#a6301f', fontFamily: F.mono, fontSize: 8, fontWeight:700,
                display:'grid', placeItems:'center', marginBottom: 12,
              }}>PDF</div>
              <div style={{fontSize: 12, fontWeight:600, color: C.ink, marginBottom: 3, letterSpacing:'-0.005em', minHeight: 32}}>
                {d.title}
              </div>
              <div style={{fontSize: 11, color: C.muted, fontFamily: F.mono, marginBottom: 10}}>{d.ref}</div>
              <div style={{display:'flex', alignItems:'center', gap: 6}}>
                <div style={{flex:1, height: 3, background: C.bg3, borderRadius:2, overflow:'hidden'}}>
                  <div style={{width: (Math.min(scanT*1.3, 1) * d.score)+'%', height:'100%', background: selected ? C.accent : C.muted2}}/>
                </div>
                <span style={{fontSize: 10, fontFamily: F.mono, color: selected ? C.accent : C.muted, fontVariantNumeric:'tabular-nums', width: 28, textAlign:'right'}}>
                  {Math.round(Math.min(scanT*1.3, 1) * d.score)}%
                </span>
              </div>
            </div>
          );
        })}
      </div>

      {/* Bottom caption */}
      <div style={{
        position:'absolute', bottom: 60, left: 60,
        opacity: clamp((localTime - 5.5) / 0.5, 0, 1),
        fontFamily: F.serif, fontSize: 44, letterSpacing:'-0.01em',
      }}>
        4 passages trouvés. <span style={{color: C.accent, fontStyle:'italic'}}>Synthèse en cours…</span>
      </div>
    </div>
  );
}

// ============ Scene 4 — Answer with citations (23–35s) ============
function SceneAnswer() {
  const { localTime } = useSprite();

  // answer chunks appear sequentially
  const chunks = [
    { at: 0.3, w: 0.6 }, // opening
    { at: 1.0, w: 0.6 }, // spec callout
    { at: 2.2, w: 0.6 }, // calc step 1
    { at: 3.0, w: 0.6 }, // calc step 2
    { at: 3.8, w: 0.6 }, // calc step 3
    { at: 4.8, w: 0.5 }, // final answer highlight
  ];
  const op = (at) => Easing.easeOutCubic(clamp((localTime - at) / 0.5, 0, 1));

  // pulse the final answer number
  const pulse = localTime > 5.0 ? 1 + Math.sin((localTime - 5.0) * 6) * 0.03 : 1;

  return (
    <div style={{position:'absolute', inset:0, background:C.bg, padding: '50px 80px', display:'flex', gap: 50}}>
      {/* Left: answer */}
      <div style={{flex: 1.3, display:'flex', flexDirection:'column'}}>
        <div style={{
          display:'flex', alignItems:'center', gap: 10,
          fontFamily: F.mono, fontSize: 13, color: C.muted,
          textTransform:'uppercase', letterSpacing:'0.1em',
          opacity: op(0),
        }}>
          <span style={{width:24, height:24, borderRadius:6, background:`linear-gradient(135deg, ${C.accent}, #7ac9c2)`, display:'grid', placeItems:'center', color:'white'}}>
            <Icon name="sparkles" size={13}/>
          </span>
          Réponse IA · 1,64 s
        </div>

        <div style={{
          fontFamily: F.serif, fontSize: 36, letterSpacing:'-0.01em',
          lineHeight: 1.25, color: C.ink, marginTop: 18,
          opacity: op(0),
          transform: `translateY(${(1-op(0))*10}px)`,
        }}>
          Charge R-32 pour MSZ-AP50VG<br/>avec liaison 22 m ?
        </div>

        <div style={{
          marginTop: 30, fontSize: 19, lineHeight: 1.65, color: C.ink2,
          fontFamily: F.sans, maxWidth: 680,
        }}>
          <div style={{opacity: op(chunks[0].at), transform:`translateY(${(1-op(chunks[0].at))*8}px)`}}>
            La charge usine est <strong style={{color:C.ink}}>1,15 kg</strong> pour une liaison ≤ 15 m<span className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`}}>1</span>.
            Au-delà, ajouter <strong style={{color:C.ink}}>20 g/m</strong><span className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`}}>1</span>.
          </div>

          {/* Step-by-step */}
          <div style={{marginTop: 28, background: C.surface, border: '1px solid '+C.line, borderRadius: 12, overflow:'hidden'}}>
            {[
              { n: 1, body: <>Charge usine : <strong>1,15 kg</strong></>, src: '[1]', at: chunks[2].at },
              { n: 2, body: <>Supplément : <code style={{fontFamily:F.mono, background:C.bg2, padding:'1px 6px', borderRadius:4, fontSize:16}}>(22 − 15) × 20 g = 140 g</code></>, src: '[1]', at: chunks[3].at },
              { n: 3, body: <>Total à introduire : <strong style={{color:C.accent}}>1,29 kg</strong> de R-32</>, src: '[2]', at: chunks[4].at },
            ].map((s, i) => (
              <div key={i} style={{
                display:'grid', gridTemplateColumns:'56px 1fr auto',
                padding:'16px 20px',
                borderBottom: i < 2 ? '1px solid '+C.hair : 'none',
                opacity: op(s.at),
                transform: `translateX(${(1-op(s.at))*-12}px)`,
                alignItems:'center',
              }}>
                <div style={{width:32, height:32, borderRadius:8, background:C.accentSoft, color:C.accentInk, fontFamily:F.mono, fontSize:14, fontWeight:600, display:'grid', placeItems:'center'}}>{s.n}</div>
                <div style={{fontSize:16, color:C.ink2}}>{s.body}</div>
                <div className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`}}>{s.src.slice(1, -1)}</div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Right: spec callout + source cards */}
      <div style={{flex: 1, display:'flex', flexDirection:'column', gap: 14}}>
        {/* Callout */}
        <div style={{
          opacity: op(chunks[1].at),
          transform: `translateY(${(1-op(chunks[1].at))*12}px)`,
          background: C.surface, border:'1px solid '+C.line, borderRadius: 12,
          padding: '4px 0',
          display:'grid', gridTemplateColumns:'1fr 1fr', marginTop: 52,
        }}>
          {[
            { label:'HP', val:'4,15', u:'MPa' },
            { label:'BP', val:'1,64', u:'MPa' },
            { label:'Charge usine', val:'1,15', u:'kg' },
            { label:'Pour 22 m', val:'1,29', u:'kg', hi: true },
          ].map((s, i) => (
            <div key={i} style={{
              padding:'18px 22px',
              borderRight: i%2===0 ? '1px solid '+C.hair : 'none',
              borderBottom: i<2 ? '1px solid '+C.hair : 'none',
              background: s.hi ? C.accentSoft : 'transparent',
              transform: s.hi ? `scale(${pulse})` : 'none',
              transformOrigin: 'center',
            }}>
              <div style={{fontSize:11, color: s.hi ? C.accentInk : C.muted, textTransform:'uppercase', letterSpacing:'0.06em', fontWeight: s.hi?600:400}}>{s.label}</div>
              <div style={{fontFamily:F.serif, fontSize:32, color: s.hi ? C.accentInk : C.ink, marginTop:4, fontVariantNumeric:'tabular-nums'}}>
                {s.val}<span style={{fontFamily:F.sans, fontSize:14, color:s.hi?C.accentInk:C.muted, fontWeight:400, marginLeft:3}}>{s.u}</span>
              </div>
            </div>
          ))}
        </div>

        {/* Sources */}
        <div style={{
          fontFamily: F.mono, fontSize: 12, color: C.muted2,
          textTransform:'uppercase', letterSpacing:'0.1em',
          marginTop: 10,
          opacity: op(1.5),
        }}>Sources consultées</div>
        {[
          { idx:1, title:'Manuel d\'installation MSZ-AP50VG', ref:'MSZ-AP_IM · p. 24', score:94, at: 1.6 },
          { idx:2, title:'Fiche produit série MSZ-AP — 2025', ref:'FP-MSZAP-2025 · §3.2', score:88, at: 1.9 },
          { idx:3, title:'Norme NF EN 378-2:2016', ref:'Art. 6.2.3', score:76, at: 2.2 },
          { idx:4, title:'Procédure SAV-PR-014', ref:'rev. B · §4', score:71, at: 2.5 },
        ].map((s, i) => (
          <div key={i} style={{
            background: C.surface, border: '1px solid '+C.line, borderRadius: 10,
            padding: '12px 14px',
            opacity: op(s.at),
            transform: `translateX(${(1-op(s.at))*20}px)`,
            display:'flex', alignItems:'center', gap: 12,
          }}>
            <div className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`, minWidth:22, height:22, fontSize:12}}>{s.idx}</div>
            <div style={{flex:1, minWidth:0}}>
              <div style={{fontSize:13, fontWeight:500, color:C.ink, marginBottom:2, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{s.title}</div>
              <div style={{fontSize:11, color:C.muted, fontFamily:F.mono}}>{s.ref}</div>
            </div>
            <div style={{display:'flex', alignItems:'center', gap:5, fontSize:11, color:C.ok, fontFamily:F.mono, fontVariantNumeric:'tabular-nums'}}>
              <span style={{width:5, height:5, borderRadius:'50%', background:C.ok}}/>
              {s.score}%
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ============ Scene 5 — Source trace (35–43s) ============
function SceneTrace() {
  const { localTime } = useSprite();

  // citation zoom in
  const zoomT = Easing.easeOutCubic(clamp(localTime / 0.7, 0, 1));
  // page flies in
  const pageT = Easing.easeOutCubic(clamp((localTime - 0.8) / 0.7, 0, 1));
  // highlight pulse
  const hiT = clamp((localTime - 2.0) / 0.4, 0, 1);
  const pulse = localTime > 2.4 ? 1 + Math.sin((localTime - 2.4) * 5) * 0.05 : 1;
  // caption
  const capT = clamp((localTime - 3.5) / 0.5, 0, 1);
  // exit
  const exitT = clamp((localTime - 6.2) / 0.8, 0, 1);

  return (
    <div style={{position:'absolute', inset:0, background:C.bg2, display:'flex', alignItems:'center', justifyContent:'center', opacity: 1 - exitT}}>
      {/* left: citation bubble */}
      <div style={{
        position:'absolute', left: 140, top: '50%', transform: `translateY(-50%) scale(${zoomT}) translateX(${(1-pageT)*150}px)`,
        opacity: zoomT,
      }}>
        <div style={{fontFamily: F.mono, fontSize: 12, color: C.muted, textTransform:'uppercase', letterSpacing:'0.1em', marginBottom: 14}}>
          Citation [1]
        </div>
        <div style={{
          padding: '20px 26px',
          background: C.surface,
          border: `1.5px solid ${C.accent}`,
          borderRadius: 14,
          boxShadow: `0 20px 50px rgba(20,20,10,0.12), 0 0 0 6px ${C.accentSoft}`,
          maxWidth: 480,
          fontSize: 18, lineHeight: 1.55, color: C.ink2,
          fontFamily: F.sans,
        }}>
          <div style={{display:'flex', alignItems:'center', gap: 10, marginBottom: 10}}>
            <div className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`, minWidth:24, height:24, fontSize:12}}>1</div>
            <div style={{fontSize: 13, color: C.muted, fontFamily: F.mono}}>MSZ-AP_IM · p. 24</div>
          </div>
          Charge R-32 pré-conditionnée : <strong style={{background: C.cite, padding:'1px 4px', borderRadius:3}}>1,15 kg</strong> pour liaisons ≤ 15 m. Ajouter <strong style={{background: C.cite, padding:'1px 4px', borderRadius:3}}>20 g/m</strong> au-delà.
        </div>

        {/* Arrow connecting */}
        <svg style={{position:'absolute', left: 480, top: '50%', width: 200, height: 100, transform:'translateY(-50%)', opacity: pageT}} viewBox="0 0 200 100" fill="none">
          <path d="M 10 50 Q 100 50 190 50" stroke={C.accent} strokeWidth="2" strokeDasharray="6 4" fill="none"/>
          <path d="M 180 40 L 195 50 L 180 60" stroke={C.accent} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </div>

      {/* right: PDF page */}
      <div style={{
        position:'absolute', right: 120, top: '50%',
        transform: `translateY(-50%) scale(${pageT}) rotate(${(1-pageT)*3}deg)`,
        opacity: pageT,
      }}>
        <div style={{
          background: 'white',
          width: 620, height: 780,
          boxShadow: '0 40px 100px rgba(20,20,10,0.2), 0 2px 8px rgba(0,0,0,0.06)',
          padding: '60px 64px',
          borderRadius: 2,
          fontSize: 15, lineHeight: 1.7, color: '#2a2a22',
        }}>
          <div style={{fontFamily: F.mono, fontSize: 10, color: C.muted, marginBottom: 20, letterSpacing:'0.1em'}}>MSZ-AP_IM · FR · rev. C</div>
          <div style={{fontFamily: F.serif, fontSize: 32, letterSpacing:'-0.01em', marginBottom: 22, color:'#1a1a15'}}>2.2 Circuit frigorifique</div>
          <p style={{margin:'0 0 14px'}}>L'unité extérieure <strong>MSZ-AP50VG</strong> est livrée pré-conditionnée avec une charge en fluide frigorigène <strong>R-32</strong>.</p>

          <table style={{width:'100%', borderCollapse:'collapse', fontSize: 13, marginTop: 20}}>
            <thead>
              <tr>
                <th style={{border:'1px solid #e4e2db', padding:'8px 12px', textAlign:'left', background:'#f7f6f2', fontSize:11, textTransform:'uppercase', letterSpacing:'0.04em', color:'#3a3a32'}}>Paramètre</th>
                <th style={{border:'1px solid #e4e2db', padding:'8px 12px', textAlign:'left', background:'#f7f6f2', fontSize:11, textTransform:'uppercase', letterSpacing:'0.04em', color:'#3a3a32'}}>Valeur</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>Fluide</td>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>R-32 (GWP 675)</td>
              </tr>
              <tr>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>Charge usine (≤ 15 m)</td>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>
                  <span style={{
                    background: C.cite, padding:'2px 6px', borderRadius:3,
                    boxShadow: hiT > 0 ? `0 0 0 ${hiT*3}px ${C.citeEdge}` : 'none',
                    transform: `scale(${pulse})`, display:'inline-block',
                    transition: 'box-shadow 200ms',
                  }}>
                    <strong>1,15 kg</strong>
                  </span>
                </td>
              </tr>
              <tr>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>Charge additionnelle</td>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>
                  <span style={{
                    background: C.cite, padding:'2px 6px', borderRadius:3,
                    boxShadow: hiT > 0 ? `0 0 0 ${hiT*3}px ${C.citeEdge}` : 'none',
                    transform: `scale(${pulse})`, display:'inline-block',
                    transition: 'box-shadow 200ms',
                  }}>
                    <strong>20 g / m</strong>
                  </span>
                </td>
              </tr>
              <tr>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>Pression HP</td>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>4,15 MPa</td>
              </tr>
              <tr>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>Pression BP</td>
                <td style={{border:'1px solid #e4e2db', padding:'8px 12px'}}>1,64 MPa</td>
              </tr>
            </tbody>
          </table>

          <div style={{marginTop: 30, textAlign:'center', fontSize: 11, color: C.muted, fontFamily: F.mono}}>— 24 —</div>
        </div>
      </div>

      {/* bottom caption */}
      <div style={{
        position:'absolute', bottom: 60, left: '50%', transform:`translateX(-50%) translateY(${(1-capT)*10}px)`,
        opacity: capT,
        fontFamily: F.serif, fontSize: 36, letterSpacing:'-0.01em',
        color: C.ink, textAlign:'center',
      }}>
        Chaque réponse est <em style={{color:C.accent}}>traçable</em> à sa source exacte.
      </div>
    </div>
  );
}

// ============ Scene 6 — Device forms (43–51s) ============
function SceneDevices() {
  const { localTime } = useSprite();
  const deskT = Easing.easeOutCubic(clamp(localTime / 0.8, 0, 1));
  const phoneT = Easing.easeOutCubic(clamp((localTime - 0.6) / 0.8, 0, 1));
  const labelsT = clamp((localTime - 1.6) / 0.5, 0, 1);

  return (
    <div style={{position:'absolute', inset:0, background: `radial-gradient(ellipse at center, ${C.bg} 0%, ${C.bg2} 70%)`, display:'flex', alignItems:'center', justifyContent:'center', gap: 80}}>
      {/* Desktop mock */}
      <div style={{
        width: 900, height: 560,
        background: '#1b1b16',
        borderRadius: 18,
        padding: 12,
        boxShadow: '0 50px 100px rgba(0,0,0,0.3)',
        transform: `translateY(${(1-deskT)*60}px) scale(${0.9 + deskT*0.1})`,
        opacity: deskT,
      }}>
        <div style={{display:'flex', gap:6, padding:'6px 10px'}}>
          <div style={{width:10, height:10, borderRadius:'50%', background:'#ff5f56'}}/>
          <div style={{width:10, height:10, borderRadius:'50%', background:'#ffbd2e'}}/>
          <div style={{width:10, height:10, borderRadius:'50%', background:'#27c93f'}}/>
        </div>
        <div style={{background:C.bg, height: 'calc(100% - 24px)', borderRadius:10, overflow:'hidden', display:'grid', gridTemplateColumns:'180px 1fr'}}>
          <div style={{background:C.bg, borderRight:'1px solid '+C.line, padding: 14, fontSize: 11}}>
            <div style={{display:'flex', alignItems:'center', gap:8, marginBottom: 20}}>
              <div style={{width:18, height:18, borderRadius:5, background:C.ink, color:'white', display:'grid', placeItems:'center', fontFamily:F.serif, fontSize:12, fontStyle:'italic'}}>F</div>
              <span style={{fontWeight:600, fontSize:11}}>Froid&Air</span>
            </div>
            {['Accueil', 'Assistant', 'Historique', 'Importer'].map((l,i) => (
              <div key={i} style={{padding:'5px 8px', color:C.ink2, background: i===1 ? C.surface : 'transparent', border: i===1? '1px solid '+C.line : 'none', borderRadius:5, marginBottom:2}}>{l}</div>
            ))}
          </div>
          <div style={{padding: 24, background: C.bg}}>
            <div style={{fontFamily:F.serif, fontSize:28, letterSpacing:'-0.01em', marginBottom: 14}}>Pression de charge R-32 ?</div>
            <div style={{background: C.surface, border: '1px solid '+C.line, borderRadius: 10, padding:'14px 18px', fontSize:12, lineHeight: 1.6, color: C.ink2}}>
              <div style={{display:'flex', alignItems:'center', gap:6, color:C.muted, fontSize:10, marginBottom:8, textTransform:'uppercase', letterSpacing:'0.08em'}}>
                <span style={{width:14, height:14, borderRadius:4, background:C.accent, display:'grid', placeItems:'center', color:'white'}}><Icon name="sparkles" size={8}/></span>
                Réponse
              </div>
              Charge usine : <strong>1,15 kg</strong><span className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`, height:14, minWidth:14, fontSize:9}}>1</span> · +20 g/m au-delà de 15 m<span className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`, height:14, minWidth:14, fontSize:9}}>1</span>.
              <div style={{display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap: 0, marginTop: 12, border: '1px solid '+C.line, borderRadius: 6, overflow:'hidden'}}>
                {[['HP','4,15','MPa'],['BP','1,64','MPa'],['Charge','1,15','kg']].map(([l,v,u],i) => (
                  <div key={i} style={{padding:'8px 10px', borderRight: i<2?'1px solid '+C.line:'none'}}>
                    <div style={{fontSize:9, color:C.muted, textTransform:'uppercase', letterSpacing:'0.04em'}}>{l}</div>
                    <div style={{fontFamily:F.serif, fontSize:16, marginTop: 2}}>{v}<span style={{fontFamily:F.sans, fontSize:9, color:C.muted, marginLeft:2}}>{u}</span></div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Phone mock */}
      <div style={{
        width: 280, height: 580,
        background: '#0b0b08',
        borderRadius: 44,
        padding: 10,
        boxShadow: '0 40px 80px rgba(0,0,0,0.3)',
        transform: `translateY(${(1-phoneT)*80}px) scale(${0.9 + phoneT*0.1})`,
        opacity: phoneT,
      }}>
        <div style={{background:C.bg, height:'100%', borderRadius:36, overflow:'hidden', padding:'46px 18px 16px', position:'relative'}}>
          <div style={{position:'absolute', top:10, left:'50%', transform:'translateX(-50%)', width:80, height:22, background:'#0b0b08', borderRadius:14}}/>
          <div style={{fontFamily:F.serif, fontSize:22, letterSpacing:'-0.01em', marginBottom: 14, lineHeight: 1.1}}>
            Assistant<br/>Froid&Air
          </div>
          <div style={{background: C.ink, color:'#fbfbfa', padding:'8px 12px', borderRadius:'12px 12px 4px 12px', fontSize:11, marginLeft:'auto', maxWidth:'80%', marginBottom: 10, textAlign:'right'}}>
            Charge R-32 à 22 m ?
          </div>
          <div style={{fontSize:11, color:C.muted, marginBottom:6, display:'flex', alignItems:'center', gap:5}}>
            <span style={{width:13, height:13, borderRadius:4, background:C.accent, display:'grid', placeItems:'center', color:'white'}}><Icon name="sparkles" size={8}/></span>
            Réponse · 1,4 s
          </div>
          <div style={{fontSize: 12, lineHeight: 1.5, color: C.ink2, marginBottom: 10}}>
            Total <strong style={{color:C.accent}}>1,29 kg</strong> — base 1,15 kg + 140 g pour 7 m en plus<span className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`, height:13, minWidth:13, fontSize:9}}>1</span>.
          </div>
          <div style={{background:C.surface, border:'1px solid '+C.line, borderRadius:8, padding:'8px 10px', display:'flex', gap:7, alignItems:'center', fontSize:10}}>
            <span className="cite" style={{background:C.cite, color:C.citeInk, border:`1px solid ${C.citeEdge}`, height:14, minWidth:14, fontSize:9}}>1</span>
            <div style={{flex:1, minWidth:0}}>
              <div style={{fontWeight:500, color:C.ink}}>MSZ-AP50VG · p.24</div>
            </div>
          </div>
        </div>
      </div>

      {/* Labels */}
      <div style={{
        position:'absolute', bottom: 100, left: '50%', transform:`translateX(-50%) translateY(${(1-labelsT)*10}px)`,
        opacity: labelsT,
        display:'flex', gap: 60, alignItems:'center',
        fontFamily: F.mono, fontSize: 14, color: C.muted,
        textTransform:'uppercase', letterSpacing:'0.1em',
      }}>
        <span>Bureau d'études</span>
        <span style={{color:C.line2}}>·</span>
        <span>Terrain · SAV</span>
      </div>

      <div style={{
        position:'absolute', top: 70, left: '50%', transform:'translateX(-50%)',
        opacity: labelsT,
        fontFamily: F.serif, fontSize: 52, letterSpacing:'-0.02em', textAlign:'center',
      }}>
        Partout où vous <em style={{color:C.accent}}>travaillez</em>.
      </div>
    </div>
  );
}

// ============ Scene 7 — Closing (51–60s) ============
function SceneClosing() {
  const { localTime } = useSprite();
  const logoT = Easing.easeOutBack(clamp(localTime / 0.7, 0, 1));
  const lineT = Easing.easeOutCubic(clamp((localTime - 0.7) / 0.6, 0, 1));
  const statsT = clamp((localTime - 1.4) / 0.5, 0, 1);
  const ctaT = clamp((localTime - 3.0) / 0.6, 0, 1);

  return (
    <div style={{position:'absolute', inset:0, background:C.bg, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap: 30}}>
      {/* Logo mark */}
      <div style={{
        transform: `scale(${logoT})`,
        opacity: logoT,
      }}>
        <div style={{
          width: 96, height: 96,
          background: C.ink, color: '#fbfbfa',
          borderRadius: 24,
          display:'grid', placeItems:'center',
          fontFamily: F.serif, fontSize: 56, fontStyle:'italic', fontWeight:400,
          position:'relative',
        }}>
          F
          <div style={{
            position:'absolute', top: 12, right: 12,
            width: 20, height: 20, borderRadius:'50%',
            background: C.accent,
          }}/>
        </div>
      </div>

      {/* Name + tagline */}
      <div style={{textAlign:'center', opacity: lineT, transform: `translateY(${(1-lineT)*10}px)`}}>
        <div style={{fontFamily:F.serif, fontSize: 96, letterSpacing:'-0.03em', lineHeight: 1, fontWeight: 400}}>
          Froid<span style={{color:C.accent, fontStyle:'italic'}}>&</span>Air
        </div>
        <div style={{fontFamily:F.sans, fontSize: 24, color: C.muted, marginTop: 14, letterSpacing:'-0.005em'}}>
          La base technique qui vous <em style={{color:C.ink}}>répond</em>.
        </div>
      </div>

      {/* Stats ticker */}
      <div style={{
        display:'flex', gap: 0,
        marginTop: 20,
        opacity: statsT,
        transform: `translateY(${(1-statsT)*12}px)`,
        background: C.surface,
        border: '1px solid '+C.line,
        borderRadius: 14,
        overflow:'hidden',
        boxShadow: '0 8px 24px rgba(20,20,10,0.06)',
      }}>
        {[
          { v: '4 821', l: 'documents' },
          { v: '1,8 s', l: 'temps moyen' },
          { v: '94 %', l: 'réponses utiles' },
          { v: '24/7', l: 'disponible' },
        ].map((s, i) => (
          <div key={i} style={{padding:'18px 32px', borderRight: i<3?'1px solid '+C.line:'none', textAlign:'center'}}>
            <div style={{fontFamily:F.serif, fontSize: 38, letterSpacing:'-0.01em', fontVariantNumeric:'tabular-nums'}}>{s.v}</div>
            <div style={{fontSize: 12, color:C.muted, textTransform:'uppercase', letterSpacing:'0.08em', marginTop: 2, fontFamily: F.mono}}>{s.l}</div>
          </div>
        ))}
      </div>

      {/* CTA */}
      <div style={{
        marginTop: 20,
        opacity: ctaT,
        transform: `translateY(${(1-ctaT)*10}px)`,
        display: 'inline-flex', alignItems:'center', gap: 10,
        background: C.ink, color: '#fbfbfa',
        padding: '14px 28px',
        borderRadius: 10,
        fontSize: 17, fontWeight: 500,
      }}>
        Poser la première question <Icon name="arrow" size={16}/>
      </div>
    </div>
  );
}

// ============ Captions ============
const CAPTIONS = [
  { at: 0.5,  end: 8.5,  text: "4 821 documents techniques. Des dizaines de marques, de normes, de procédures…" },
  { at: 9.2,  end: 14.5, text: "Une seule question en langage naturel suffit." },
  { at: 15.2, end: 22.5, text: "Le moteur sémantique lit tous vos documents et sélectionne les passages pertinents." },
  { at: 23.2, end: 34.5, text: "La réponse arrive synthétisée — chiffres, étapes, calculs — avec citations numérotées." },
  { at: 35.2, end: 42.5, text: "Chaque affirmation renvoie à la source exacte. Traçabilité totale." },
  { at: 43.2, end: 50.5, text: "Bureau ou terrain, desktop ou mobile : la même base technique." },
  { at: 51.2, end: 60.0, text: "Froid&Air. La base technique qui vous répond." },
];

function Captions() {
  const time = useTime();
  const active = CAPTIONS.find(c => time >= c.at && time <= c.end);
  if (!active) return null;
  const fadeIn = Easing.easeOutCubic(clamp((time - active.at) / 0.4, 0, 1));
  const fadeOut = 1 - Easing.easeInCubic(clamp((time - (active.end - 0.4)) / 0.4, 0, 1));
  const op = Math.min(fadeIn, fadeOut);
  return (
    <div style={{
      position:'absolute', bottom: 42, left:'50%',
      transform: `translateX(-50%) translateY(${(1-fadeIn)*8}px)`,
      opacity: op,
      background: 'rgba(21,21,15,0.92)',
      color: '#fbfbfa',
      padding: '14px 24px',
      borderRadius: 10,
      fontSize: 20,
      fontFamily: F.sans,
      maxWidth: 1100,
      textAlign:'center',
      letterSpacing: '-0.005em',
      backdropFilter: 'blur(8px)',
      boxShadow: '0 10px 30px rgba(0,0,0,0.3)',
      pointerEvents: 'none',
    }}>
      {active.text}
    </div>
  );
}

// ============ Chapter indicator ============
const CHAPTERS = [
  { at: 0,    label: '01 · Le problème' },
  { at: 9,    label: '02 · La requête' },
  { at: 15,   label: '03 · Recherche sémantique' },
  { at: 23,   label: '04 · La réponse' },
  { at: 35,   label: '05 · Traçabilité' },
  { at: 43,   label: '06 · Multi-support' },
  { at: 51,   label: '07 · Froid&Air' },
];
function ChapterHUD() {
  const time = useTime();
  let ch = CHAPTERS[0];
  for (const c of CHAPTERS) if (time >= c.at) ch = c;
  return (
    <div style={{
      position:'absolute', top: 32, left: 42,
      fontFamily: F.mono, fontSize: 12,
      color: C.muted,
      letterSpacing: '0.1em',
      textTransform:'uppercase',
      display:'flex', alignItems:'center', gap: 12,
      background: 'rgba(255,255,255,0.7)',
      backdropFilter: 'blur(8px)',
      padding: '6px 12px',
      borderRadius: 6,
      border: '1px solid '+C.line,
    }}>
      <span style={{width:6, height:6, borderRadius:'50%', background:C.accent}}/>
      {ch.label}
    </div>
  );
}

function BrandCorner() {
  return (
    <div style={{
      position:'absolute', top: 32, right: 42,
      display:'flex', alignItems:'center', gap: 10,
      background: 'rgba(255,255,255,0.7)',
      backdropFilter: 'blur(8px)',
      padding: '6px 12px',
      borderRadius: 6,
      border: '1px solid '+C.line,
      fontSize: 13,
    }}>
      <div style={{width: 20, height: 20, borderRadius: 5, background: C.ink, color:'#fbfbfa', display:'grid', placeItems:'center', fontFamily:F.serif, fontSize:14, fontStyle:'italic'}}>F</div>
      <span style={{fontWeight: 600, letterSpacing:'-0.005em'}}>Froid<span style={{color:C.accent}}>&</span>Air</span>
    </div>
  );
}

// ============ Full composition ============
function Video() {
  return (
    <Stage width={1920} height={1080} duration={60} background={C.bg}>
      <Sprite start={0} end={9}>
        <ScenePaperChaos/>
      </Sprite>
      <Sprite start={9} end={15}>
        <SceneSearchReveal/>
      </Sprite>
      <Sprite start={15} end={23}>
        <SceneRetrieval/>
      </Sprite>
      <Sprite start={23} end={35}>
        <SceneAnswer/>
      </Sprite>
      <Sprite start={35} end={43}>
        <SceneTrace/>
      </Sprite>
      <Sprite start={43} end={51}>
        <SceneDevices/>
      </Sprite>
      <Sprite start={51} end={60}>
        <SceneClosing/>
      </Sprite>

      <ChapterHUD/>
      <BrandCorner/>
      <Captions/>
    </Stage>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Video/>);
