// Scenes for the Tellings video.
// Each scene is a Sprite with start/end seconds.

// ── Scene 1: HOOK (0–5.0s) — kinetic typography ───────────────────
// Plays the dog→dah joke purely through type:
//   "her first word for"      (small)
//        dog                   (BIG, then struck through)
//        dah.                  (BIGGER, terracotta, italic, drops in)
function HookScene() {
  const { localTime: t } = useSprite();

  // wordmark
  const wmOp = clamp((t - 0.05) / 0.4, 0, 1);

  // "her first word for" types in (0.4–1.4)
  const lineStart = 0.4;
  const lineText = "her first word for";
  const lineChars = Math.max(0, Math.floor((t - lineStart) * 28));
  const lineVisible = lineText.slice(0, Math.min(lineChars, lineText.length));
  const lineOp = clamp((t - lineStart) / 0.2, 0, 1);

  // "dog" arrives (1.3) big & black
  const dogStart = 1.3;
  const dogP = clamp((t - dogStart) / 0.45, 0, 1);
  const dogEase = Easing.easeOutBack(dogP);
  const dogScale = 0.6 + 0.4 * dogEase;
  const dogOp = clamp((t - dogStart) / 0.2, 0, 1);

  // strikethrough sweeps across "dog" (1.95–2.35)
  const strikeStart = 1.95;
  const strikeP = Easing.easeOutCubic(clamp((t - strikeStart) / 0.35, 0, 1));

  // "dah." drops in (2.3) bigger, terracotta, italic
  const dahStart = 2.3;
  const dahP = clamp((t - dahStart) / 0.55, 0, 1);
  const dahEase = Easing.easeOutBack(dahP);
  const dahScale = 0.55 + 0.45 * dahEase;
  const dahOp = clamp((t - dahStart) / 0.25, 0, 1);
  const dahY = (1 - Easing.easeOutCubic(clamp((t - dahStart) / 0.5, 0, 1))) * 24;

  // dog slides up & dims to make room (2.3)
  const dogShift = clamp((t - 2.3) / 0.5, 0, 1);
  const dogYShift = -Easing.easeInOutCubic(dogShift) * 20;
  const dogDim = 1 - dogShift * 0.5;

  // tag becomes a line straight from the chapter
  const tagStart = 3.5;
  const tagOp = clamp((t - tagStart) / 0.5, 0, 1);
  const tagY = (1 - Easing.easeOutCubic(clamp((t - tagStart) / 0.6, 0, 1))) * 10;

  // paw prints scamper across, two diagonal trails (puppy energy)
  // Each entry: [x, y, rotation, scale, start]
  const paws = [
    { x:  50, y: 760, r: -18, s: 0.85, t0: 3.05 },
    { x: 105, y: 800, r:   8, s: 0.95, t0: 3.18 },
    { x: 165, y: 760, r: -12, s: 0.90, t0: 3.30 },
    { x: 225, y: 805, r:  14, s: 1.00, t0: 3.42 },
    { x: 290, y: 770, r:  -6, s: 0.92, t0: 3.55 },
    { x: 355, y: 815, r:  18, s: 0.98, t0: 3.68 },
    { x: 420, y: 775, r: -10, s: 0.88, t0: 3.80 },
  ];

  // exit
  const exitT = clamp((t - 4.4) / 0.6, 0, 1);
  const sceneY = -exitT * 60;
  const sceneOpacity = 1 - exitT;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: TPALETTE.cream,
      transform: `translateY(${sceneY}px)`,
      opacity: sceneOpacity,
    }}>
      <PaperGrain opacity={0.08}/>

      {/* wordmark */}
      <div style={{
        position: 'absolute', top: 60, left: 0, right: 0,
        display: 'flex', justifyContent: 'center',
        opacity: wmOp,
      }}>
        <Wordmark size={22} color={TPALETTE.muted}/>
      </div>

      {/* "her first word for" */}
      <div style={{
        position: 'absolute', top: 240, left: 0, right: 0,
        textAlign: 'center',
        fontFamily: SERIF, fontStyle: 'italic',
        fontSize: 32, color: TPALETTE.inkSoft,
        letterSpacing: '-0.005em',
        opacity: lineOp,
      }}>
        {lineVisible}
        <span style={{
          opacity: lineChars < lineText.length ? (Math.floor(t * 4) % 2 ? 1 : 0) : 0,
          color: TPALETTE.terracotta,
        }}>▍</span>
      </div>

      {/* "dog" — big black italic, struck through */}
      <div style={{
        position: 'absolute',
        top: 340, left: 0, right: 0,
        textAlign: 'center',
        opacity: dogOp * dogDim,
        transform: `scale(${dogScale}) translateY(${dogYShift}px)`,
        transformOrigin: 'center center',
      }}>
        <span style={{
          position: 'relative',
          display: 'inline-block',
          fontFamily: SERIF, fontStyle: 'italic',
          fontSize: 170, fontWeight: 500,
          color: TPALETTE.ink,
          letterSpacing: '-0.04em',
          lineHeight: 0.9,
          paddingInline: 20,
        }}>
          dog
          {/* strikethrough line that sweeps in */}
          <span style={{
            position: 'absolute',
            left: 20, right: 20,
            top: '54%',
            height: 8,
            background: TPALETTE.terracotta,
            borderRadius: 4,
            transform: `scaleX(${strikeP}) rotate(-2deg)`,
            transformOrigin: 'left center',
            boxShadow: '0 1px 0 rgba(26,22,18,0.1)',
          }}/>
        </span>
      </div>

      {/* "dah." — bigger, terracotta, italic, drops in below */}
      <div style={{
        position: 'absolute',
        top: 520, left: 0, right: 0,
        textAlign: 'center',
        opacity: dahOp,
        transform: `scale(${dahScale}) translateY(${dahY}px)`,
        transformOrigin: 'center center',
      }}>
        <div style={{
          fontFamily: SERIF, fontStyle: 'italic',
          fontSize: 220, fontWeight: 500,
          color: TPALETTE.terracotta,
          letterSpacing: '-0.05em',
          lineHeight: 0.85,
        }}>
          dah.
        </div>
      </div>

      {/* paw prints scamper across */}
      {paws.map((p, i) => {
        const local = clamp((t - p.t0) / 0.35, 0, 1);
        const ease = Easing.easeOutBack(local);
        const pawScale = p.s * (0.2 + 0.8 * ease);
        const pawOp = clamp((t - p.t0) / 0.18, 0, 1);
        // a tiny lift then settle, like a hop
        const hop = -Math.sin(clamp((t - p.t0) / 0.3, 0, 1) * Math.PI) * 8;
        return (
          <div key={i} style={{
            position: 'absolute',
            left: p.x, top: p.y + hop,
            transform: `scale(${pawScale})`,
            transformOrigin: 'center',
            opacity: pawOp,
          }}>
            <PawPrint size={26} color={TPALETTE.terracotta} rotate={p.r}/>
          </div>
        );
      })}

      {/* the terrier trots in at the end of the paw trail */}
      {(() => {
        const tStart = 3.7;
        const p = clamp((t - tStart) / 0.6, 0, 1);
        const ease = Easing.easeOutCubic(p);
        const x = 560 - (560 - 430) * ease; // trot in from the right
        const bob = Math.sin(clamp((t - tStart) / 0.18, 0, 6) * Math.PI) * 4;
        const op = clamp((t - tStart) / 0.25, 0, 1);
        return (
          <div style={{
            position: 'absolute',
            left: x, top: 712 + bob,
            opacity: op,
            transform: 'scaleX(-1)', // face left, toward the trail
          }}>
            <TerrierMini size={108}/>
          </div>
        );
      })()}

      {/* tag — line from the actual chapter */}
      <div style={{
        position: 'absolute',
        top: 875, left: 0, right: 0,
        textAlign: 'center',
        opacity: tagOp,
        transform: `translateY(${tagY}px)`,
        fontFamily: SERIF, fontStyle: 'italic',
        fontSize: 22, color: TPALETTE.muted,
        letterSpacing: '-0.005em',
      }}>
        every dog. real or pictured.
      </div>
    </div>
  );
}

