// HERO PLAYER — inline audio player placeholder const { useState: useStatePl, useRef: useRefPl, useEffect: useEffectPl } = React; // When you're ready, drop mp3s into assets/preview/ and fill this queue. // Set `src: "assets/preview/your-file.mp3"` on any track to activate it. const QUEUE = [ { title: "Neon Memories", album: "Digital Blade", src: "assets/preview/neon-memories.mp3", cover: "assets/albums/03-digital-blade.png" }, ]; function HeroPlayer() { const [ix, setIx] = useStatePl(0); const [playing, setPlaying] = useStatePl(false); const [prog, setProg] = useStatePl(0); const [dur, setDur] = useStatePl(0); const [cur, setCur] = useStatePl(0); const [vol, setVol] = useStatePl(0.8); const [muted, setMuted] = useStatePl(false); const audioRef = useRefPl(null); const track = QUEUE[ix]; const ready = !!track.src; useEffectPl(() => { const a = audioRef.current; if (!a) return; setPlaying(false); setProg(0); setCur(0); if (ready) { a.load(); } }, [ix, ready]); useEffectPl(() => { const a = audioRef.current; if (!a) return; a.volume = muted ? 0 : vol; }, [vol, muted]); const toggle = () => { if (!ready) return; const a = audioRef.current; if (!a) return; if (a.paused) { a.play(); setPlaying(true); } else { a.pause(); setPlaying(false); } }; const prev = () => setIx((ix - 1 + QUEUE.length) % QUEUE.length); const next = () => setIx((ix + 1) % QUEUE.length); const onTime = () => { const a = audioRef.current; if (!a) return; setCur(a.currentTime); setDur(a.duration || 0); setProg(a.duration ? (a.currentTime / a.duration) * 100 : 0); }; const seek = (e) => { if (!ready) return; const a = audioRef.current; if (!a || !a.duration) return; const r = e.currentTarget.getBoundingClientRect(); const p = (e.clientX - r.left) / r.width; a.currentTime = p * a.duration; }; const fmt = (s) => { if (!isFinite(s) || s < 0) s = 0; const m = Math.floor(s / 60); const sec = Math.floor(s % 60); return `${String(m).padStart(2,"0")}:${String(sec).padStart(2,"0")}`; }; // Animated equalizer bars (purely visual) const bars = Array.from({length: 40}); return (
); } const pl = { wrap: { marginTop: 8, padding: 20, position: "relative", }, head: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14, }, main: { display: "grid", gridTemplateColumns: "90px 1fr", gap: 18, alignItems: "flex-start", }, disc: { width: 90, height: 90, position: "relative", }, info: { minWidth: 0 }, eq: { marginTop: 12, display: "flex", alignItems: "flex-end", gap: 2, height: 32, borderBottom: "1px solid var(--panel-stroke)", paddingBottom: 2, }, track: { marginTop: 12, height: 4, background: "oklch(0.2 0.06 300)", position: "relative", transition: "opacity .2s", }, trackFill: { height: "100%", background: "linear-gradient(90deg, var(--magenta), var(--cyan))", boxShadow: "0 0 8px var(--magenta)", transition: "width .1s linear", }, trackDot: { position: "absolute", top: -3, width: 10, height: 10, borderRadius: "50%", background: "var(--magenta)", boxShadow: "0 0 10px var(--magenta)", transition: "left .1s linear", }, times: { display: "flex", justifyContent: "space-between", marginTop: 4, }, ctrls: { display: "flex", alignItems: "center", gap: 8, marginTop: 10, }, btn: { width: 32, height: 32, border: "1px solid var(--panel-stroke)", background: "oklch(0.12 0.04 300 / 0.6)", color: "var(--ink)", cursor: "pointer", fontFamily: "Orbitron, sans-serif", fontSize: 10, }, play: { width: 44, height: 32, background: "var(--magenta)", color: "var(--bg-0)", border: "none", fontSize: 12, fontWeight: 900, }, queue: { marginTop: 14, borderTop: "1px solid var(--panel-stroke)", paddingTop: 12, display: "flex", flexDirection: "column", gap: 2, }, qItem: { display: "flex", alignItems: "center", gap: 10, padding: "6px 10px", border: "1px solid transparent", background: "transparent", fontFamily: "inherit", fontSize: 12, textAlign: "left", cursor: "pointer", transition: "all .15s", }, volWrap: { display: "flex", alignItems: "center", gap: 8, padding: "0 4px 0 0", }, volSlider: { width: 90, height: 4, appearance: "none", WebkitAppearance: "none", background: "oklch(0.2 0.06 300)", outline: "none", cursor: "pointer", accentColor: "var(--magenta)", }, }; // Equalizer keyframes const _plStyle = document.createElement("style"); _plStyle.textContent = `@keyframes eqbar { from { transform: scaleY(0.3); } to { transform: scaleY(1); } }`; document.head.appendChild(_plStyle); window.HeroPlayer = HeroPlayer;