···9999 let introEl: HTMLAudioElement;
100100 let gameEl: HTMLAudioElement;
101101 let audioUnlocked = false;
102102+ let audioCtx: AudioContext | undefined;
102103103104 function unlockAudio() {
104105 if (audioUnlocked) return;
···106107 // Mobile browsers ignore preload — force load on first user gesture
107108 introEl?.load();
108109 gameEl?.load();
110110+111111+ // Use Web Audio API GainNode to force volume on mobile (iOS ignores .volume)
112112+ try {
113113+ audioCtx = new AudioContext();
114114+ for (const el of [introEl, gameEl]) {
115115+ if (!el) continue;
116116+ const source = audioCtx.createMediaElementSource(el);
117117+ const gain = audioCtx.createGain();
118118+ gain.gain.value = 0.6;
119119+ source.connect(gain);
120120+ gain.connect(audioCtx.destination);
121121+ }
122122+ audioCtx.resume().catch(() => {});
123123+ } catch (e) {
124124+ console.warn('[vodjam] Web Audio gain setup failed:', e);
125125+ }
109126 }
110127111128 function playCorrectTrack() {