import { useEffect, useRef } from "react"; /** Full-screen animated SVG sine waves morphing between clean & corrupted forms. */ export default function WaveformBackground() { const ref = useRef(null); useEffect(() => { const svg = ref.current; if (!svg) return; let frame = 0; let raf = 0; const paths = svg.querySelectorAll("path[data-wave]"); const buildPath = ( width: number, height: number, amp: number, freq: number, noise: number, phase: number ) => { const points: string[] = []; const step = 6; for (let x = 0; x <= width; x += step) { const base = Math.sin((x / width) * Math.PI * 2 * freq + phase) * amp; const jitter = noise * (Math.sin((x / width) * Math.PI * 2 * (freq * 4.7) + phase * 1.3) * 0.5 + Math.sin((x / width) * Math.PI * 2 * (freq * 11.3) + phase * 0.7) * 0.5); const y = height / 2 + base + jitter; points.push(`${x},${y.toFixed(2)}`); } return `M${points.join(" L")}`; }; const tick = () => { frame += 1; const w = svg.viewBox.baseVal.width || 1600; const h = svg.viewBox.baseVal.height || 600; const t = frame / 60; paths.forEach((p, i) => { const layer = i + 1; const noiseRamp = 4 + 8 * Math.sin(t * 0.25 + layer * 0.7); // morph clean ↔ corrupted const d = buildPath( w, h, 18 + layer * 6, 1.3 + layer * 0.4, Math.max(0, noiseRamp), t * (0.4 + layer * 0.15) ); p.setAttribute("d", d); }); raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, []); return (
{/* Faint grid */}
{/* Animated waves */} {/* Soft scan-line vignette */}
); }