// ── Scene 2: RECORD (5.0–11.5s) — phone arrives, tap record ───────
function RecordScene() {
  const { localTime: t } = useSprite();

  // phone slides up
  const slideP = Easing.easeOutCubic(clamp(t / 0.7, 0, 1));
  const phoneY = (1 - slideP) * 600 + 80;

  // record button pulse pre-tap
  const preTapPulse = 1 + Math.sin(t * 5) * 0.04;
  const tapT = 1.6;
  const recording = t >= tapT;
  const tapPress = clamp((t - tapT) / 0.15, 0, 1);
  const buttonScale = recording
    ? (1 - tapPress * 0.18 + 0.02 * Math.sin(t * 9))
    : preTapPulse;

  // waveform start after tap
  const waveT = recording ? t - tapT : 0;

  // caption that types in once recording starts (mock transcript)
  const captionFull = "the terrier at the end of our block got more 'dah's than i got 'mama's all month.";
  const captionStart = tapT + 0.4;
  const cps = 22; // chars per sec
  const captionChars = Math.max(0, Math.floor((t - captionStart) * cps));
  const captionText = captionFull.slice(0, captionChars);

  // exit
  const exitT = clamp((t - 7.0) / 0.5, 0, 1);
  const sceneOpacity = 1 - exitT;
  const sceneY = -exitT * 30;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: TPALETTE.cream,
      opacity: sceneOpacity,
      transform: `translateY(${sceneY}px)`,
    }}>
      <PaperGrain opacity={0.08}/>

      {/* on-screen caption above phone */}
      <div style={{
        position: 'absolute', top: 110, left: 0, right: 0,
        textAlign: 'center',
        fontFamily: SERIF, fontStyle: 'italic',
        fontSize: 34, color: TPALETTE.ink,
        letterSpacing: '-0.01em',
        opacity: clamp((t - 0.3) / 0.5, 0, 1) * (1 - clamp((t - 4.4) / 0.5, 0, 1)),
      }}>
        so you tap.<br/>
        <span style={{ color: TPALETTE.muted, fontStyle: 'normal', fontFamily: SANS, fontSize: 22 }}>and speak.</span>
      </div>

      {/* phone */}
      <div style={{
        position: 'absolute', left: '50%', top: phoneY,
        width: 460, marginLeft: -230,
      }}>
        <Phone x={0} y={0} width={460}>
          <RecordScreen t={t} recording={recording} waveT={waveT} buttonScale={buttonScale} caption={captionText}/>
        </Phone>
      </div>
    </div>
  );
}

