SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,338
Folders
408
Scanned Size
3.84 GB
PHP Files
890
Editable Text Files
12,599
File viewer
guarded to /htdocs
/arcade/games/Beat Lights.HTML
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no" /> <title>Beat Lights — Tone Pad Game</title> <meta name="theme-color" content="#0a0f1e" /> <style> :root{ --bg:#0a0f1e; --ink:#eaf2ff; --edge:rgba(255,255,255,.18); --glass:rgba(255,255,255,.06); --acc:#6ae0ff; --ok:#48d18a; --warn:#ffcc4d; --bad:#ff6b6b; --vio:#7c4dff; } *{box-sizing:border-box} html,body{margin:0;height:100%;background:radial-gradient(100% 70% at 50% 20%,#111935 0%,#0a0f1e 65%,#070b16 100%);color:var(--ink);font-family:system-ui,Segoe UI,Inter,Roboto} #hud{position:fixed;top:0;left:0;right:0;display:flex;gap:.6rem;justify-content:space-between;align-items:center;padding:.6rem 1rem;background:rgba(255,255,255,.05);backdrop-filter:blur(8px);border-bottom:1px solid var(--edge);z-index:10} .pill{padding:.35rem .7rem;border:1px solid var(--edge);border-radius:999px;background:var(--glass);font-variant-numeric:tabular-nums} .btn{padding:.55rem .95rem;border:1px solid var(--edge);border-radius:.8rem;background:linear-gradient(180deg,rgba(255,255,255,.1),rgba(255,255,255,.04));cursor:pointer} .btn:hover{background:linear-gradient(180deg,rgba(255,255,255,.14),rgba(255,255,255,.06))} main{display:grid;place-items:center;min-height:100vh;padding-top:64px} .grid{display:grid;grid-template-columns:repeat(2,minmax(120px,220px));gap:1rem} .pad{ position:relative; height:180px; border-radius:1rem; border:1px solid var(--edge); background:var(--glass); display:grid; place-items:center; font-weight:700; letter-spacing:.5px; cursor:pointer; box-shadow: inset 0 0 0 1px rgba(255,255,255,.04); user-select:none; -webkit-user-select:none; touch-action:manipulation; } .pad .label{opacity:.85} .pad:active{transform:translateY(1px)} .pad.light{box-shadow:0 0 30px rgba(106,224,255,.6), inset 0 0 0 1px rgba(255,255,255,.08)} .pad.good{box-shadow:0 0 26px rgba(72,209,138,.6)} .pad.bad{box-shadow:0 0 26px rgba(255,107,107,.6)} .pad.k1{background:linear-gradient(180deg, rgba(124,77,255,.25), rgba(124,77,255,.08))} .pad.k2{background:linear-gradient(180deg, rgba(106,224,255,.25), rgba(106,224,255,.08))} .pad.k3{background:linear-gradient(180deg, rgba(255,204,77,.25), rgba(255,204,77,.08))} .pad.k4{background:linear-gradient(180deg, rgba(72,209,138,.25), rgba(72,209,138,.08))} .key{position:absolute;bottom:.5rem;right:.6rem;opacity:.7;font-size:.9rem;border:1px solid var(--edge);border-radius:.5rem;padding:.1rem .35rem;background:rgba(255,255,255,.08)} .controls{display:flex;gap:.5rem;align-items:center;margin-top:1.2rem} .kbd{border:1px solid var(--edge);background:var(--glass);padding:.2rem .45rem;border-radius:.45rem} #overlay{position:fixed;inset:0;z-index:2147483647;display:grid;place-items:center;pointer-events:auto} #panel{pointer-events:auto; width:min(560px,92vw); padding:1.2rem 1.4rem; border:1px solid var(--edge); border-radius:1rem; background:rgba(255,255,255,.08); backdrop-filter: blur(12px); text-align:center; box-shadow:0 12px 40px rgba(0,0,0,.35)} .hidden{display:none !important} .flash{position:fixed;inset:0;pointer-events:none;opacity:0;transition:opacity .12s ease;background:radial-gradient(60% 40% at 50% 70%, rgba(106,224,255,.25), transparent 70%)} .flash.show{opacity:1} </style> </head> <body> <div id="hud"> <div class="pill" id="score">Score 0</div> <div class="pill" id="combo">Combo 0</div> <div class="pill" id="acc">ACC 100%</div> <div class="pill">BPM <span id="bpmLabel">120</span></div> <div> <button class="btn" id="bpmDown">−</button> <button class="btn" id="bpmUp">+</button> <button class="btn" id="freeBtn" title="Play tones anytime (no scoring)">Free Play: Off</button> </div> </div> <main> <div class="grid" id="padGrid" aria-label="Tone pads"> <button class="pad k1" data-idx="0"><span class="label">Pad 1</span><span class="key">A</span></button> <button class="pad k2" data-idx="1"><span class="label">Pad 2</span><span class="key">S</span></button> <button class="pad k3" data-idx="2"><span class="label">Pad 3</span><span class="key">D</span></button> <button class="pad k4" data-idx="3"><span class="label">Pad 4</span><span class="key">F</span></button> </div> <div class="controls"> <span>Hit the pad that lights up on each beat • Keys: <span class="kbd">A</span> <span class="kbd">S</span> <span class="kbd">D</span> <span class="kbd">F</span></span> </div> </main> <div id="overlay"> <div id="panel"> <h1>Beat Lights</h1> <p>Press the pad that lights up to the beat. Make melodies while keeping your combo!</p> <button class="btn" id="playBtn" type="button" autofocus>▶ Start</button> <p style="opacity:.8;margin-top:.6rem">Tip: Press <b>Enter</b> or <b>Space</b> to start.</p> </div> </div> <div id="flash" class="flash"></div> <script> (()=>{ // ---------- Audio ---------- let ctx=null, master=null; function initAudio(){ if(ctx) return; const Ctx = window.AudioContext || window.webkitAudioContext; ctx = new Ctx(); master = ctx.createGain(); master.gain.value = 0.9; master.connect(ctx.destination); } function tone(freq, dur=0.2, type='sine', gain=0.18){ if(!ctx) initAudio(); const o = ctx.createOscillator(); const g = ctx.createGain(); o.type = type; o.frequency.value = freq; g.gain.value = gain; o.connect(g).connect(master); const t = ctx.currentTime; g.gain.setValueAtTime(0, t); g.gain.linearRampToValueAtTime(gain, t+0.01); g.gain.exponentialRampToValueAtTime(0.0001, t+dur); o.start(t); o.stop(t+dur+0.02); } // ---------- Game State ---------- const pads = [...document.querySelectorAll('.pad')]; const flash = document.getElementById('flash'); const hudScore = document.getElementById('score'); const hudCombo = document.getElementById('combo'); const hudAcc = document.getElementById('acc'); const bpmLabel = document.getElementById('bpmLabel'); const bpmDown = document.getElementById('bpmDown'); const bpmUp = document.getElementById('bpmUp'); const freeBtn = document.getElementById('freeBtn'); let bpm = 120; bpmLabel.textContent = bpm; let playing = false, freePlay = false; let beatTimer = 0, beatDur = 60 / bpm; // seconds per beat let step = 0; let cueIdx = 0; // which pad should the player press let allowInput = false; // only within beat window let windowMs = 220; // hit window ±ms const scaleFreq = [261.63, 329.63, 392.00, 493.88]; // C4, E4, G4, B4 const keyMap = { 'a':0, 's':1, 'd':2, 'f':3, 'ArrowLeft':0, 'ArrowDown':1, 'ArrowRight':2, 'ArrowUp':3 }; // Scoring const S = { score:0, combo:0, total:0, weighted:0 }; function updateHUD(){ const acc = S.total ? Math.round((S.weighted/S.total)*100) : 100; hudScore.textContent = 'Score ' + S.score; hudCombo.textContent = 'Combo ' + S.combo; hudAcc.textContent = 'ACC ' + acc + '%'; } function flashFX(ok=true){ flash.style.background = ok ? 'radial-gradient(60% 40% at 50% 70%, rgba(72,209,138,.35), transparent 70%)' : 'radial-gradient(60% 40% at 50% 70%, rgba(255,107,107,.35), transparent 70%)'; flash.classList.add('show'); setTimeout(()=>flash.classList.remove('show'), 110); } // Make a simple looping melody (16 beats, values 0..3) const pattern = Array.from({length:16}, (_,i)=> (i%4===0) ? 0 : [1,2,3][(Math.random()*3)|0]); function setBPM(v){ bpm = Math.max(80, Math.min(180, v)); bpmLabel.textContent=bpm; beatDur = 60/bpm; } bpmDown.onclick=()=>setBPM(bpm-5); bpmUp.onclick=()=>setBPM(bpm+5); freeBtn.onclick=()=>{ freePlay=!freePlay; freeBtn.textContent = 'Free Play: ' + (freePlay?'On':'Off'); }; // ---------- Input ---------- function pressPad(idx){ // sound & visual tone(scaleFreq[idx], 0.22, 'sine', 0.23); const p = pads[idx]; p.classList.add('good'); setTimeout(()=>p.classList.remove('good'), 120); if(!playing || freePlay) return; if(!allowInput){ // too early/late S.combo = 0; flashFX(false); updateHUD(); return; } if(idx === cueIdx){ // correct hit S.combo++; S.score += 100 + Math.min(500, S.combo*5); S.total++; S.weighted += 1; flashFX(true); updateHUD(); allowInput = false; // prevent multi-hits this beat }else{ S.combo = 0; S.total++; // counts against acc flashFX(false); updateHUD(); allowInput = false; } } pads.forEach(p=>p.addEventListener('click', e=> pressPad(+p.dataset.idx))); window.addEventListener('keydown', e=>{ const idx = keyMap[e.key.toLowerCase()]; if(idx!==undefined){ e.preventDefault(); pressPad(idx); } }, {passive:false}); // ---------- Beat Loop ---------- function lightOn(idx){ const p = pads[idx]; p.classList.add('light'); setTimeout(()=>p.classList.remove('light'), Math.min(200, beatDur*1000*0.7)); } function tick(dt){ if(!playing) return; beatTimer += dt; if(beatTimer >= beatDur){ beatTimer -= beatDur; // New beat step = (step + 1) % pattern.length; cueIdx = pattern[step]; lightOn(cueIdx); tone(90, 0.05, 'triangle', 0.12); // metronome tick // open hit window shortly after tick (human reaction) allowInput = true; setTimeout(()=>{ allowInput = false; S.total++; }, windowMs); } } // ---------- Main Loop ---------- let last = performance.now(); function loop(now){ const dt = Math.min(0.033, (now-last)/1000); last = now; tick(dt); requestAnimationFrame(loop); } requestAnimationFrame(loop); // Expose start window.start = () => { initAudio(); ctx.resume?.(); S.score=0; S.combo=0; S.total=0; S.weighted=0; updateHUD(); playing = true; beatTimer = 0; step = -1; // so first tick shows pattern[0] }; })(); </script> <!-- ===== StartFix v3 (must stay at end) ===== --> <script> (function startFixV3(){ function bind(){ const overlay=document.getElementById('overlay'), playBtn=document.getElementById('playBtn'); if(!overlay||!playBtn){requestAnimationFrame(bind);return;} overlay.style.cssText+='position:fixed;inset:0;z-index:2147483647;display:grid;place-items:center;pointer-events:auto;'; playBtn.style.pointerEvents='auto'; playBtn.style.cursor='pointer'; let started=false; function go(){ if(started) return; started=true; try{ typeof window.start==='function' && window.start(); }catch(e){} overlay.classList.add('hidden'); overlay.style.display='none'; try{ const Ctx=window.AudioContext||window.webkitAudioContext; if(Ctx){ const ctx=new Ctx(); ctx.resume?.(); const o=ctx.createOscillator(), g=ctx.createGain(); g.gain.value=0; o.connect(g).connect(ctx.destination); o.start(); o.stop(ctx.currentTime+0.01); } }catch(e){} } playBtn.addEventListener('click',(e)=>{e.preventDefault();e.stopPropagation();go();},{passive:false}); playBtn.addEventListener('touchend',(e)=>{e.preventDefault();e.stopPropagation();go();},{passive:false}); window.addEventListener('keydown',(e)=>{ if((e.key==='Enter'||e.key===' ')&&!overlay.classList.contains('hidden')){ e.preventDefault(); go(); }},{passive:false}); // self-heal for editors/iframes for ~1.5s let n=0;(function bump(){n++;try{document.body.appendChild(overlay); overlay.style.zIndex='2147483647';}catch(e){} if(n<90 && !overlay.classList.contains('hidden')) requestAnimationFrame(bump);})(); } if(document.readyState==='loading') document.addEventListener('DOMContentLoaded', bind); else bind(); })(); </script> </body> </html>
Save file
Quick jump
open a path
Open