/** Infrastructure adapter: Web Audio API sound effects. */ let audioContext: AudioContext | null = null; function getAudioContext(): AudioContext | null { if (typeof window === 'undefined') return null; if (!audioContext) { try { audioContext = new (window.AudioContext || (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext!)(); } catch { return null; } } return audioContext; } export function playHoverSound() { const ctx = getAudioContext(); if (!ctx) return; try { const osc = ctx.createOscillator(); const gain = ctx.createGain(); const filter = ctx.createBiquadFilter(); osc.type = 'sine'; osc.frequency.value = 1100; filter.type = 'lowpass'; filter.frequency.value = 1400; gain.gain.value = 0.04; osc.connect(filter); filter.connect(gain); gain.connect(ctx.destination); osc.start(); gain.gain.linearRampToValueAtTime(0.001, ctx.currentTime + 0.12); setTimeout(() => osc.stop(), 150); } catch { // Silent fail } } export function playAddSound() { const ctx = getAudioContext(); if (!ctx) return; try { const osc = ctx.createOscillator(); const gain = ctx.createGain(); const filter = ctx.createBiquadFilter(); osc.type = 'sine'; osc.frequency.value = 1080; filter.type = 'lowpass'; filter.frequency.value = 1550; gain.gain.value = 0.022; osc.connect(filter); filter.connect(gain); gain.connect(ctx.destination); osc.start(); gain.gain.linearRampToValueAtTime(0.001, ctx.currentTime + 0.08); setTimeout(() => osc.stop(), 120); } catch { // Silent fail } } export function playSuccessSound() { const ctx = getAudioContext(); if (!ctx) return; try { const notes = [523, 659, 784, 1046]; notes.forEach((freq, i) => { setTimeout(() => { try { const osc = ctx.createOscillator(); const gain = ctx.createGain(); const filter = ctx.createBiquadFilter(); osc.type = 'sine'; osc.frequency.value = freq; filter.type = 'lowpass'; filter.frequency.value = 2000; gain.gain.value = 0.07; osc.connect(filter); filter.connect(gain); gain.connect(ctx.destination); osc.start(); gain.gain.linearRampToValueAtTime(0.001, ctx.currentTime + 0.5); setTimeout(() => osc.stop(), 600); } catch { // Silent fail } }, i * 120); }); } catch { // Silent fail } }