function RecordScreen({ t, recording, waveT, buttonScale, caption }) {
  return (
    <div style={{ position: 'absolute', inset: 0, padding: '64px 24px 24px', display: 'flex', flexDirection: 'column' }}>
      {/* header */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 4 }}>
        <Wordmark size={20} color={TPALETTE.muted}/>
        <div style={{ fontFamily: MONO, fontSize: 10, color: TPALETTE.mutedSoft, letterSpacing: '0.1em' }}>
          {recording ? '● REC' : 'TUE · MAR 12'}
        </div>
      </div>

      {/* prompt */}
      <div style={{ marginTop: 30, textAlign: 'center', paddingInline: 8 }}>
        <div style={{
          fontFamily: SERIF, fontStyle: 'italic', fontSize: 28,
          color: TPALETTE.ink, lineHeight: 1.2, letterSpacing: '-0.01em',
        }}>
          {recording ? 'recording…' : 'what happened today?'}
        </div>
      </div>

      {/* waveform */}
      <div style={{ marginTop: 36, display: 'flex', justifyContent: 'center' }}>
        <Waveform width={360} height={76} t={waveT} active={recording}/>
      </div>

      {/* live transcription card */}
      <div style={{
        marginTop: 28, marginInline: 6,
        background: '#fff8ec',
        border: `1px solid ${TPALETTE.hair}`,
        borderRadius: 16,
        padding: '18px 20px 20px',
        flex: 1,
        display: 'flex', flexDirection: 'column',
      }}>
        <div style={{
          fontFamily: MONO, fontSize: 11, letterSpacing: '0.16em',
          color: TPALETTE.terracotta, textTransform: 'uppercase',
          marginBottom: 12,
        }}>
          {recording ? '● transcribing' : 'transcript'}
        </div>
        <div style={{
          fontFamily: SERIF, fontStyle: 'italic',
          fontSize: 24, lineHeight: 1.5, color: TPALETTE.ink,
          letterSpacing: '-0.005em',
        }}>
          {caption}
          {recording && <span style={{ opacity: Math.floor(t * 4) % 2 ? 1 : 0, color: TPALETTE.terracotta }}>▍</span>}
        </div>
      </div>

      {/* spacer */}
      <div style={{ height: 14 }}/>

      {/* timer + record button */}
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 18, paddingBottom: 24 }}>
        <div style={{
          fontFamily: MONO, fontSize: 13, color: TPALETTE.muted,
          letterSpacing: '0.08em',
        }}>
          {recording
            ? `0:${String(Math.floor(waveT)).padStart(2,'0')}`
            : 'hold to record · or tap'}
        </div>
        <div style={{
          width: 84, height: 84, borderRadius: 42,
          background: TPALETTE.terracotta,
          transform: `scale(${buttonScale})`,
          boxShadow: '0 8px 22px rgba(196,97,58,0.45), inset 0 0 0 4px rgba(245,240,232,0.95), inset 0 0 0 5px ' + TPALETTE.terracotta,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          {recording && <div style={{ width: 26, height: 26, borderRadius: 4, background: TPALETTE.cream }}/>}
        </div>
      </div>
    </div>
  );
}

