// Act 2 — Solution pipeline (5–20s): URL → analyze → clip → publish adapted
function Act2Solution() {
  return (
    <Sprite start={5.0} end={20.0}>
      <Act2Inner />
    </Sprite>
  );
}

function Act2Inner() {
  const { localTime: t } = useSprite();

  // Phases (act-local, total 15s):
  //   0.0 - 1.5   Logo reveal
  //   1.5 - 4.5   Paste URL (1 typed, 1 instant)
  //   4.5 - 7.5   AI analysis
  //   7.5 - 11.0  Clip generation
  //  11.0 - 15.0  Publish adapted to each network

  return (
    <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, #0f0f0f 0%, #000 100%)', overflow: 'hidden' }}>
      {t < 1.5 && <LogoReveal t={t} />}
      {t >= 1.5 && t < 4.5 && <PhaseURL t={t - 1.5} />}
      {t >= 4.5 && t < 7.5 && <PhaseAnalysis t={t - 4.5} />}
      {t >= 7.5 && t < 11.0 && <PhaseClip t={t - 7.5} />}
      {t >= 11.0 && t < 15.0 && <PhaseAdaptPublish t={t - 11.0} />}

      <Subtitles t={t} />
    </div>
  );
}

function LogoReveal({ t }) {
  // Logo reveal compressed to 1.5s total: fade-in 0.0-0.4s, hold 0.4-1.1s, fade-out 1.1-1.5s.
  // Slogan moved to Act 5 (closer to CTA).
  if (t >= 1.5) return null;
  const fadeIn = Easing.easeOutCubic(clamp(t / 0.4, 0, 1));
  const fadeOut = t > 1.1 ? Easing.easeInCubic(clamp((1.5 - t) / 0.4, 0, 1)) : 1;
  const opacity = Math.min(fadeIn, fadeOut);
  const scaleK = Easing.easeOutBack(clamp(t / 0.55, 0, 1));
  const scale = 0.6 + scaleK * 0.4;
  return (
    <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', opacity }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 24, transform: `scale(${scale}) translateX(-32px)` }}>
        <BoltLogo size={128} />
        <div style={{ fontFamily: 'Inter, system-ui, sans-serif', fontSize: 128, fontWeight: 800, letterSpacing: '-0.04em', color: '#fff' }}>Chispa</div>
      </div>
    </div>
  );
}

function BoltLogo({ size = 80 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 100 100">
      <defs>
        <linearGradient id="bolt-grad" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor="#F59E0B" />
          <stop offset="100%" stopColor="#EA580C" />
        </linearGradient>
        <filter id="bolt-glow"><feGaussianBlur stdDeviation="3" /></filter>
      </defs>
      <path d="M55 8 L25 52 L48 52 L42 92 L75 42 L52 42 Z" fill="url(#bolt-grad)" filter="url(#bolt-glow)" opacity="0.6" />
      <path d="M55 8 L25 52 L48 52 L42 92 L75 42 L52 42 Z" fill="url(#bolt-grad)" />
    </svg>
  );
}

