From a86421eb5c86d5e3743576d99d2af5546abaf0cc Mon Sep 17 00:00:00 2001 From: Me Here Date: Mon, 25 May 2026 19:16:13 -0500 Subject: [PATCH] Player: light/dark theme so the device stands out from the background MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device case was nearly the same tone as the room — the body's radial-gradient even peaked *lighter* than the case — so the unit blended into the background. Added a theme toggle mirroring the editor (◐/☀/☾, cycles system → light → dark, shares the "metronome.theme" key, with a pre-paint head script to avoid a flash) and reworked the palette around it: - dark: a charcoal device sits a clear step lighter than a near-black room, with a rim highlight + drop shadow + faint cyan glow so it reads as an object; - light: the dark device sits on a bright "desk" card (panel + fields go light). Device internals (OLED, beat LEDs, buttons, knob, screws) keep fixed dark-hardware colours in both themes via --dtxt/--dmuted, so only the environment switches. Co-Authored-By: Claude Opus 4.7 (1M context) --- player.html | 80 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/player.html b/player.html index bd02be8..f68a9dd 100644 --- a/player.html +++ b/player.html @@ -16,29 +16,57 @@ Audio here is the synthesized voice set (the firmware uses the same scheduler; on hardware the voices map to CC0 samples on the I2S DAC). One file, no deps. --> +
VARASYS PM‑1 · hardware player (mockup) - Open editor ↗ + + + Open editor ↗ +
@@ -333,6 +365,20 @@ $("bLoad").onclick=()=>loadConfig($("cfg").value); $("storedSel").onchange=(e)=>{ const v=e.target.value; if(!v) return; const sl = v[0]==="b" ? e.target._builtin[+v.slice(1)] : e.target._lists[+v.slice(1)]; if(!sl) return; loadSetlistObj({title:sl.title,items:(sl.items||[]).map(it=>({...it}))}); setStatus("✓ Loaded set list “"+(sl.title||"set list")+"”.",true); }; +/* theme toggle — cycles system → light → dark; shares the editor's "metronome.theme" key */ +const THEMES = ["system","light","dark"]; +function effectiveTheme(p){ return p==="system" ? (matchMedia("(prefers-color-scheme: light)").matches?"light":"dark") : p; } +function themePref(){ try{ const p=localStorage.getItem("metronome.theme"); return (p==="light"||p==="dark"||p==="system")?p:"system"; }catch(e){ return "system"; } } +function applyTheme(p){ + try{ localStorage.setItem("metronome.theme",p); }catch(e){} + document.documentElement.dataset.theme = effectiveTheme(p); + $("themeBtn").textContent = p==="system" ? "◐" : p==="light" ? "☀" : "☾"; + $("themeBtn").title = "Theme: "+p+" (click to cycle: system → light → dark)"; +} +$("themeBtn").onclick = ()=> applyTheme(THEMES[(THEMES.indexOf(themePref())+1)%THEMES.length]); +matchMedia("(prefers-color-scheme: light)").addEventListener("change", ()=>{ if(themePref()==="system") applyTheme("system"); }); +applyTheme(themePref()); + addEventListener("keydown",(e)=>{ const t=e.target, tag=t?t.tagName:""; if(tag==="TEXTAREA"||tag==="INPUT"||tag==="SELECT") return; const k=e.key;