// ── Scene 3: PHOTOS (11.5–16.0s) — auto-attach from camera roll ───
function PhotosScene() {
  const { localTime: t } = useSprite();

  // caption
  const capOp = clamp((t - 0.1) / 0.5, 0, 1) * (1 - clamp((t - 3.3) / 0.5, 0, 1));

  // photos fly in around the central recording card
  const photoStarts = [0.4, 0.6, 0.8, 1.0, 1.2, 1.4];
  const photos = [
    { caption: 'nose to nose', illo: <IlloNoseToNose/>, from: { x: -260, y: -180 }, to: { x: -185, y: -150 }, rot: -10 },
    { caption: 'the terrier',  illo: <IlloTerrier/>,    from: { x: 260, y: -160 }, to: { x: 185, y: -130 }, rot: 8 },
    { caption: 'dah!',         illo: <IlloDah/>,        from: { x: -300, y: 40 },  to: { x: -210, y: 25 },  rot: -6 },
    { caption: 'window watch', illo: <IlloWindow/>,     from: { x: 300, y: 60 },   to: { x: 205, y: 40 },   rot: 11 },
    { caption: 'first walk',   illo: <IlloWalk/>,       from: { x: -180, y: 230 }, to: { x: -135, y: 195 }, rot: 4 },
    { caption: 'good night',   illo: <IlloGoodnight/>,  from: { x: 200, y: 240 },  to: { x: 150, y: 200 },  rot: -8 },
  ];

  const sceneExit = clamp((t - 3.5) / 0.5, 0, 1);

  return (
    <div style={{ position: 'absolute', inset: 0, background: TPALETTE.cream, opacity: 1 - sceneExit }}>
      <PaperGrain opacity={0.08}/>

      {/* caption */}
      <div style={{
        position: 'absolute', top: 110, left: 0, right: 0,
        textAlign: 'center', opacity: capOp,
        fontFamily: SERIF, fontStyle: 'italic',
        fontSize: 34, color: TPALETTE.ink, letterSpacing: '-0.01em',
      }}>
        the photos<br/>
        <span style={{ color: TPALETTE.muted, fontStyle: 'normal', fontFamily: SANS, fontSize: 22 }}>
          show up on their own.
        </span>
      </div>

      {/* center: recording row */}
      <div style={{
        position: 'absolute', left: '50%', top: '50%',
        transform: 'translate(-50%, -50%)',
        width: 340,
      }}>
        <FeedRow title="“the terrier at the end…”" dur="0:34 · MAR 12" />
        <div style={{
          marginTop: 8,
          fontFamily: MONO, fontSize: 10, color: TPALETTE.mutedSoft,
          letterSpacing: '0.08em', textAlign: 'center', opacity: clamp((t - 0.3) / 0.4, 0, 1),
        }}>
          ATTACHING 6 PHOTOS · ±12h
        </div>
      </div>

      {/* photos fly in */}
      {photos.map((p, i) => {
        const start = photoStarts[i];
        const local = clamp((t - start) / 0.7, 0, 1);
        const ease = Easing.easeOutCubic(local);
        const x = p.from.x + (p.to.x - p.from.x) * ease;
        const y = p.from.y + (p.to.y - p.from.y) * ease;
        const op = clamp((t - start) / 0.3, 0, 1);
        const r = p.rot * ease;
        return (
          <div key={i} style={{
            position: 'absolute', left: '50%', top: '50%',
            transform: `translate(calc(-50% + ${x}px), calc(-50% + ${y}px)) rotate(${r}deg)`,
            opacity: op,
          }}>
            <PhotoCard caption={p.caption} illo={p.illo} width={138} height={168}/>
          </div>
        );
      })}
    </div>
  );
}