function PhaseURL({ t }) {
  // 3.0s window (1.5-4.5 absolute). One URL typed, the other appears instantly.
  const opacity = t < 0.3 ? Easing.easeOutCubic(t / 0.3) : t > 2.6 ? Easing.easeInCubic(Math.max(0, (3.0 - t) / 0.4)) : 1;
  const url1 = 'twitch.tv/streamer/v/2847391';
  const url2 = 'youtube.com/watch?v=Hk9oG7tT4nQ';
  // Twitch typed in 0.0–1.4s. YouTube appears pre-filled at 1.4s with scale-in.
  const typed1 = t < 1.4
    ? url1.slice(0, Math.min(url1.length, Math.floor(t * 26)))
    : url1;
  const url1Active = t < 1.4;
  const url1Done = t >= 1.4;
  const url2In = clamp((t - 1.4) / 0.35, 0, 1);
  const url2Eased = Easing.easeOutBack(url2In);
  const url2Done = t >= 1.6;
  const showCursor = Math.floor(t * 4) % 2 === 0;
  const buttonProgress = Easing.easeOutCubic(clamp((t - 1.8) * 4, 0, 1));

  // CLICK animation centered around t=2.2 (well before phase end at 3.0)
  let btnScale = 1;
  let btnBrightness = 1;
  let pressed = false;
  if (t >= 2.05 && t < 2.2) {
    const k = (t - 2.05) / 0.15;
    btnScale = 1 + k * 0.05;
  } else if (t >= 2.2 && t < 2.35) {
    const k = (t - 2.2) / 0.15;
    btnScale = 1.05 - k * 0.13;
    btnBrightness = 1 + k * 0.3;
    pressed = true;
  } else if (t >= 2.35 && t < 2.5) {
    const k = (t - 2.35) / 0.15;
    btnScale = 0.92 + k * 0.08;
    btnBrightness = 1.3 - k * 0.3;
    pressed = true;
  } else if (t >= 2.5) {
    pressed = true;
  }
  const rippleStart = 2.3;
  const rippleProgress = clamp((t - rippleStart) / 0.4, 0, 1);
  const showRipple = rippleProgress > 0 && rippleProgress < 1;
  const showClickCursor = t >= 1.9 && t < 2.35;
  const cursorIn = clamp((t - 1.85) / 0.15, 0, 1);

  return (
    <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', opacity }}>
      <div style={{
        width: 1080,
        height: 480,
        padding: 44,
        boxSizing: 'border-box',
        background: 'rgba(255,255,255,0.04)',
        border: '1px solid rgba(255,255,255,0.1)',
        borderRadius: 24,
        backdropFilter: 'blur(20px)',
        display: 'flex',
        flexDirection: 'column',
        gap: 20,
      }}>
        <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 18, color: '#F59E0B', letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 600 }}>
          paso 1 · pega tu directo o vídeo
        </div>

        <URLRow
          label="TWITCH · DIRECTO"
          labelColor="#9146FF"
          icon={<TwitchIcon />}
          typed={typed1}
          active={url1Active}
          done={url1Done}
          cursor={showCursor}
        />

        <div style={{ opacity: url2Eased, transform: `scale(${0.94 + url2Eased * 0.06})`, transformOrigin: 'left center' }}>
          <URLRow
            label="YOUTUBE · VÍDEO LARGO"
            labelColor="#FF0033"
            icon={<YouTubeIcon />}
            typed={url2}
            active={false}
            done={url2Done}
            cursor={false}
          />
        </div>

        <div style={{ flex: 1, display: 'flex', justifyContent: 'flex-end', alignItems: 'flex-end' }}>
          <div style={{ position: 'relative' }}>
            {/* Ripple */}
            {showRipple && (
              <div style={{
                position: 'absolute',
                top: '50%', left: '50%',
                width: 80, height: 80,
                marginLeft: -40, marginTop: -40,
                borderRadius: '50%',
                background: 'rgba(245,158,11,0.45)',
                transform: `translate(-50%, -50%) scale(${1 + rippleProgress * 4})`,
                opacity: 1 - rippleProgress,
                pointerEvents: 'none',
                zIndex: 0,
              }} />
            )}
            {/* In-product CTA — neutral so it doesn't compete with Act 5 hero CTA */}
            <div style={{
              padding: '16px 32px',
              background: pressed ? 'rgba(234,88,12,0.18)' : 'rgba(234,88,12,0.08)',
              border: '1.5px solid rgba(234,88,12,0.7)',
              borderRadius: 12,
              fontFamily: 'Inter, system-ui, sans-serif',
              fontSize: 22, fontWeight: 700, color: '#F59E0B',
              boxShadow: pressed
                ? '0 0 24px rgba(234,88,12,0.4)'
                : '0 4px 16px rgba(0,0,0,0.4)',
              opacity: buttonProgress,
              transform: `translateY(${(1 - buttonProgress) * 10}px) scale(${btnScale})`,
              filter: `brightness(${btnBrightness})`,
              pointerEvents: buttonProgress < 0.5 ? 'none' : 'auto',
              position: 'relative',
              zIndex: 1,
              transition: 'background 80ms linear, box-shadow 80ms linear',
            }}>
              Detectar la chispa →
            </div>
            {/* Click cursor — appears, hovers, taps */}
            {showClickCursor && buttonProgress > 0.5 && (
              <svg
                width="28" height="28" viewBox="0 0 28 28"
                style={{
                  position: 'absolute',
                  right: 20,
                  bottom: 4,
                  pointerEvents: 'none',
                  opacity: cursorIn,
                  transform: `translate(${(1 - cursorIn) * -28}px, ${(1 - cursorIn) * 28}px) scale(${pressed ? 0.85 : 1})`,
                  zIndex: 2,
                  filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.5))',
                  transition: 'transform 80ms ease-out',
                }}
              >
                <path d="M5 2 L5 22 L11 17 L14.5 24 L17 22.5 L13.5 16 L21 16 Z" fill="#fff" stroke="#000" strokeWidth="1.2" strokeLinejoin="round"/>
              </svg>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

