// Three BGM video design variants. Each is a self-contained component // that renders a 1920x1080 frame (scaled to artboard size by parent), // with the source video looping in the background and synthetic // audio-reactive ornaments animated on top. const { useEffect, useRef, useState } = React; // ───────────────────────────────────────────────────────────────────── // Shared: pseudo-music amplitude generator. Returns 0..1. // Used so all three designs share a consistent "musicality" even though // none of them are reading real audio. // ───────────────────────────────────────────────────────────────────── function waveAmp(t, i = 0) { // Multiple sines + bass envelope; tuned to feel lo-fi-ish. const beat = (Math.sin(t * Math.PI * 1.8) * 0.5 + 0.5) ** 2; // 0..1, kicks const mid = Math.sin(t * 4.1 + i * 0.31) * 0.45; const hi = Math.sin(t * 9.7 + i * 0.83) * 0.25; const drift = Math.sin(t * 0.6 + i * 0.07) * 0.18; const raw = Math.abs(mid + hi + drift) * 0.7 + beat * 0.35; return Math.max(0.05, Math.min(1, raw)); } // Animation tick hook (returns elapsed seconds since mount). function useTick() { const [t, setT] = useState(0); useEffect(() => { let raf, start = performance.now(); const loop = (now) => { setT((now - start) / 1000); raf = requestAnimationFrame(loop); }; raf = requestAnimationFrame(loop); return () => cancelAnimationFrame(raf); }, []); return t; } // Looping muted bg video used by all variants function BgVideo({ style }) { const ref = useRef(null); useEffect(() => { const v = ref.current; if (!v) return; v.muted = true; v.play().catch(() => {}); }, []); return (