// formats.jsx — Premium invite formats: dramatic, immediately recognizable
const { useState: useStateF, useEffect: useEffectF, useRef: useRefF } = React;

const FORMATS = [
  { id: 'statico',  name: 'Statico',   icon: '📄', desc: 'Immagine PNG da mandare su WhatsApp' },
  { id: 'animato',  name: 'Animato',   icon: '✨', desc: 'Età che pulsa, palloncini, candelina viva' },
  { id: 'scartalo', name: 'Scartalo',  icon: '🎁', desc: 'Tocca il regalo: il fiocco vola via, esplode la festa, esce l\u2019invito' },
  { id: 'video',    name: 'Mini-video',icon: '🎬', desc: '14 sec drammatici con musica · finale wow' },
];

// ─────────────────────────────────────────────────────────────
// ANIMATO — giant pulsing age, balloons w/ name, candle on top
// ─────────────────────────────────────────────────────────────
function FormatAnimato({ themeId, layoutId, data, paused = false }) {
  const theme = THEMES[themeId];
  const p = theme.palette;
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', background: p.bg }}>
      {/* base invitation behind, dimmed slightly */}
      <div style={{ position: 'absolute', inset: 0, opacity: 0.55 }}>
        <Invitation themeId={themeId} layoutId={layoutId} data={data} />
      </div>
      {/* darkening overlay so foreground pops */}
      <div style={{ position: 'absolute', inset: 0, background: `radial-gradient(ellipse at 50% 50%, transparent 0%, ${theme.dark ? '#000' : p.ink}33 100%)` }} />

      {/* GIANT PULSING AGE — center stage */}
      <div style={{
        position: 'absolute', left: '50%', top: '42%', transform: 'translate(-50%, -50%)',
        width: '60%', aspectRatio: '1 / 1', borderRadius: '50%',
        background: `radial-gradient(circle at 30% 30%, ${p.accent}, ${p.primary})`,
        boxShadow: `0 12px 40px ${p.ink}55, inset -8px -12px 20px rgba(0,0,0,0.18), inset 8px 8px 14px rgba(255,255,255,0.4)`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        animation: paused ? 'none' : 'fmt-age-pulse 1.6s ease-in-out infinite',
      }}>
        <div style={{
          fontFamily: 'DM Serif Display, serif', fontStyle: 'italic',
          fontSize: '42cqw', lineHeight: 0.85, color: '#fff',
          textShadow: `0 4px 0 ${p.ink}66, 0 8px 24px rgba(0,0,0,0.4)`,
        }}>
          {data.eta}
        </div>
        {/* Candle on top of age */}
        <div style={{ position: 'absolute', top: '-6%', left: '50%', transform: 'translateX(-50%)' }}>
          <div style={{ width: 6, height: 22, background: '#FBE6C5', margin: '0 auto', borderRadius: 1 }}/>
          <div style={{
            position: 'absolute', top: -16, left: '50%', transform: 'translateX(-50%)',
            width: 14, height: 20,
            background: 'radial-gradient(ellipse at 50% 70%, #FFE066 0%, #FF9A3D 60%, transparent 90%)',
            borderRadius: '50% 50% 30% 30% / 70% 70% 30% 30%',
            animation: paused ? 'none' : 'fmt-flame 0.32s ease-in-out infinite alternate',
            filter: 'drop-shadow(0 0 8px #FF9A3Daa)',
          }}/>
        </div>
      </div>

      {/* Name — typed across top with hand-drawn strokes underneath */}
      <div style={{ position: 'absolute', left: '6%', right: '6%', top: '8%', textAlign: 'center' }}>
        <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '0.3em', color: p.ink, opacity: 0.75 }}>
          OGGI · FESTEGGIA
        </div>
        <div style={{
          marginTop: 6,
          fontFamily: 'DM Serif Display, serif', fontStyle: 'italic',
          fontSize: 38, lineHeight: 1, color: p.ink,
          animation: paused ? 'none' : 'fmt-name-bob 3.2s ease-in-out infinite',
          display: 'inline-block',
        }}>
          {data.nome}
        </div>
      </div>

      {/* Balloons rising — bigger, more, varied */}
      {!paused && (
        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 4 }}>
          {[
            { c: p.primary,   x: 4,  s: 36, d: 0 },
            { c: p.secondary, x: 14, s: 28, d: 1.4 },
            { c: p.accent,    x: 88, s: 32, d: 0.6 },
            { c: '#FF9FCC',   x: 78, s: 26, d: 2.2 },
            { c: p.primary,   x: 92, s: 22, d: 3.2 },
            { c: p.secondary, x: 8,  s: 24, d: 4.0 },
          ].map((b, i) => (
            <div key={i} style={{
              position: 'absolute',
              left: `${b.x}%`, bottom: -50,
              animation: `fmt-balloon ${7 + i * 0.4}s ${b.d}s linear infinite`,
            }}>
              <div style={{
                width: b.s, height: b.s * 1.25,
                borderRadius: '50% 50% 50% 50% / 60% 60% 40% 40%',
                background: `radial-gradient(ellipse at 30% 30%, ${b.c}ee, ${b.c})`,
                position: 'relative',
                boxShadow: `inset -4px -3px 6px rgba(0,0,0,0.22), 0 4px 10px ${p.ink}33`,
              }}>
                <div style={{
                  position: 'absolute', top: '20%', left: '24%',
                  width: '20%', height: '24%', background: 'rgba(255,255,255,0.6)',
                  borderRadius: '50%', filter: 'blur(1px)',
                }} />
              </div>
              <svg width="2" height="40" style={{ display: 'block', margin: '0 auto' }}>
                <path d="M1 0 Q 3 14, 1 26 T 1 40" stroke={p.ink} strokeWidth="1" fill="none" opacity="0.4"/>
              </svg>
            </div>
          ))}
        </div>
      )}

      {/* Confetti rain — bigger pieces */}
      {!paused && (
        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 5 }}>
          {Array.from({ length: 26 }).map((_, i) => {
            const colors = [p.primary, p.secondary, p.accent, '#FFD93D', '#FF6B9D', p.light];
            return (
              <div key={i} style={{
                position: 'absolute',
                left: `${(i * 13.7) % 100}%`,
                top: -20,
                width: 8 + (i % 3) * 3,
                height: 14 + (i % 3) * 5,
                background: colors[i % colors.length],
                borderRadius: i % 2 === 0 ? 1.5 : '50%',
                animation: `fmt-confetti ${3 + (i % 5) * 0.4}s ${(i * 0.18) % 4}s linear infinite`,
                transform: `rotate(${i * 23}deg)`,
                boxShadow: '0 1px 3px rgba(0,0,0,0.18)',
              }} />
            );
          })}
        </div>
      )}

      {/* Sparkles trail */}
      {!paused && (
        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 6 }}>
          {Array.from({ length: 14 }).map((_, i) => (
            <div key={i} style={{
              position: 'absolute',
              left: `${10 + (i * 11) % 80}%`,
              top: `${20 + (i * 9) % 60}%`,
              width: 12 + (i % 3) * 4,
              height: 12 + (i % 3) * 4,
              animation: `fmt-sparkle 1.4s ${i * 0.16}s ease-in-out infinite`,
            }}>
              <svg viewBox="0 0 24 24" width="100%" height="100%">
                <path d="M12 2 L13 11 L22 12 L13 13 L12 22 L11 13 L2 12 L11 11 Z" fill={p.accent}/>
              </svg>
            </div>
          ))}
        </div>
      )}

      {/* Bottom details slab */}
      <div style={{
        position: 'absolute', left: '6%', right: '6%', bottom: '5%',
        background: 'rgba(255,255,255,0.96)',
        borderRadius: 16, padding: '12px 16px',
        boxShadow: `0 10px 24px ${p.ink}33`,
        fontSize: 11, color: p.ink, fontWeight: 700,
        display: 'grid', gridTemplateColumns: 'auto 1fr', columnGap: 10, rowGap: 4,
        zIndex: 3,
      }}>
        <span style={{ opacity: 0.55 }}>QUANDO</span>
        <span>{formatVideoDate(data.data)} · {data.ora}</span>
        <span style={{ opacity: 0.55 }}>DOVE</span>
        <span>{data.luogo}</span>
      </div>

      <style>{`
        @keyframes fmt-confetti {
          0%   { transform: translateY(0) rotate(0deg); }
          100% { transform: translateY(140%) rotate(720deg); }
        }
        @keyframes fmt-balloon {
          0%   { transform: translateY(0) translateX(0); opacity: 0; }
          8%   { opacity: 1; }
          92%  { opacity: 1; }
          100% { transform: translateY(-130%) translateX(8px); opacity: 0; }
        }
        @keyframes fmt-sparkle {
          0%, 100% { opacity: 0; transform: scale(0.4) rotate(0deg); }
          50%      { opacity: 1; transform: scale(1.2) rotate(180deg); }
        }
        @keyframes fmt-age-pulse {
          0%, 100% { transform: translate(-50%, -50%) scale(1); }
          50%      { transform: translate(-50%, -50%) scale(1.05); }
        }
        @keyframes fmt-name-bob {
          0%, 100% { transform: translateY(0) rotate(-1deg); }
          50%      { transform: translateY(-3px) rotate(1deg); }
        }
        @keyframes fmt-flame {
          from { transform: translateX(-50%) scaleY(1); }
          to   { transform: translateX(-50%) scaleY(1.18); }
        }
      `}</style>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SCARTALO — gift box that unwraps with explosion, invite pops out