function URLRow({ label, labelColor, icon, typed, active, done, cursor }) {
  const borderColor = active ? '#EA580C' : done ? 'rgba(34,197,94,0.5)' : 'rgba(255,255,255,0.08)';
  const glow = active ? '0 0 32px rgba(234,88,12,0.3)' : 'none';
  return (
    <div>
      <div style={{
        fontFamily: 'JetBrains Mono, monospace',
        fontSize: 12,
        color: labelColor,
        letterSpacing: '0.16em',
        fontWeight: 700,
        marginBottom: 8,
        lineHeight: 1,
      }}>
        {label}
      </div>
      <div style={{
        width: '100%',
        height: 76,
        boxSizing: 'border-box',
        display: 'flex', alignItems: 'center', gap: 16,
        padding: '0 26px',
        background: '#0a0a0a',
        border: `2px solid ${borderColor}`,
        borderRadius: 14,
        color: '#fff',
        transition: 'border-color 200ms',
        boxShadow: glow,
        overflow: 'hidden',
      }}>
        <div style={{ flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', width: 28, height: 28 }}>{icon}</div>
        <span style={{
          flex: 1,
          whiteSpace: 'nowrap',
          overflow: 'hidden',
          textOverflow: 'clip',
          fontFamily: 'JetBrains Mono, monospace',
          fontSize: 24,
          lineHeight: 1,
          display: 'inline-flex',
          alignItems: 'center',
        }}>
          <span>{typed}</span>
          <span style={{
            color: '#EA580C',
            visibility: active && cursor ? 'visible' : 'hidden',
            display: 'inline-block',
            width: 14,
            textAlign: 'left',
          }}>▋</span>
        </span>
        <div style={{ flexShrink: 0, width: 22, height: 22, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {done && (
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#22c55e" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="4 12 10 18 20 6"/>
            </svg>
          )}
        </div>
      </div>
    </div>
  );
}

function TwitchIcon() {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill="#9146FF">
      <path d="M2.149 0l-1.612 4.119v16.836h5.731v3.045h3.224l3.045-3.045h4.657l6.269-6.269v-14.686h-21.314zm19.164 13.612l-3.582 3.582h-5.731l-3.045 3.045v-3.045h-4.836v-15.045h17.194v11.463zm-3.582-7.343v6.262h-2.149v-6.262h2.149zm-5.731 0v6.262h-2.149v-6.262h2.149z"/>
    </svg>
  );
}

function YouTubeIcon() {
  return (
    <svg width="26" height="22" viewBox="0 0 24 18" fill="#FF0033">
      <path d="M23.498 2.815c-.276-1.034-1.087-1.847-2.117-2.123C19.505.225 12 .225 12 .225s-7.505 0-9.381.467C1.589.968.776 1.781.502 2.815.04 4.694.04 8.6.04 8.6s0 3.906.462 5.785c.275 1.034 1.087 1.847 2.117 2.123 1.876.467 9.381.467 9.381.467s7.505 0 9.381-.467c1.03-.276 1.841-1.089 2.117-2.123.462-1.879.462-5.785.462-5.785s0-3.906-.462-5.785zM9.602 12.225V4.975L15.83 8.6l-6.228 3.625z"/>
    </svg>
  );
}

function PhaseAnalysis({ t }) {
  // 3s phase (4.5-7.5 absolute). Hold until 2.5, fade 2.5-3.0.
  const opacity = t < 0.3 ? Easing.easeOutCubic(t / 0.3) : t > 2.5 ? Easing.easeInCubic(clamp((3.0 - t) / 0.5, 0, 1)) : 1;

  // Animated waveform with detection markers
  const bars = [];
  for (let i = 0; i < 80; i++) {
    const phase = i * 0.4 + t * 3;
    const h = 10 + Math.abs(Math.sin(phase)) * 50 + Math.abs(Math.sin(phase * 1.3)) * 30;
    bars.push(h);
  }

  // Detection markers at specific positions; appear progressively
  const markers = [
    { pos: 18, label: 'grito',    appear: 0.6 },
    { pos: 36, label: 'reacción', appear: 1.2 },
    { pos: 52, label: 'giro',     appear: 1.8 },
    { pos: 68, label: 'climax',   appear: 2.4 },
  ];

  // Scanning line position — scaled to 3s phase
  const scanX = (t / 3.0) * 100;

  return (
    <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 28, opacity }}>
      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 16, color: '#F59E0B', letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 600 }}>
        paso 2 · IA analiza tu directo
      </div>
      <div style={{ width: 1100, height: 280, position: 'relative', background: 'rgba(255,255,255,0.02)', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 16, padding: 24 }}>
        {/* Waveform */}
        <div style={{ position: 'absolute', left: 24, right: 24, top: 80, bottom: 80, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 1 }}>
          {bars.map((h, i) => {
            const isNearMarker = markers.some(m => Math.abs(m.pos - i) < 3 && t > m.appear);
            return (
              <div key={i} style={{
                width: 10,
                height: h,
                background: isNearMarker ? '#EA580C' : 'linear-gradient(180deg, #F59E0B 0%, #EA580C 100%)',
                borderRadius: 2,
                boxShadow: isNearMarker ? '0 0 12px rgba(234,88,12,0.8)' : 'none',
              }} />
            );
          })}
        </div>
        {/* Scanning line */}
        <div style={{ position: 'absolute', top: 60, bottom: 60, left: `calc(24px + ${scanX * 10.5}px)`, width: 2, background: 'linear-gradient(180deg, transparent, #F59E0B, transparent)', boxShadow: '0 0 20px #F59E0B' }} />

        {/* Markers */}
        {markers.map((m, i) => {
          if (t < m.appear) return null;
          const opacity = Math.min(1, (t - m.appear) * 3);
          return (
            <div key={i} style={{
              position: 'absolute',
              top: 18,
              left: `calc(24px + ${m.pos * 13.4}px - 30px)`,
              width: 60,
              opacity,
            }}>
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
                <div style={{
                  padding: '4px 10px',
                  background: '#EA580C',
                  borderRadius: 999,
                  fontFamily: 'JetBrains Mono, monospace',
                  fontSize: 10,
                  color: '#fff',
                  letterSpacing: '0.05em',
                  textTransform: 'uppercase',
                }}>{m.label}</div>
                <svg width="14" height="14" viewBox="0 0 14 14"><path d="M7 0 L4 6 L6 6 L4 14 L10 5 L7 5 Z" fill="#F59E0B" /></svg>
              </div>
            </div>
          );
        })}

        {/* Bottom label */}
        <div style={{ position: 'absolute', left: 24, bottom: 24, fontFamily: 'JetBrains Mono, monospace', fontSize: 16, color: 'rgba(255,255,255,0.5)' }}>
          analizando audio + reacciones · 03:24:18
        </div>
        <div style={{ position: 'absolute', right: 24, bottom: 24, fontFamily: 'JetBrains Mono, monospace', fontSize: 16, color: '#F59E0B', display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: 4, background: '#F59E0B', boxShadow: '0 0 12px #F59E0B' }} />
          {markers.filter(m => t > m.appear).length} momentos detectados
        </div>
      </div>
    </div>
  );
}

