/* invitation-scene.jsx — shared visual primitives for Pavle's invitation.
 * Loaded as a Babel script. Reads the shared timeline via useTime()
 * (provided by the app through window.TimelineContext). Exports components
 * to window for the variants file to compose.
 */
const { useTime, Easing, clamp, interpolate } = window;

/* ---------- timing helper: fade/slide a block in (and optionally out) ---------- */
function Appear({ inAt = 0, inDur = 0.8, outAt = null, outDur = 0.6, rise = 22, scaleFrom = 1, children, style = {} }) {
  const t = useTime();
  let op = 0, ty = rise, sc = scaleFrom;
  if (t < inAt) { op = 0; ty = rise; sc = scaleFrom; }
  else if (t < inAt + inDur) {
    const p = Easing.easeOutCubic(clamp((t - inAt) / inDur, 0, 1));
    op = p; ty = rise * (1 - p); sc = scaleFrom + (1 - scaleFrom) * p;
  } else if (outAt != null && t > outAt) {
    const p = Easing.easeInCubic(clamp((t - outAt) / outDur, 0, 1));
    op = 1 - p; ty = -rise * 0.45 * p; sc = 1;
  } else { op = 1; ty = 0; sc = 1; }
  return (
    <div style={{ opacity: op, transform: `translateY(${ty}px) scale(${sc})`, willChange: 'transform,opacity', ...style }}>
      {children}
    </div>
  );
}

