// Shared helpers: cursor, audio, crosses bg // Exports to window: Cursor, useAudio, CrossesBg, Chrome, FloatingCross const { useState, useEffect, useRef, useMemo, useCallback } = React; // ==== AUDIO ENGINE ==== let _audioCtx = null; function getCtx() { if (!_audioCtx) { _audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } if (_audioCtx.state === 'suspended') _audioCtx.resume(); return _audioCtx; } function play808(freq = 55, dur = 0.35, vol = 0.25) { try { const ctx = getCtx(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = 'sine'; osc.frequency.setValueAtTime(freq * 3, ctx.currentTime); osc.frequency.exponentialRampToValueAtTime(freq, ctx.currentTime + 0.08); gain.gain.setValueAtTime(vol, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + dur); osc.connect(gain).connect(ctx.destination); osc.start(); osc.stop(ctx.currentTime + dur); } catch (e) {} } function playClick() { try { const ctx = getCtx(); // short noise burst const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.08, ctx.sampleRate); const data = buffer.getChannelData(0); for (let i = 0; i < data.length; i++) { data[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / data.length, 3); } const src = ctx.createBufferSource(); src.buffer = buffer; const gain = ctx.createGain(); gain.gain.value = 0.12; const filter = ctx.createBiquadFilter(); filter.type = 'highpass'; filter.frequency.value = 2000; src.connect(filter).connect(gain).connect(ctx.destination); src.start(); } catch (e) {} } function playCrackle() { try { const ctx = getCtx(); const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.3, ctx.sampleRate); const data = buffer.getChannelData(0); for (let i = 0; i < data.length; i++) { data[i] = (Math.random() > 0.985) ? (Math.random() * 2 - 1) * 0.7 : 0; } const src = ctx.createBufferSource(); src.buffer = buffer; const gain = ctx.createGain(); gain.gain.value = 0.18; src.connect(gain).connect(ctx.destination); src.start(); } catch (e) {} } function playHover() { try { const ctx = getCtx(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = 'square'; osc.frequency.value = 1800; gain.gain.setValueAtTime(0.03, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + 0.04); osc.connect(gain).connect(ctx.destination); osc.start(); osc.stop(ctx.currentTime + 0.04); } catch (e) {} } window.TP_Audio = { play808, playClick, playCrackle, playHover, getCtx }; // ==== CURSOR ==== function Cursor() { const cursorRef = useRef(null); const trailRef = useRef(null); const posRef = useRef({ x: 0, y: 0 }); const trailPosRef = useRef({ x: 0, y: 0 }); const [clicking, setClicking] = useState(false); useEffect(() => { const onMove = (e) => { posRef.current = { x: e.clientX, y: e.clientY }; if (cursorRef.current) { cursorRef.current.style.transform = `translate(${e.clientX}px, ${e.clientY}px) translate(-50%, -50%)`; } }; const onDown = () => { setClicking(true); TP_Audio.playClick(); }; const onUp = () => setClicking(false); window.addEventListener('mousemove', onMove); window.addEventListener('mousedown', onDown); window.addEventListener('mouseup', onUp); let raf; const loop = () => { trailPosRef.current.x += (posRef.current.x - trailPosRef.current.x) * 0.18; trailPosRef.current.y += (posRef.current.y - trailPosRef.current.y) * 0.18; if (trailRef.current) { trailRef.current.style.transform = `translate(${trailPosRef.current.x}px, ${trailPosRef.current.y}px) translate(-50%, -50%)`; } raf = requestAnimationFrame(loop); }; loop(); return () => { window.removeEventListener('mousemove', onMove); window.removeEventListener('mousedown', onDown); window.removeEventListener('mouseup', onUp); cancelAnimationFrame(raf); }; }, []); const crossSvg = ( ); return ( <>