// ── Scene 4: CHAPTER (16.0–22.5s) — text writes itself ────────────
function ChapterScene() {
  const { localTime: t } = useSprite();

  const intro = "we turn them into chapters.";
  const introSub = "in your voice.";

  // phone with chapter page
  const phoneIn = Easing.easeOutCubic(clamp(t / 0.6, 0, 1));
  const phoneY = (1 - phoneIn) * 80 + 220;

  // typing — faster so it can land, then hold
  const fullText = "The word ‘dog’ came out as ‘dah’ for about three weeks, and she said it at every dog, real or pictured. The terrier at the end of our block got more ‘dah’s than I got ‘mama’s all month. I did not take it personally. Mostly.";
  const typeStart = 0.7;
  const cps = 58;
  const chars = Math.max(0, Math.floor((t - typeStart) * cps));
  const visible = fullText.slice(0, chars);
  const done = chars >= fullText.length;

  const exitT = clamp((t - 7.4) / 0.5, 0, 1);

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: TPALETTE.cream,
      opacity: 1 - exitT,
    }}>
      <PaperGrain opacity={0.08}/>

      <div style={{
        position: 'absolute', top: 100, left: 0, right: 0, textAlign: 'center',
        opacity: clamp((t - 0.05) / 0.4, 0, 1),
      }}>
        <div style={{
          fontFamily: SERIF, fontStyle: 'italic',
          fontSize: 34, color: TPALETTE.ink, letterSpacing: '-0.01em',
        }}>
          {intro}
        </div>
        <div style={{
          fontFamily: SANS, fontSize: 22, color: TPALETTE.muted, marginTop: 4,
        }}>
          {introSub}
        </div>
      </div>

      <div style={{
        position: 'absolute', left: '50%', top: phoneY,
        width: 460, marginLeft: -230,
      }}>
        <Phone width={460}>
          <ChapterPage typedText={visible} t={t} done={done}/>
        </Phone>
      </div>
    </div>
  );
}