// ─────────────────────────────────────────────────────────────
function FormatScartalo({ themeId, layoutId, data, paused = false }) {
  const [phase, setPhase] = useStateF('closed'); // closed → unwrapping → revealed
  const theme = THEMES[themeId];
  const p = theme.palette;

  useEffectF(() => {
    if (paused) return;
    let t1, t2;
    if (phase === 'closed') {
      t1 = setTimeout(() => setPhase('unwrapping'), 1800);
    } else if (phase === 'unwrapping') {
      t1 = setTimeout(() => setPhase('revealed'), 1400);
    } else if (phase === 'revealed') {
      t1 = setTimeout(() => setPhase('closed'), 5500);
    }
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [phase, paused]);

  const onTap = () => {
    if (phase === 'closed') setPhase('unwrapping');
    else if (phase === 'revealed') setPhase('closed');
  };

  const showLid = phase === 'closed';
  const lidLifted = phase !== 'closed';
  const showBox = phase !== 'revealed';
  const showInvite = phase === 'revealed';
  const showBurst = phase === 'unwrapping' || phase === 'revealed';

  return (
    <div onClick={onTap} style={{
      position: 'absolute', inset: 0, overflow: 'hidden', cursor: 'pointer',
      background: `radial-gradient(ellipse at 50% 60%, ${p.bg2} 0%, ${theme.dark ? '#0A0A14' : p.ink} 100%)`,
    }}>
      {/* Background glow during unwrap */}
      {showBurst && (
        <div style={{
          position: 'absolute', left: '50%', top: '50%',
          transform: 'translate(-50%, -50%)',
          width: '180%', aspectRatio: '1 / 1',
          background: `radial-gradient(circle, ${p.accent}aa 0%, ${p.primary}55 30%, transparent 60%)`,
          animation: 'fmt-godrays 1.4s ease-out forwards',
          pointerEvents: 'none',
        }}/>
      )}

      {/* Light rays */}
      {showBurst && (
        <div style={{
          position: 'absolute', left: '50%', top: '50%',
          transform: 'translate(-50%, -50%)',
          width: '200%', aspectRatio: '1 / 1',
          backgroundImage: `conic-gradient(from 0deg, transparent 0deg, ${p.accent}33 12deg, transparent 24deg, transparent 36deg, ${p.light}33 48deg, transparent 60deg, transparent 72deg, ${p.accent}33 84deg, transparent 96deg)`,
          animation: 'fmt-rays-spin 4s linear infinite',
          opacity: 0.7,
          pointerEvents: 'none',
        }}/>
      )}

      {/* Gift box */}
      {showBox && (
        <div style={{
          position: 'absolute', left: '50%', top: '54%',
          transform: 'translate(-50%, -50%)',
          width: '60%', aspectRatio: '1 / 1',
          animation: phase === 'closed' && !paused ? 'fmt-box-anticipation 1.8s ease-in-out' : 'none',
        }}>
          {/* Box shadow on floor */}
          <div style={{
            position: 'absolute', left: '5%', right: '5%', bottom: '-12%',
            height: '8%', background: '#000', opacity: 0.45,
            filter: 'blur(10px)', borderRadius: '50%',
          }}/>

          {/* Box body */}
          <div style={{
            position: 'absolute', left: 0, right: 0, top: '30%', bottom: 0,
            background: `linear-gradient(135deg, ${p.primary} 0%, ${p.secondary} 100%)`,
            borderRadius: 6,
            boxShadow: `inset -8px -10px 20px rgba(0,0,0,0.25), inset 6px 6px 12px rgba(255,255,255,0.2), 0 14px 30px rgba(0,0,0,0.4)`,
          }}>
            {/* Vertical ribbon on body */}
            <div style={{
              position: 'absolute', left: '50%', top: 0, bottom: 0,
              width: '14%', transform: 'translateX(-50%)',
              background: `linear-gradient(180deg, ${p.accent}, ${p.accent}dd)`,
              boxShadow: 'inset -2px 0 4px rgba(0,0,0,0.2), inset 2px 0 4px rgba(255,255,255,0.3)',
            }}/>
            {/* Sparkle on body */}
            <div style={{
              position: 'absolute', left: '15%', top: '20%',
              width: '20%', height: '15%',
              background: 'rgba(255,255,255,0.3)',
              borderRadius: '50%', filter: 'blur(8px)',
            }}/>
          </div>

          {/* Lid */}
          <div style={{
            position: 'absolute', left: '-4%', right: '-4%', top: '20%',
            height: '20%',
            background: `linear-gradient(135deg, ${p.primary} 0%, ${p.ink} 100%)`,
            borderRadius: 6,
            boxShadow: `inset -8px -6px 14px rgba(0,0,0,0.3), inset 6px 6px 10px rgba(255,255,255,0.2), 0 6px 14px rgba(0,0,0,0.4)`,
            transform: lidLifted ? 'translateY(-180%) rotate(-18deg)' : 'translateY(0) rotate(0)',
            transition: 'transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)',
            zIndex: 3,
          }}>
            {/* Vertical ribbon on lid */}
            <div style={{
              position: 'absolute', left: '50%', top: 0, bottom: 0,
              width: '13%', transform: 'translateX(-50%)',
              background: `linear-gradient(180deg, ${p.accent}, ${p.accent}dd)`,
            }}/>
          </div>

          {/* Bow */}
          <div style={{
            position: 'absolute', left: '50%', top: '14%',
            transform: lidLifted
              ? 'translate(-50%, -200%) rotate(720deg) scale(0.4)'
              : 'translate(-50%, 0) rotate(0deg) scale(1)',
            transition: 'transform 0.7s cubic-bezier(0.36, 0, 0.66, -0.56)',
            opacity: lidLifted ? 0 : 1,
            zIndex: 4,
            animation: showLid && !paused ? 'fmt-bow-bounce 1.6s ease-in-out infinite' : 'none',
          }}>
            <svg width="80" height="56" viewBox="0 0 80 56">
              <ellipse cx="20" cy="28" rx="18" ry="14" fill={p.accent} />
              <ellipse cx="60" cy="28" rx="18" ry="14" fill={p.accent} />
              <ellipse cx="20" cy="28" rx="10" ry="7" fill="rgba(0,0,0,0.18)" />
              <ellipse cx="60" cy="28" rx="10" ry="7" fill="rgba(0,0,0,0.18)" />
              <ellipse cx="20" cy="22" rx="8" ry="3" fill="rgba(255,255,255,0.4)" />
              <ellipse cx="60" cy="22" rx="8" ry="3" fill="rgba(255,255,255,0.4)" />
              <rect x="34" y="20" width="12" height="16" rx="2" fill={p.primary}/>
              <rect x="34" y="24" width="12" height="2" fill="rgba(0,0,0,0.2)"/>
            </svg>
          </div>

          {/* "Tocca per scoprire" hint */}
          {showLid && (
            <div style={{
              position: 'absolute', left: '50%', top: '110%',
              transform: 'translateX(-50%)',
              fontSize: 14, fontWeight: 800, letterSpacing: '0.15em',
              color: '#fff', textAlign: 'center', whiteSpace: 'nowrap',
              animation: !paused ? 'fmt-hint-pulse 1.4s ease-in-out infinite' : 'none',
              textShadow: '0 2px 8px rgba(0,0,0,0.6)',
            }}>
              ✨ TOCCA PER SCARTARE ✨
            </div>
          )}
        </div>
      )}

      {/* Confetti burst from box */}
      {showBurst && (
        <div style={{
          position: 'absolute', left: '50%', top: '50%',
          transform: 'translate(-50%, -50%)',
          width: 1, height: 1, pointerEvents: 'none', zIndex: 5,
        }}>
          {Array.from({ length: 40 }).map((_, i) => {
            const colors = [p.primary, p.secondary, p.accent, '#FFD93D', '#FF6B9D', '#fff'];
            const angle = (i / 40) * Math.PI * 2;
            const dist = 140 + (i % 4) * 40;
            const dx = Math.cos(angle) * dist;
            const dy = Math.sin(angle) * dist;
            return (
              <div key={i} style={{
                position: 'absolute', left: 0, top: 0,
                width: 8 + (i % 3) * 3, height: 14 + (i % 3) * 4,
                background: colors[i % colors.length],
                borderRadius: i % 2 === 0 ? 1.5 : '50%',
                animation: `fmt-burst 1.4s ${i * 0.01}s cubic-bezier(0.16, 1, 0.3, 1) forwards`,
                '--dx': `${dx}px`,
                '--dy': `${dy}px`,
              }} />
            );
          })}
        </div>
      )}

      {/* Stars trail */}
      {showBurst && (
        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 5 }}>
          {Array.from({ length: 14 }).map((_, i) => (
            <div key={i} style={{
              position: 'absolute',
              left: `${10 + (i * 11) % 80}%`,
              top: `${15 + (i * 9) % 70}%`,
              width: 16 + (i % 3) * 6,
              height: 16 + (i % 3) * 6,
              animation: `fmt-star-twinkle 1.6s ${i * 0.07}s ease-out forwards`,
            }}>
              <svg viewBox="0 0 24 24" width="100%" height="100%">
                <path d="M12 2 L13 11 L22 12 L13 13 L12 22 L11 13 L2 12 L11 11 Z" fill={i % 2 === 0 ? p.accent : '#fff'}/>
              </svg>
            </div>
          ))}
        </div>
      )}

      {/* Invitation reveal */}
      {showInvite && (
        <>
          <div style={{
            position: 'absolute', left: '8%', right: '8%', top: '6%', bottom: '6%',
            borderRadius: 14, overflow: 'hidden',
            boxShadow: `0 30px 80px rgba(0,0,0,0.5), 0 0 0 6px ${p.accent}, 0 0 60px ${p.accent}aa`,
            animation: 'fmt-invite-rise 0.9s cubic-bezier(0.34, 1.56, 0.64, 1) both',
            zIndex: 6,
          }}>
            <Invitation themeId={themeId} layoutId={layoutId} data={data} />
            {/* shine sweep */}
            <div style={{
              position: 'absolute', inset: 0,
              background: 'linear-gradient(105deg, transparent 30%, rgba(255,255,255,0.5) 50%, transparent 70%)',
              animation: 'fmt-shine-sweep 1.6s 0.4s ease-out',
              pointerEvents: 'none', mixBlendMode: 'overlay',
            }}/>
          </div>
          <div style={{
            position: 'absolute', left: 0, right: 0, bottom: 14, textAlign: 'center',
            fontSize: 11, color: '#fff', opacity: 0.7, fontWeight: 700, letterSpacing: '0.1em',
            zIndex: 7, pointerEvents: 'none',
          }}>
            ✨ TOCCA PER RICHIUDERE
          </div>
        </>
      )}

      <style>{`
        @keyframes fmt-bow-bounce {
          0%, 100% { transform: translate(-50%, 0) rotate(-3deg) scale(1); }
          50%      { transform: translate(-50%, -4px) rotate(3deg) scale(1.04); }
        }
        @keyframes fmt-box-anticipation {
          0%, 100%       { transform: translate(-50%, -50%) rotate(0deg) scale(1); }
          25%, 75%       { transform: translate(-50%, -50%) rotate(-2deg) scale(1.02); }
          50%            { transform: translate(-50%, -50%) rotate(2deg) scale(1.02); }
        }
        @keyframes fmt-hint-pulse {
          0%, 100% { opacity: 0.7; transform: translateX(-50%) scale(1); }
          50%      { opacity: 1;   transform: translateX(-50%) scale(1.06); }
        }
        @keyframes fmt-burst {
          0%   { transform: translate(0, 0) rotate(0deg) scale(0.4); opacity: 0; }
          10%  { opacity: 1; }
          100% { transform: translate(var(--dx), var(--dy)) rotate(720deg) scale(1); opacity: 0; }
        }
        @keyframes fmt-star-twinkle {
          0%   { opacity: 0; transform: scale(0.2) rotate(0deg); }
          40%  { opacity: 1; transform: scale(1.4) rotate(180deg); }
          100% { opacity: 0; transform: scale(0.6) rotate(360deg); }
        }
        @keyframes fmt-godrays {
          0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
          40%  { opacity: 1; }
          100% { opacity: 0.4; transform: translate(-50%, -50%) scale(1); }
        }
        @keyframes fmt-rays-spin {
          to { transform: translate(-50%, -50%) rotate(360deg); }
        }
        @keyframes fmt-invite-rise {
          0%   { transform: translateY(80%) scale(0.3) rotate(-8deg); opacity: 0; }
          50%  { opacity: 1; }
          100% { transform: translateY(0) scale(1) rotate(0deg); opacity: 1; }
        }
        @keyframes fmt-shine-sweep {
          0%   { transform: translateX(-100%); }
          100% { transform: translateX(100%); }
        }
      `}</style>
    </div>
  );
}