function PhaseClip({ t }) {
  // 3.5s phase (7.5-11.0 absolute). Hold until 3.0, fade 3.0-3.5.
  const opacity = t < 0.3 ? Easing.easeOutCubic(t / 0.3) : t > 3.0 ? Easing.easeInCubic(clamp((3.5 - t) / 0.5, 0, 1)) : 1;

  // Subtitle bake-in
  const subProgress = Math.min(1, Math.max(0, (t - 0.6) / 0.5));
  // Caption rotation cycles through 3 subtitle styles to show variety
  const cap = Math.min(2, Math.floor(Math.max(0, t - 0.7) / 0.65));
  const captions = ['¡NO J*DAS!', 'NO ME LO CREO', 'ESTO ES BRUTAL'];
  const captionText = captions[cap];

  // Subtle "now generating" pulse on the clip frame
  const framePulse = 0.5 + Math.sin(t * 3.2) * 0.5;

  return (
    <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 24, opacity }}>
      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 18, color: '#F59E0B', letterSpacing: '0.18em', textTransform: 'uppercase', fontWeight: 600 }}>
        paso 3 · clip vertical listo
      </div>
      <div style={{ display: 'flex', gap: 60, alignItems: 'center' }}>
        {/* Left: phone-mockup-style vertical clip */}
        <div style={{
          width: 320, height: 568,
          borderRadius: 28,
          background: 'linear-gradient(135deg, #2a1810 0%, #0a0a0a 100%)',
          border: '3px solid rgba(234,88,12,0.55)',
          boxShadow: `0 0 ${50 + framePulse * 30}px rgba(234,88,12,0.35)`,
          position: 'relative',
          overflow: 'hidden',
        }}>
          {/* Fake video frame — a centered "face" silhouette + waveform feet */}
          <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <div style={{ width: 180, height: 240, background: 'radial-gradient(ellipse at 50% 40%, rgba(245,158,11,0.18) 0%, rgba(234,88,12,0.06) 60%, transparent 100%)', borderRadius: '50%' }} />
          </div>

          {/* Top badge */}
          <div style={{ position: 'absolute', top: 18, left: 18, padding: '6px 14px', background: 'rgba(0,0,0,0.7)', borderRadius: 6, fontFamily: 'JetBrains Mono, monospace', fontSize: 16, color: '#F59E0B', letterSpacing: '0.08em', fontWeight: 700 }}>
            9:16 · 28s
          </div>
          <div style={{ position: 'absolute', top: 18, right: 18, padding: '6px 14px', background: 'rgba(234,88,12,0.18)', border: '1px solid rgba(234,88,12,0.5)', borderRadius: 999, fontFamily: 'JetBrains Mono, monospace', fontSize: 16, color: '#F59E0B', letterSpacing: '0.08em', fontWeight: 700, display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ display: 'inline-block', width: 7, height: 7, borderRadius: 4, background: '#EA580C' }} />
            renderizado
          </div>

          {/* Burned subtitle */}
          {subProgress > 0 && (
            <div style={{
              position: 'absolute',
              bottom: 80,
              left: '50%',
              transform: `translateX(-50%) scale(${0.85 + subProgress * 0.15})`,
              opacity: subProgress,
              padding: '10px 18px',
              background: '#fff',
              color: '#000',
              fontFamily: 'Inter, system-ui, sans-serif',
              fontSize: 26,
              fontWeight: 900,
              letterSpacing: '-0.01em',
              textTransform: 'uppercase',
              borderRadius: 8,
              whiteSpace: 'nowrap',
              boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
            }}>
              {captionText}
            </div>
          )}

          {/* Progress dots at bottom */}
          <div style={{ position: 'absolute', bottom: 28, left: 0, right: 0, display: 'flex', justifyContent: 'center', gap: 6 }}>
            {[0, 1, 2].map(i => (
              <div key={i} style={{
                width: i === cap ? 28 : 8,
                height: 8,
                borderRadius: 4,
                background: i === cap ? '#F59E0B' : 'rgba(255,255,255,0.3)',
                transition: 'width 200ms',
              }} />
            ))}
          </div>
        </div>

        {/* Right: feature checklist */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 20, maxWidth: 420 }}>
          <ClipFeature delay={0.0} t={t} icon="✂️" label="Cortado 9:16" desc="recorte automático centrado en el rostro" />
          <ClipFeature delay={0.3} t={t} icon="📝" label="Subtítulos quemados" desc="alto contraste, estilo broadcast" />
          <ClipFeature delay={0.6} t={t} icon="🎚️" label="Audio normalizado" desc="-14 LUFS, sin distorsión" />
          <ClipFeature delay={0.9} t={t} icon="🎬" label="Hook en frame 0" desc="los 2 primeros segundos enganchan" />
        </div>
      </div>
    </div>
  );
}

