Five-round sequence practice
HTML for this example
Select the code and use your copy shortcut. Changes in this preview are temporary.
<!doctype html><html lang="en-US"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Five-round sequence practice</title><style>*{box-sizing:border-box}html{color-scheme:light}body{margin:0;background:var(--bg,#eef1f4);color:var(--ink,#233449);font:16px/1.5 system-ui,-apple-system,Segoe UI,sans-serif}main{max-width:1040px;margin:auto;padding:26px 28px 44px}header{margin-bottom:20px}h1{font-size:clamp(26px,4vw,36px);letter-spacing:-.035em;line-height:1.15;margin:5px 0 10px}h2{font-size:21px;line-height:1.3;margin:0 0 15px}h3{font-size:17px;margin:0 0 9px}p{margin:8px 0 16px}.kicker{font-size:12px;text-transform:uppercase;letter-spacing:.12em;font-weight:750;color:var(--accent,#315b87)}.muted,small{color:#556473}.panel{margin:20px 0;padding:24px;border:1px solid var(--line,#ccd5df);border-radius:10px;background:#fff}.hero{padding:24px;background:var(--hero,#183b5c);color:#fff;border-radius:12px;margin:18px 0}.hero .kicker,.hero small{color:#d9e5ef}.big{font-size:clamp(32px,5vw,52px);line-height:1.15;font-weight:750;letter-spacing:-.035em;overflow-wrap:anywhere;margin:10px 0 15px}.row{display:flex;flex-wrap:wrap;gap:15px;align-items:end}.row>label{flex:1;min-width:140px}.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.thirds{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px}label{display:block;font-size:14px;font-weight:650}input,select,textarea{font:inherit;font-size:16px;color:inherit;display:block;width:100%;margin-top:6px;padding:11px 12px;border:1px solid #a9b4c1;border-radius:6px;background:white;min-width:0}input[type=checkbox]{display:inline;width:auto;margin:0 8px 0 0;accent-color:var(--accent,#315b87)}textarea{min-height:100px;resize:vertical}button{font:inherit;font-weight:650;min-height:44px;border:1px solid var(--accent,#315b87);border-radius:6px;background:var(--accent,#315b87);color:white;padding:10px 16px;cursor:pointer}button.secondary{background:white;color:var(--accent,#315b87)}button:disabled{opacity:.5;cursor:default}button[aria-pressed=true]{box-shadow:0 0 0 3px #eab655}button:hover:not(:disabled){filter:brightness(.94)}:focus-visible{outline:3px solid #e5a72f;outline-offset:3px}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0 0}[hidden]{display:none!important}.error{color:#a3232a;font-weight:650}.error:not(:empty){padding:12px;background:#fff0ed;border-left:4px solid #ab3439;margin:14px 0}.note{padding:14px;background:#edf2f6;border-radius:6px;margin:14px 0}.mono,pre{font-family:ui-monospace,Consolas,monospace;font-variant-numeric:tabular-nums}pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px;line-height:1.7;margin:0}.mono{overflow-wrap:anywhere}table{width:100%;border-collapse:collapse;table-layout:fixed;font-size:14px}th,td{text-align:left;vertical-align:top;overflow-wrap:anywhere;padding:11px 8px;border-bottom:1px solid #d4dce4}th{font-size:12px;text-transform:uppercase;letter-spacing:.035em;color:#536372}th:first-child,td:first-child{padding-left:0}.tag{display:inline-block;padding:4px 8px;border:1px solid currentColor;border-radius:4px;font-size:12px;font-weight:750}.rule{border-top:1px solid #cbd4dd;padding-top:18px}.line{height:30px;border-bottom:1px solid #aab5bf}.stat{font-size:34px;line-height:1.15;font-weight:750}.stat small{font:14px system-ui;display:block;margin-top:8px}details{margin:20px 0;border-top:1px solid #cbd4dd;padding:18px 0}summary{font-weight:700;cursor:pointer}details p{margin-top:15px}a{color:var(--accent,#315b87)}footer{font-size:13px;color:#556473;margin-top:25px}fieldset{min-width:0;border:1px solid #c8d2db;border-radius:7px;padding:18px;margin:15px 0}legend{font-weight:750;padding:0 6px}@media(max-width:720px){main{padding:20px}.panel,.hero{padding:20px}.thirds{gap:10px}}@media(max-width:540px){main{padding:16px}.grid,.thirds{grid-template-columns:1fr}.panel,.hero{padding:18px}.row{gap:12px}.row>label{min-width:100px}h1{font-size:27px}th,td{padding:10px 5px;font-size:13px}.big{font-size:37px}}.surface{background:white;border:1px solid #ccd5df;border-radius:10px;padding:24px;margin:18px 0}.metrics{display:flex;gap:34px;flex-wrap:wrap}.metric b{font-size:clamp(32px,5vw,52px);line-height:1.1;display:block;letter-spacing:-.04em}.metric span{display:block;margin-top:8px;font-size:14px}.strip{display:grid;grid-template-columns:repeat(10,minmax(0,1fr));gap:7px;margin:22px 0}.unit{padding:10px 3px;text-align:center;background:#e5f0eb;border-bottom:4px solid #327660;font-size:13px;font-weight:700}.unit.rework{background:#fff0d5;border-color:#aa701d}.unit.fail{background:#f9e2e0;border-color:#ab3d35}.ledger-row{display:grid;grid-template-columns:100px 1fr 140px;gap:18px;padding:18px 0;border-bottom:1px solid #d2dbe3;align-items:start}.ledger-row p{margin:5px 0}.amount{text-align:right;font-size:22px;font-weight:750}.pill{display:inline-block;border-radius:20px;background:#e7edf2;padding:5px 10px;font-size:12px;font-weight:700}.timeline{border-left:3px solid #c7d4de;padding:0 0 0 22px;margin:16px 0}.timeline article{padding:10px 0 18px}.timeline h3{margin-bottom:5px}.timeline p{margin:5px 0}.artifact{font-family:Georgia,serif}.warning{background:#fff3db;border-left:4px solid #a66d18;padding:15px}.empty{color:#5d6771;font-style:italic}.check{color:#22694f}.bad{color:#9a332e}button.linklike{padding:8px 12px;min-height:40px;background:white;color:var(--accent,#315b87)}@media(max-width:540px){.surface{padding:18px}.ledger-row{grid-template-columns:65px 1fr;gap:12px}.ledger-row .amount{grid-column:2;text-align:left}.strip{gap:3px}.unit{font-size:11px;padding:8px 0}.metrics{gap:22px}.metric b{font-size:38px}}.sequence{max-width:650px;margin:auto;border-top:6px solid #79518d}.sequence .metrics{justify-content:space-between}.sequence h2{margin:6px 0}.cue{min-height:50px;padding:13px;background:#f0ebf5;font-size:18px;font-weight:700}.symbols{display:grid;grid-template-columns:1fr 1fr;gap:16px}.symbol{min-height:125px;background:#f5f1f8;color:#493956;border:2px solid #c7b5d3;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:5px;opacity:1!important}.symbol span{font:45px/1 Georgia,serif}.symbol b{font-size:15px}.symbol[aria-pressed=true]{background:#634878;color:white;border-color:#352341;box-shadow:inset 0 0 0 4px #dcc0ed}.symbol:disabled{cursor:default}.symbol:enabled:hover{background:#e3d5ec}@media(max-width:540px){.symbols{gap:10px}.symbol{min-height:105px}.symbol span{font-size:38px}.sequence .metrics{gap:15px}}</style></head><body style="--bg:#f3f0f6;--accent:#6e4f83"><main><header><div class="kicker">Original JavaScript sequence game · untimed</div><h1>Five-round sequence practice</h1><p class="muted">Watch the numbered symbols, then repeat the complete prefix in order.</p></header><section class="surface sequence"><div class="metrics"><div><span class="kicker">Phase</span><h2 id="phase"></h2></div><div><span class="kicker">Round</span><h2 id="round"></h2></div><div><span class="kicker">Completed</span><h2 id="completed"></h2></div></div><p id="cue" class="cue" role="status" aria-live="polite"></p><div class="symbols"><button type="button" id="symbol1" class="symbol s1"><span aria-hidden="true">○</span><b>1 Circle</b></button><button type="button" id="symbol2" class="symbol s2"><span aria-hidden="true">△</span><b>2 Triangle</b></button><button type="button" id="symbol3" class="symbol s3"><span aria-hidden="true">□</span><b>3 Square</b></button><button type="button" id="symbol4" class="symbol s4"><span aria-hidden="true">☆</span><b>4 Star</b></button></div><p id="response" class="note"></p><div class="actions"><button type="button" id="start">Start</button><button type="button" id="replay" class="secondary">Replay round</button><button type="button" id="next" class="secondary">Next round</button><button type="button" id="reset" class="secondary">Reset</button></div></section><section class="panel"><label for="mode">Sequence mode<select id="mode"><option value="play">Ordinary play · five random IDs, repeats allowed</option><option value="dev">Development fixture · 1, 3, 1, 4, 2</option></select></label><p id="modeNote"></p></section><details><summary>Practice timing and session rules</summary><p>A symbol stays on for 350 ms, then off for 150 ms. Guesses count only in Response, through one native click handler. There is no response deadline. Replay resets the response position but earns no extra completed-round credit.</p><p>Leaving the window or hiding the tab interrupts an active session; Start creates a fresh one. Won and Lost remain terminal until Reset. This original symbol game uses no toy artwork, sounds, hardware, score storage, or memory-improvement claim.</p></details><footer>Local session only · No network or saved progress. Keep maintained source records authoritative.</footer></main><script>const $=id=>document.getElementById(id);const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
const names=['','Circle','Triangle','Square','Star'];let game={phase:'idle',sequence:[],round:0,index:0,completed:0,active:0,message:'Ready. Start to watch the first symbol.'},generation=0,timers=[];
function cancel(){generation++;timers.forEach(clearTimeout);timers=[]}function schedule(fn,ms,token){const t=setTimeout(()=>{if(token===generation)fn()},ms);timers.push(t)}
function render(){const p=game.phase;$('phase').textContent=p[0].toUpperCase()+p.slice(1);$('round').textContent=game.round+' / 5';$('completed').textContent=game.completed+' / 5';$('cue').textContent=game.active?'Watch: '+game.active+' '+names[game.active]:game.message;$('response').textContent='Response progress: '+game.index+' / '+game.round+' positions matched.';for(let i=1;i<=4;i++){const b=$('symbol'+i);b.disabled=p!=='response';b.setAttribute('aria-pressed',String(game.active===i))}$('start').disabled=p!=='idle';$('mode').disabled=p!=='idle';$('replay').disabled=!['response','between'].includes(p);$('next').disabled=p!=='between';$('modeNote').textContent=$('mode').value==='dev'?'Inspectable practice key: 1 → 3 → 1 → 4 → 2.':'At Start, choose five IDs independently from 1–4. Repeats, including a whole repeated sequence, are possible.'}
function playback(){cancel();const token=generation;game.phase='playback';game.index=0;game.active=0;game.message='Watch the sequence. Guesses are unavailable.';render();function show(i){if(token!==generation)return;game.active=game.sequence[i];render();schedule(()=>{game.active=0;game.message='Watch · off interval';render();schedule(()=>{if(i+1<game.round)show(i+1);else{game.phase='response';game.index=0;game.message='Your turn. Repeat the whole prefix.';render()}},150,token)},350,token)}show(0)}
function start(){if(game.phase!=='idle')return false;game.sequence=$('mode').value==='dev'?[1,3,1,4,2]:Array.from({length:5},()=>1+Math.floor(Math.random()*4));game.round=1;game.index=0;game.completed=0;playback();return true}
function guess(id){if(game.phase!=='response'||![1,2,3,4].includes(id))return false;if(id!==game.sequence[game.index]){game.phase='lost';game.message='Lost at position '+(game.index+1)+'. Expected '+game.sequence[game.index]+' '+names[game.sequence[game.index]]+'. Reset to try again.';render();return true}game.index++;game.message='Matched '+game.index+' of '+game.round+'.';if(game.index===game.round){game.completed=Math.max(game.completed,game.round);game.phase=game.round===5?'won':'between';game.message=game.phase==='won'?'All five rounds complete. Reset for another game.':'Round complete. Choose Next round or replay this prefix.'}render();return true}
function replay(){if(!['response','between'].includes(game.phase))return false;playback();return true}function next(){if(game.phase!=='between'||game.round>=5)return false;game.round++;playback();return true}function reset(interrupted=false){cancel();game={phase:'idle',sequence:[],round:0,index:0,completed:0,active:0,message:interrupted?'Interrupted. Start a fresh sequence when ready.':'Ready. Start to watch the first symbol.'};render()}function interrupt(){if(['playback','response','between'].includes(game.phase))reset(true)}
for(let i=1;i<=4;i++)$('symbol'+i).addEventListener('click',()=>guess(i));$('start').onclick=start;$('replay').onclick=replay;$('next').onclick=next;$('reset').onclick=()=>reset();$('mode').addEventListener('change',render);window.addEventListener('blur',interrupt);document.addEventListener('visibilitychange',()=>{if(document.hidden)interrupt()});render();</script></body></html>