function ChapterPage({ typedText, t, done }) {
  return (
    <div style={{ position: 'absolute', inset: 0, padding: '60px 30px 30px', display: 'flex', flexDirection: 'column' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 4 }}>
        <div style={{ fontFamily: MONO, fontSize: 11, color: TPALETTE.mutedSoft, letterSpacing: '0.16em' }}>CHAPTER SEVEN</div>
        <div style={{ fontFamily: MONO, fontSize: 11, color: TPALETTE.mutedSoft, letterSpacing: '0.16em' }}>MARCH 2025</div>
      </div>

      <div style={{
        fontFamily: SERIF, fontStyle: 'italic',
        fontSize: 34, color: TPALETTE.ink, marginTop: 14,
        letterSpacing: '-0.015em', lineHeight: 1.05,
      }}>
        the terrier
      </div>

      <div style={{ height: 1, background: TPALETTE.hair, marginTop: 16, marginBottom: 20 }}/>

      <div style={{
        fontFamily: SERIF, fontSize: 23, lineHeight: 1.6,
        color: TPALETTE.ink, letterSpacing: '0.002em',
        textWrap: 'pretty',
      }}>
        {typedText}
        {!done && (
          <span style={{ opacity: Math.floor(t * 3) % 2 ? 1 : 0, color: TPALETTE.terracotta }}>▍</span>
        )}
      </div>

      {/* attached photos — fades in once the chapter is written */}
      <div style={{
        marginTop: 40,
        opacity: clamp((t - 5.2) / 0.6, 0, 1),
        transform: `translateY(${(1 - clamp((t - 5.2) / 0.6, 0, 1)) * 8}px)`,
      }}>
        <div style={{
          fontFamily: MONO, fontSize: 10, color: TPALETTE.mutedSoft,
          letterSpacing: '0.14em', textTransform: 'uppercase', marginBottom: 10,
        }}>From this week</div>
        <div style={{ display: 'flex', gap: 10 }}>
          {[<IlloTerrier/>, <IlloDah/>, <IlloWindow/>].map((illo, i) => (
            <div key={i} style={{
              flex: 1, aspectRatio: '1 / 1', borderRadius: 10, overflow: 'hidden',
              boxShadow: '0 2px 8px rgba(26,22,18,0.12)',
            }}>{illo}</div>
          ))}
        </div>
      </div>

      <div style={{ flex: 1 }}/>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <svg width="12" height="12" viewBox="0 0 14 14"><path d="M3 4 L3 10 L8 10 L11 13 L11 1 L8 4 Z" fill={TPALETTE.terracotta}/></svg>
          <div style={{ fontFamily: MONO, fontSize: 11, color: TPALETTE.mutedSoft, letterSpacing: '0.12em' }}>
            IN MOM’S VOICE
          </div>
        </div>
        <div style={{
          padding: '9px 16px', borderRadius: 999,
          background: TPALETTE.ink, color: TPALETTE.cream,
          fontFamily: SANS, fontSize: 13, fontWeight: 600, letterSpacing: '0.01em',
        }}>Lock chapter</div>
      </div>
    </div>
  );
}