/* ---------- pastel sky background with warm center glow ---------- */
function SkyBackground({ variant = 'A' }) {
  const t = useTime();
  // gentle breathing of the central glow
  const glow = 0.55 + 0.12 * Math.sin(t * 0.6);
  const base = variant === 'B'
    ? 'linear-gradient(180deg, #DCE7F0 0%, #E9EEEA 42%, #FBEFE6 100%)'
    : 'linear-gradient(180deg, #D9E6F1 0%, #EAF0EC 46%, #FCF4EC 100%)';
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>
      <div style={{ position: 'absolute', inset: 0, background: base }} />
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(58% 46% at 50% 38%, rgba(255,247,228,${glow}) 0%, rgba(255,247,228,0) 70%)`,
      }} />
      {/* soft top wash of powder blue */}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(80% 40% at 50% -6%, rgba(175,201,222,0.45) 0%, rgba(175,201,222,0) 60%)',
      }} />
    </div>
  );
}

/* ---------- drifting bokeh lights ---------- */
const BOKEH = (() => {
  const arr = [];
  const cols = ['rgba(255,236,180,0.55)', 'rgba(255,255,255,0.5)', 'rgba(190,212,232,0.5)', 'rgba(201,224,201,0.45)'];
  for (let i = 0; i < 12; i++) {
    arr.push({
      x: (i * 97 + 60) % 1080,
      size: 36 + (i % 4) * 26,
      speed: 26 + (i % 5) * 10,
      phase: (i * 1.7) % (Math.PI * 2),
      sway: 18 + (i % 3) * 14,
      col: cols[i % cols.length],
      off: (i * 173) % 2200,
    });
  }
  return arr;
})();
function Bokeh() {
  const t = useTime();
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>
      {BOKEH.map((b, i) => {
        const span = 2200;
        const y = ((b.off + (2200 - t * b.speed)) % span + span) % span - 140;
        const x = b.x + Math.sin(t * 0.5 + b.phase) * b.sway;
        const edgeFade = clamp(Math.min(y + 100, 2000 - y) / 260, 0, 1);
        return (
          <div key={i} style={{
            position: 'absolute', left: x, top: y,
            width: b.size, height: b.size, borderRadius: '50%',
            background: `radial-gradient(circle at 38% 34%, ${b.col} 0%, rgba(255,255,255,0) 70%)`,
            filter: 'blur(2px)', opacity: 0.85 * edgeFade,
          }} />
        );
      })}
    </div>
  );
}

/* ---------- twinkling stars / gold sparkles ---------- */
const SPARKS = (() => {
  const arr = [];
  for (let i = 0; i < 16; i++) {
    arr.push({
      x: (i * 131 + 40) % 1060,
      y: (i * 257 + 80) % 1840,
      size: 8 + (i % 4) * 6,
      phase: (i * 0.9) % (Math.PI * 2),
      rate: 1.4 + (i % 5) * 0.35,
      gold: i % 3 !== 0,
    });
  }
  return arr;
})();
function Sparkles() {
  const t = useTime();
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>
      {SPARKS.map((s, i) => {
        const tw = 0.25 + 0.75 * Math.pow(Math.max(0, Math.sin(t * s.rate + s.phase)), 2);
        const col = s.gold ? '#E9C66A' : '#FFFFFF';
        return (
          <div key={i} style={{
            position: 'absolute', left: s.x, top: s.y, width: s.size, height: s.size,
            transform: `translate(-50%,-50%) scale(${0.6 + tw * 0.6})`, opacity: tw,
          }}>
            <FourStar size={s.size} color={col} />
          </div>
        );
      })}
    </div>
  );
}
function FourStar({ size = 12, color = '#E9C66A' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" style={{ display: 'block', filter: `drop-shadow(0 0 4px ${color})` }}>
      <path d="M12 0 C13 8 16 11 24 12 C16 13 13 16 12 24 C11 16 8 13 0 12 C8 11 11 8 12 0 Z" fill={color} />
    </svg>
  );
}

/* ---------- balloon ---------- */
function Balloon({ x, baseY, size = 120, color, hi, mode = 'bob', phase = 0, sway = 16, rise = 18, tilt = 0 }) {
  const t = useTime();
  let y = baseY, dx = Math.sin(t * 0.5 + phase) * sway;
  if (mode === 'rise') {
    const span = 2300;
    y = baseY - (((t * rise + phase * 60) % span));
    if (y < -260) y += span;
  } else {
    y = baseY + Math.sin(t * 0.7 + phase) * 16;
  }
  const rot = tilt + Math.sin(t * 0.6 + phase) * 4;
  const w = size, h = size * 1.18;
  return (
    <div style={{ position: 'absolute', left: x, top: y, transform: `translate(-50%,0) rotate(${rot}deg)`, transformOrigin: '50% 0%', willChange: 'transform' }}>
      {/* string */}
      <div style={{
        position: 'absolute', left: '50%', top: h - 4, width: 1.5, height: size * 0.9,
        background: 'linear-gradient(180deg, rgba(120,120,120,0.5), rgba(120,120,120,0))',
        transform: `translateX(-50%) rotate(${Math.sin(t + phase) * 3}deg)`, transformOrigin: 'top',
      }} />
      <div style={{ position: 'relative', width: w, height: h }}>
        <div style={{
          position: 'absolute', inset: 0, borderRadius: '50% 50% 48% 48% / 54% 54% 46% 46%',
          background: `radial-gradient(38% 32% at 36% 28%, ${hi} 0%, ${color} 46%, ${color} 100%)`,
          boxShadow: `inset -10px -16px 26px rgba(0,0,0,0.10), 0 10px 22px rgba(80,90,110,0.12)`,
        }} />
        {/* knot */}
        <div style={{
          position: 'absolute', left: '50%', top: h - 7, width: 12, height: 10,
          transform: 'translateX(-50%)', background: color, clipPath: 'polygon(50% 0, 100% 100%, 0 100%)', opacity: 0.9,
        }} />
        {/* specular */}
        <div style={{
          position: 'absolute', left: '26%', top: '16%', width: '20%', height: '26%', borderRadius: '50%',
          background: 'radial-gradient(circle, rgba(255,255,255,0.75), rgba(255,255,255,0))',
        }} />
      </div>
    </div>
  );
}

/* ---------- soft white dove ---------- */
function Dove({ size = 120, color = '#FFFFFF' }) {
  const t = useTime();
  const flap = Math.sin(t * 1.6) * 6;
  return (
    <svg width={size} height={size * 0.8} viewBox="0 0 120 96" style={{ display: 'block', filter: 'drop-shadow(0 4px 14px rgba(140,160,190,0.45))', overflow: 'visible' }}>
      <g style={{ transform: `rotate(${flap * 0.15}deg)`, transformOrigin: '60px 60px' }}>
        {/* body */}
        <path d="M18 64 C30 50 44 48 60 52 C76 56 92 52 104 40 C100 58 86 70 66 72 C70 80 64 88 54 86 C58 80 54 74 48 74 C36 78 24 74 18 64 Z" fill={color} />
        {/* upper wing */}
        <path d={`M52 54 C58 ${30 + flap} 78 ${22 + flap} 98 30 C84 42 70 46 56 50 Z`} fill={color} opacity="0.96" />
        {/* lower wing hint */}
        <path d="M40 62 C46 70 56 72 66 70 C58 64 48 62 40 62 Z" fill="#EFF4F8" opacity="0.7" />
        {/* head + beak */}
        <circle cx="22" cy="60" r="6.5" fill={color} />
        <path d="M16 60 L7 61 L16 64 Z" fill="#E7C067" />
        <circle cx="20.5" cy="59" r="1.3" fill="#5b6472" />
      </g>
    </svg>
  );
}

/* ---------- delicate cross ---------- */
function Cross({ h = 120, color = '#C9A24B' }) {
  const w = h * 0.62;
  return (
    <svg width={w} height={h} viewBox="0 0 62 120" style={{ display: 'block', filter: `drop-shadow(0 0 8px rgba(201,162,75,0.5))`, overflow: 'visible' }}>
      <defs>
        <linearGradient id="goldX" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0" stopColor="#EAD089" />
          <stop offset="0.5" stopColor="#C9A24B" />
          <stop offset="1" stopColor="#A87E2E" />
        </linearGradient>
      </defs>
      <g fill="url(#goldX)">
        {/* vertical */}
        <rect x="26.5" y="4" width="9" height="112" rx="4.5" />
        {/* horizontal */}
        <rect x="10" y="34" width="42" height="9" rx="4.5" />
      </g>
      {/* tiny shine */}
      <circle cx="31" cy="38.5" r="2.4" fill="#fff" opacity="0.7" />
    </svg>
  );
}

/* ---------- Pavle medallion (photo + gold ring + glow + pastel rim wash) ---------- */
function Medallion({ size = 520, glowFrom = 2.2 }) {
  const t = useTime();
  // entrance glow + gentle "giggle" bob/scale once present
  const intro = clamp((t - glowFrom) / 1.0, 0, 1);
  const introE = Easing.easeOutCubic(intro);
  const bob = t > glowFrom ? Math.sin((t - glowFrom) * 1.9) * 4 + Math.sin((t - glowFrom) * 0.9) * 3 : 0;
  const breathe = 1 + (t > glowFrom ? Math.sin((t - glowFrom) * 1.4) * 0.012 : 0);
  const op = introE;
  const sc = (0.86 + 0.14 * introE) * breathe;
  return (
    <div style={{
      position: 'absolute', left: '50%', top: 0, width: size, height: size,
      transform: `translate(-50%,0) translateY(${bob}px) scale(${sc})`, transformOrigin: '50% 50%',
      opacity: op, willChange: 'transform,opacity',
    }}>
      {/* outer soft halo */}
      <div style={{
        position: 'absolute', inset: -size * 0.16, borderRadius: '50%',
        background: 'radial-gradient(circle, rgba(255,247,224,0.85) 0%, rgba(255,247,224,0.35) 42%, rgba(255,247,224,0) 70%)',
        filter: 'blur(4px)',
      }} />
      {/* gold ring */}
      <div style={{
        position: 'absolute', inset: -8, borderRadius: '50%',
        background: 'conic-gradient(from 210deg, #EAD089, #C9A24B, #F2E2A6, #B8893A, #EAD089)',
        boxShadow: '0 10px 40px rgba(180,150,70,0.40), inset 0 2px 6px rgba(255,255,255,0.5)',
      }} />
      <div style={{ position: 'absolute', inset: -2, borderRadius: '50%', background: '#FBF4E7' }} />
      {/* photo */}
      <div style={{ position: 'absolute', inset: 6, borderRadius: '50%', overflow: 'hidden' }}>
        <img src="assets/pavle-medallion.png" alt="Pavle" style={{ width: '112%', height: '112%', objectFit: 'cover', marginLeft: '-6%', marginTop: '-5%', display: 'block' }} />
        {/* pastel rim wash to subdue busy corners and lift into the scene */}
        <div style={{
          position: 'absolute', inset: 0, borderRadius: '50%',
          background: 'radial-gradient(circle at 50% 46%, rgba(255,255,255,0) 52%, rgba(233,238,234,0.55) 78%, rgba(214,225,236,0.8) 100%)',
          mixBlendMode: 'screen',
        }} />
        <div style={{
          position: 'absolute', inset: 0, borderRadius: '50%',
          boxShadow: 'inset 0 6px 22px rgba(255,255,255,0.45)',
        }} />
      </div>
    </div>
  );
}

Object.assign(window, {
  Appear, SkyBackground, Bokeh, Sparkles, FourStar, Balloon, Dove, Cross, Medallion,
});