function ClipFeature({ delay, t, icon, label, desc }) {
  const local = t - delay;
  const ease = Easing.easeOutCubic(clamp(local * 4, 0, 1));
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 16,
      padding: '14px 18px',
      background: 'rgba(255,255,255,0.04)',
      border: '1px solid rgba(255,255,255,0.08)',
      borderRadius: 12,
      opacity: ease,
      transform: `translateX(${(1 - ease) * 20}px)`,
    }}>
      <div style={{ fontSize: 28, lineHeight: 1, width: 40, textAlign: 'center' }}>{icon}</div>
      <div style={{ fontFamily: 'Inter, system-ui, sans-serif' }}>
        <div style={{ fontSize: 18, fontWeight: 700, color: '#fff', letterSpacing: '-0.01em', lineHeight: 1.2 }}>{label}</div>
        <div style={{ fontSize: 14, color: 'rgba(255,255,255,0.55)', marginTop: 3, lineHeight: 1.3 }}>{desc}</div>
      </div>
    </div>
  );
}

// ── Phase 4 · Publica adaptado a cada red (4s, merged adapt+publish) ────────
function PhaseAdaptPublish({ t }) {
  const opacity = t < 0.3 ? Easing.easeOutCubic(t / 0.3) : t > 3.5 ? Easing.easeInCubic(clamp((4.0 - t) / 0.5, 0, 1)) : 1;
  const headlineProgress = Easing.easeOutCubic(clamp(t / 0.5, 0, 1));

  const cards = [
    {
      label: 'YouTube Shorts',
      sub: 'estética limpia',
      accent: '#FF0033',
      icon: <PubYouTube />,
      delay: 0.4,
      renderClip: () => (
        <div style={{ position: 'absolute', bottom: 22, left: '50%', transform: 'translateX(-50%)', padding: '5px 10px', background: 'rgba(255,255,255,0.92)', color: '#000', fontFamily: 'Inter, system-ui, sans-serif', fontSize: 13, fontWeight: 500, borderRadius: 3, whiteSpace: 'nowrap' }}>
          que pasó después...
        </div>
      ),
    },
    {
      label: 'TikTok',
      sub: 'bold · alto contraste',
      accent: '#25F4EE',
      icon: <PubTikTok />,
      delay: 0.65,
      renderClip: () => (
        <div style={{ position: 'absolute', bottom: 28, left: '50%', transform: 'translateX(-50%) rotate(-2deg)', padding: '7px 12px', background: '#fff', color: '#000', fontFamily: 'Inter, system-ui, sans-serif', fontSize: 18, fontWeight: 900, letterSpacing: '-0.01em', textTransform: 'uppercase', borderRadius: 5, whiteSpace: 'nowrap', boxShadow: '0 4px 12px rgba(0,0,0,0.5)' }}>
          ¿QUÉ PASÓ?!
        </div>
      ),
    },
    {
      label: 'Instagram Reels',
      sub: 'hook visual fijo',
      accent: '#E1306C',
      icon: <PubInstagram />,
      delay: 0.9,
      renderClip: () => (
        <div style={{ position: 'absolute', bottom: 26, left: '50%', transform: 'translateX(-50%)', padding: '6px 12px', background: 'linear-gradient(90deg, #F58529, #DD2A7B, #8134AF)', color: '#fff', fontFamily: 'Inter, system-ui, sans-serif', fontSize: 14, fontWeight: 800, letterSpacing: '-0.01em', borderRadius: 5, whiteSpace: 'nowrap', boxShadow: '0 4px 12px rgba(225,48,108,0.4)' }}>
          ¿QUÉ PASÓ AQUÍ?
        </div>
      ),
    },
  ];

  return (
    <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 36, opacity, padding: '60px 60px' }}>
      <div style={{
        textAlign: 'center',
        opacity: headlineProgress,
        transform: `translateY(${(1 - headlineProgress) * 16}px)`,
      }}>
        <div style={{
          fontFamily: 'JetBrains Mono, monospace',
          fontSize: 18,
          color: '#F59E0B',
          letterSpacing: '0.18em',
          textTransform: 'uppercase',
          fontWeight: 600,
          marginBottom: 12,
        }}>
          paso 4 · publica adaptado a cada red
        </div>
        <div style={{
          fontFamily: 'Inter, system-ui, sans-serif',
          fontSize: 96,
          fontWeight: 900,
          color: '#fff',
          letterSpacing: '-0.04em',
          lineHeight: 0.95,
          textTransform: 'uppercase',
          textShadow: '0 8px 40px rgba(234,88,12,0.25)',
        }}>
          publica mientras <span style={{ color: '#F59E0B' }}>duermes</span>.
        </div>
      </div>

      <div style={{ display: 'flex', gap: 28 }}>
        {cards.map((c, i) => {
          const local = t - c.delay;
          const slide = Easing.easeOutCubic(clamp(local * 2.4, 0, 1));
          const done = local > 0.8;
          const doneIn = Easing.easeOutBack(clamp((local - 0.8) / 0.3, 0, 1));
          return (
            <div key={i} style={{
              width: 280, height: 420,
              background: '#0a0a0a',
              borderRadius: 18,
              border: `1px solid ${c.accent}55`,
              position: 'relative',
              overflow: 'hidden',
              boxShadow: `0 0 30px ${c.accent}22`,
              transform: `translateY(${(1 - slide) * 30}px)`,
              opacity: local < 0 ? 0 : slide,
            }}>
              <div style={{ padding: '14px 18px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontFamily: 'JetBrains Mono, monospace' }}>
                <div style={{ fontSize: 14, color: c.accent, letterSpacing: '0.08em', fontWeight: 700 }}>{c.label}</div>
                {done && (
                  <div style={{
                    width: 30, height: 30, borderRadius: 15, background: '#22c55e',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    transform: `scale(${doneIn})`,
                    boxShadow: '0 0 16px rgba(34,197,94,0.6)',
                  }}>
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="4 12 10 18 20 6"/></svg>
                  </div>
                )}
              </div>
              <div style={{ position: 'absolute', top: 52, left: 18, right: 18, bottom: 64, background: 'linear-gradient(135deg, #2a1810 0%, #000 100%)', borderRadius: 12, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <div style={{ opacity: 0.5, transform: 'scale(0.55)' }}>{c.icon}</div>
                {c.renderClip()}
              </div>
              <div style={{ position: 'absolute', bottom: 18, left: 18, right: 18, fontFamily: 'JetBrains Mono, monospace', fontSize: 16, color: 'rgba(255,255,255,0.5)', letterSpacing: '0.06em', textTransform: 'uppercase', textAlign: 'center' }}>{c.sub}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function PubYouTube() {
  return (
    <svg width="92" height="68" viewBox="0 0 24 18" fill="#FF0033">
      <path d="M23.498 2.815c-.276-1.034-1.087-1.847-2.117-2.123C19.505.225 12 .225 12 .225s-7.505 0-9.381.467C1.589.968.776 1.781.502 2.815.04 4.694.04 8.6.04 8.6s0 3.906.462 5.785c.275 1.034 1.087 1.847 2.117 2.123 1.876.467 9.381.467 9.381.467s7.505 0 9.381-.467c1.03-.276 1.841-1.089 2.117-2.123.462-1.879.462-5.785.462-5.785s0-3.906-.462-5.785zM9.602 12.225V4.975L15.83 8.6l-6.228 3.625z"/>
    </svg>
  );
}
function PubTikTok() {
  return (
    <svg width="80" height="92" viewBox="0 0 24 24">
      <path d="M19.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-5.2 1.74 2.89 2.89 0 0 1 2.31-4.64 2.93 2.93 0 0 1 .88.13V9.4a6.84 6.84 0 0 0-1-.05A6.33 6.33 0 0 0 5.8 20.1a6.34 6.34 0 0 0 10.86-4.43v-7a8.16 8.16 0 0 0 4.77 1.52v-3.4a4.85 4.85 0 0 1-1.84-.1z" fill="#25F4EE"/>
      <path d="M17.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-5.2 1.74 2.89 2.89 0 0 1 2.31-4.64 2.93 2.93 0 0 1 .88.13V9.4a6.84 6.84 0 0 0-1-.05A6.33 6.33 0 0 0 3.8 20.1a6.34 6.34 0 0 0 10.86-4.43v-7a8.16 8.16 0 0 0 4.77 1.52v-3.4a4.85 4.85 0 0 1-1.84-.1z" fill="#FE2C55" transform="translate(2,0)" opacity="0.85"/>
      <path d="M18.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-5.2 1.74 2.89 2.89 0 0 1 2.31-4.64 2.93 2.93 0 0 1 .88.13V9.4a6.84 6.84 0 0 0-1-.05A6.33 6.33 0 0 0 4.8 20.1a6.34 6.34 0 0 0 10.86-4.43v-7a8.16 8.16 0 0 0 4.77 1.52v-3.4a4.85 4.85 0 0 1-1.84-.1z" fill="#fff"/>
    </svg>
  );
}
function PubInstagram() {
  return (
    <svg width="84" height="84" viewBox="0 0 24 24">
      <defs>
        <linearGradient id="ig-grad" x1="0%" y1="0%" x2="100%" y2="100%">
          <stop offset="0%" stopColor="#F58529"/>
          <stop offset="35%" stopColor="#DD2A7B"/>
          <stop offset="70%" stopColor="#8134AF"/>
          <stop offset="100%" stopColor="#515BD4"/>
        </linearGradient>
      </defs>
      <rect x="2" y="2" width="20" height="20" rx="5.5" fill="url(#ig-grad)"/>
      <circle cx="12" cy="12" r="4.5" fill="none" stroke="#fff" strokeWidth="2"/>
      <circle cx="17.5" cy="6.5" r="1.3" fill="#fff"/>
    </svg>
  );
}

function Subtitles({ t }) {
  // Cues aligned with new 15s act-local timeline
  const cues = [
    { t: 1.5, end: 4.5,  es: 'Pega tu URL · Twitch o YouTube.',         en: 'Paste your URL · Twitch or YouTube.' },
    { t: 4.5, end: 7.5,  es: 'La IA detecta los momentos virales.',     en: 'AI spots the viral moments.' },
    { t: 7.5, end: 11.0, es: 'Corta, encuadra y quema subtítulos.',     en: 'Cuts, frames and burns subtitles.' },
    { t: 11.0, end: 15.0, es: 'Publica adaptado a cada red.',           en: 'Publishes adapted to each network.' },
  ];
  return <CueLayer cues={cues} t={t} />;
}

window.Act2Solution = Act2Solution;