// ── Scene 5: BOOK ─────────────────────────────────────────────────
function BookScene() {
  const { localTime: t } = useSprite();

  // Slow scale-in + small upward drift (ken-burns), no 3D
  const riseP = Easing.easeOutCubic(clamp(t / 0.8, 0, 1));
  const scale = 0.95 + 0.05 * riseP;
  const driftY = (1 - riseP) * 26;
  const opacity = riseP;

  // caption
  const capOp = clamp((t - 0.4) / 0.5, 0, 1) * (1 - clamp((t - 2.4) / 0.4, 0, 1));

  const exitT = clamp((t - 2.7) / 0.4, 0, 1);

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: 'radial-gradient(120% 70% at 50% 56%, #ECE2CF 0%, #D8C9AE 78%)',
      opacity: 1 - exitT,
    }}>
      <PaperGrain opacity={0.12}/>

      {/* caption */}
      <div style={{
        position: 'absolute', top: 110, left: 0, right: 0, textAlign: 'center',
        opacity: capOp,
        fontFamily: SERIF, fontStyle: 'italic',
        fontSize: 34, color: TPALETTE.ink, letterSpacing: '-0.01em',
      }}>
        a real book.<br/>
        <span style={{ color: TPALETTE.muted, fontStyle: 'normal', fontFamily: SANS, fontSize: 22 }}>
          they’ll hold it one day.
        </span>
      </div>

      <div style={{
        position: 'absolute', left: '50%', top: 280,
        transform: `translate(-50%, ${driftY}px) scale(${scale})`,
        opacity,
      }}>
        <BookMock width={300}/>
      </div>

      {/* ground shadow */}
      <div style={{
        position: 'absolute', left: '50%', bottom: 130,
        width: 320, height: 28,
        transform: 'translateX(-50%)',
        background: 'radial-gradient(ellipse at center, rgba(60,20,5,0.40), rgba(60,20,5,0) 70%)',
        filter: 'blur(10px)',
        opacity: 0.7 * opacity,
      }}/>
    </div>
  );
}

// ── Scene 6: END (27.0–30.0s) — wordmark + tagline ────────────────
function EndScene() {
  const { localTime: t } = useSprite();

  const wordmarkP = Easing.easeOutCubic(clamp(t / 0.8, 0, 1));
  const wordmarkScale = 0.92 + 0.08 * wordmarkP;
  const taglineOp = clamp((t - 0.8) / 0.6, 0, 1);

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: TPALETTE.cream,
    }}>
      <PaperGrain opacity={0.08}/>

      {/* warm vignette — the love shot, in a soft circle */}
      <div style={{
        position: 'absolute', left: '50%', top: '20%',
        transform: `translate(-50%, 0) scale(${0.85 + 0.15 * wordmarkP})`,
        opacity: wordmarkP,
        width: 150, height: 150, borderRadius: 75,
        overflow: 'hidden',
        boxShadow: '0 10px 30px rgba(26,22,18,0.16)',
      }}>
        <IlloNoseToNose/>
      </div>

      <div style={{
        position: 'absolute', left: 0, right: 0, top: '40%',
        textAlign: 'center',
        opacity: wordmarkP,
        transform: `scale(${wordmarkScale})`,
      }}>
        <div style={{
          fontFamily: SERIF, fontStyle: 'italic',
          fontSize: 110, color: TPALETTE.ink,
          letterSpacing: '-0.04em', lineHeight: 1,
        }}>
          tellings
        </div>
        <div style={{
          width: 60, height: 2,
          background: TPALETTE.terracotta,
          margin: '28px auto 0',
          transform: `scaleX(${clamp((t - 0.5) / 0.4, 0, 1)})`,
          transformOrigin: 'center',
        }}/>
      </div>

      <div style={{
        position: 'absolute', left: 0, right: 0, top: '60%',
        textAlign: 'center',
        opacity: taglineOp,
        transform: `translateY(${(1 - taglineOp) * 10}px)`,
      }}>
        <div style={{
          fontFamily: SANS, fontSize: 22, color: TPALETTE.muted,
          letterSpacing: '0.01em', lineHeight: 1.5,
        }}>
          your voice. their story.<br/>
          <span style={{ color: TPALETTE.ink, fontFamily: SERIF, fontStyle: 'italic', fontSize: 26 }}>
            forever.
          </span>
        </div>
      </div>

      <div style={{
        position: 'absolute', bottom: 60, left: 0, right: 0,
        textAlign: 'center',
        fontFamily: MONO, fontSize: 11, color: TPALETTE.mutedSoft,
        letterSpacing: '0.18em', textTransform: 'uppercase',
        opacity: clamp((t - 1.4) / 0.5, 0, 1),
      }}>
        tellings.co
      </div>
    </div>
  );
}

Object.assign(window, {
  HookScene, RecordScene, PhotosScene, ChapterScene, BookScene, EndScene,
});