// ─────────────────────────────────────────────────────────────
// MINI-VIDEO — 14s dramatic sequence with photo + age countdown
// ─────────────────────────────────────────────────────────────
function FormatVideo({ themeId, layoutId, data, autoplay = true }) {
  const [t, setT] = useStateF(0);
  const [playing, setPlaying] = useStateF(autoplay);
  const startRef = useRefF(null);
  const DURATION = 14000;

  useEffectF(() => {
    if (!playing) return;
    let raf;
    startRef.current = performance.now() - t * DURATION;
    const tick = (now) => {
      const elapsed = (now - startRef.current) / DURATION;
      if (elapsed >= 1) {
        setT(0);
        startRef.current = now;
      } else {
        setT(elapsed);
      }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [playing]);

  const theme = THEMES[themeId];
  const p = theme.palette;

  // Phases (t = 0..1):
  // 0.00-0.10: dark, "Una festa che non dimenticherai..." typewriter
  // 0.10-0.25: photo zooms in with ken burns
  // 0.25-0.40: name explodes onto screen letter by letter
  // 0.40-0.55: age countdown 1,2,3...N with big bounce
  // 0.55-0.75: invitation reveal slides up, details fade in
  // 0.75-1.00: massive confetti + "SEI INVITATO?" pulse

  const tagline = "Una festa che non dimenticherai...";
  const taglineProgress = Math.max(0, Math.min(1, t / 0.10));
  const taglineChars = Math.floor(tagline.length * taglineProgress);

  const photoOpacity = t > 0.10 && t < 0.30 ? 1 : 0;
  const photoZoom = t > 0.10 ? 1 + (t - 0.10) * 0.6 : 1;

  const nameProgress = Math.max(0, Math.min(1, (t - 0.25) / 0.15));
  const nome = (data.nome || 'Nome').toUpperCase();
  const nameChars = Math.floor(nome.length * nameProgress);
  const nameOpacity = t > 0.25 && t < 0.50 ? 1 : 0;

  const targetAge = parseInt(data.eta, 10) || 1;
  const ageProgress = Math.max(0, Math.min(1, (t - 0.40) / 0.15));
  const currentAge = Math.max(1, Math.min(targetAge, Math.ceil(ageProgress * targetAge)));
  const ageVisible = t > 0.40 && t < 0.60;
  const ageBounce = ageProgress < 1 ? 1 + Math.sin(ageProgress * Math.PI * targetAge * 2) * 0.08 : 1;

  const inviteY = t < 0.55 ? 100 : Math.max(0, 100 - (t - 0.55) * 500);
  const inviteOpacity = t < 0.55 ? 0 : 1;

  const finaleProgress = Math.max(0, Math.min(1, (t - 0.75) / 0.25));

  return (
    <div style={{ position: 'absolute', inset: 0, background: '#0A0A14', overflow: 'hidden' }}>
      {/* Phase 0: typewriter tagline on black */}
      {t < 0.13 && (
        <div style={{
          position: 'absolute', inset: 0,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          padding: '0 16%',
          opacity: t < 0.10 ? 1 : 1 - (t - 0.10) * 30,
        }}>
          <div style={{
            color: '#fff', fontFamily: 'DM Serif Display, serif', fontStyle: 'italic',
            fontSize: 24, lineHeight: 1.3, textAlign: 'center',
          }}>
            {tagline.slice(0, taglineChars)}
            <span style={{ opacity: taglineProgress < 1 ? 1 : 0, color: p.primary }}>|</span>
          </div>
        </div>
      )}

      {/* Phase 1: photo or themed reveal */}
      {photoOpacity > 0 && (
        <div style={{
          position: 'absolute', inset: 0,
          opacity: photoOpacity,
          transform: `scale(${photoZoom})`,
          transition: 'opacity 0.3s, transform 0.1s linear',
        }}>
          {data.photo ? (
            <img src={data.photo} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
          ) : (
            <div style={{
              width: '100%', height: '100%',
              background: `radial-gradient(circle at 50% 40%, ${p.bg2} 0%, ${p.ink} 100%)`,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              flexDirection: 'column', gap: 16,
            }}>
              {/* candle */}
              <div style={{ position: 'relative' }}>
                <div style={{ width: 8, height: 70, background: '#F4E4C1', borderRadius: 2 }}/>
                <div style={{
                  position: 'absolute', top: -28, left: '50%', transform: 'translateX(-50%)',
                  width: 22, height: 32,
                  background: 'radial-gradient(ellipse at 50% 70%, #FFE066 0%, #FF9A3D 50%, transparent 80%)',
                  borderRadius: '50% 50% 30% 30% / 70% 70% 30% 30%',
                  animation: 'fmt-flame 0.4s ease-in-out infinite alternate',
                  filter: 'drop-shadow(0 0 14px #FF9A3Daa)',
                }}/>
              </div>
              <div style={{ color: '#fff', fontSize: 11, letterSpacing: '0.3em', opacity: 0.6, fontWeight: 700 }}>
                STA PER ARRIVARE
              </div>
            </div>
          )}
          {/* dark vignette */}
          <div style={{
            position: 'absolute', inset: 0,
            background: 'radial-gradient(ellipse at 50% 50%, transparent 40%, rgba(0,0,0,0.7) 100%)',
          }}/>
        </div>
      )}

      {/* Phase 2: name big explosion */}
      {nameOpacity > 0 && (
        <div style={{
          position: 'absolute', inset: 0,
          background: `linear-gradient(180deg, ${p.bg} 0%, ${p.bg2} 100%)`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          padding: '0 6%',
          opacity: nameOpacity,
          transition: 'opacity 0.3s',
        }}>
          <div style={{
            fontFamily: 'DM Serif Display, serif', fontStyle: 'italic',
            fontSize: nome.length > 8 ? 50 : 64, lineHeight: 0.95,
            color: p.ink, textAlign: 'center',
            letterSpacing: '-0.02em',
          }}>
            {nome.split('').map((ch, i) => (
              <span key={i} style={{
                display: 'inline-block',
                opacity: i < nameChars ? 1 : 0,
                transform: i < nameChars ? 'translateY(0) scale(1)' : 'translateY(40px) scale(0.5)',
                transition: 'all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)',
                color: i % 2 === 0 ? p.ink : p.primary,
              }}>{ch === ' ' ? '\u00A0' : ch}</span>
            ))}
          </div>
        </div>
      )}

      {/* Phase 3: age countdown with bounce */}
      {ageVisible && (
        <div style={{
          position: 'absolute', inset: 0,
          background: p.primary,
          display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center',
        }}>
          <div style={{ color: '#fff', fontSize: 13, fontWeight: 800, letterSpacing: '0.3em', opacity: 0.85 }}>
            COMPIE
          </div>
          <div style={{
            fontFamily: 'DM Serif Display, serif',
            fontSize: 220, lineHeight: 0.85, color: '#fff',
            transform: `scale(${ageBounce})`,
            textShadow: `0 8px 0 ${p.ink}55, 0 14px 30px rgba(0,0,0,0.4)`,
            marginTop: 8,
          }}>
            {currentAge}
          </div>
          <div style={{ color: '#fff', fontSize: 18, fontWeight: 800, letterSpacing: '0.2em', marginTop: -6 }}>
            {targetAge === 1 ? 'ANNO' : 'ANNI'}
          </div>
        </div>
      )}

      {/* Phase 4: invitation card slides up */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `linear-gradient(180deg, ${p.bg} 0%, ${p.bg2} 100%)`,
        opacity: inviteOpacity,
        transition: 'opacity 0.2s',
      }}>
        <div style={{
          position: 'absolute', left: '10%', right: '10%', top: '8%', bottom: '14%',
          transform: `translateY(${inviteY}%)`,
          transition: 'transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)',
          borderRadius: 14, overflow: 'hidden',
          boxShadow: `0 20px 60px ${p.ink}66`,
        }}>
          <Invitation themeId={themeId} layoutId={layoutId} data={data} />
        </div>
        {/* floor "SEI INVITATO?" pulse */}
        {finaleProgress > 0 && (
          <div style={{
            position: 'absolute', left: 0, right: 0, bottom: '4%', textAlign: 'center',
            fontSize: 22, fontWeight: 900, letterSpacing: '0.15em',
            color: p.primary,
            opacity: finaleProgress,
            animation: 'fmt-cta-pulse 0.8s ease-in-out infinite',
          }}>
            SEI INVITATO/A?
          </div>
        )}
      </div>

      {/* Phase 5: confetti finale */}
      {finaleProgress > 0 && (
        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 9 }}>
          {Array.from({ length: 50 }).map((_, i) => {
            const colors = [p.primary, p.secondary, p.accent, '#FFD93D', '#fff'];
            return (
              <div key={i} style={{
                position: 'absolute',
                left: `${(i * 11) % 100}%`,
                top: -10,
                width: 8 + (i % 3) * 3,
                height: 14 + (i % 3) * 4,
                background: colors[i % colors.length],
                borderRadius: i % 2 === 0 ? 1.5 : '50%',
                animation: `fmt-confetti-finale ${1.6 + (i % 4) * 0.3}s ${(i % 8) * 0.04}s linear forwards`,
                transform: `rotate(${i * 17}deg)`,
                boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
              }} />
            );
          })}
        </div>
      )}

      {/* Progress bar */}
      <div style={{
        position: 'absolute', left: 12, right: 12, top: 12,
        height: 3, background: 'rgba(255,255,255,0.25)', borderRadius: 2, zIndex: 10,
      }}>
        <div style={{
          height: '100%', width: `${t * 100}%`, background: '#fff', borderRadius: 2,
        }}/>
      </div>
      {/* Replay */}
      <button
        onClick={() => { setT(0); setPlaying(true); }}
        style={{
          position: 'absolute', bottom: 12, right: 12,
          width: 36, height: 36, borderRadius: 999,
          background: 'rgba(0,0,0,0.7)', color: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          border: 'none', zIndex: 10,
        }}
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
          <path d="M3 12 A 9 9 0 1 1 6 18.7 M 3 19 V 13 H 9"/>
        </svg>
      </button>

      <style>{`
        @keyframes fmt-flame {
          from { transform: translateX(-50%) scaleY(1); }
          to   { transform: translateX(-50%) scaleY(1.15); }
        }
        @keyframes fmt-confetti-finale {
          to { transform: translateY(160%) rotate(720deg); }
        }
        @keyframes fmt-cta-pulse {
          0%, 100% { transform: scale(1); }
          50%      { transform: scale(1.06); }
        }
      `}</style>
    </div>
  );
}

function formatVideoDate(iso) {
  if (!iso) return '20 Apr 2026';
  const d = new Date(iso);
  if (isNaN(d)) return iso;
  const months = ['Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'];
  return `${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}`;
}

function FormattedInvite({ format, themeId, layoutId, data, paused = false }) {
  if (format === 'animato') return <FormatAnimato themeId={themeId} layoutId={layoutId} data={data} paused={paused} />;
  if (format === 'scartalo')return <FormatScartalo themeId={themeId} layoutId={layoutId} data={data} paused={paused} />;
  if (format === 'video')   return <FormatVideo   themeId={themeId} layoutId={layoutId} data={data} autoplay={!paused} />;
  return <Invitation themeId={themeId} layoutId={layoutId} data={data} />;
}

Object.assign(window, { FORMATS, FormatAnimato, FormatScartalo, FormatVideo, FormattedInvite });
