Same counters · number practice — Let learners connect a visible quantity to its numeral and written cardinal name, explaining why changing object arrangement does not…

HTML for this example

Select the code and use your copy shortcut. Changes in this preview are temporary.

<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Same counters · number practice</title><style>
*{box-sizing:border-box}body{margin:0;background:#fff4e4;color:#41315e;font:17px/1.5 system-ui,sans-serif}main{max-width:1000px;margin:auto;padding:30px}h1{font-size:clamp(32px,5vw,47px);letter-spacing:-.04em;line-height:1.12;margin:6px 0 11px}h2{font-size:23px;margin:0 0 14px}p{margin:0 0 12px}.eyebrow{font-size:12px;font-weight:750;letter-spacing:.12em;text-transform:uppercase;color:#8d5d75}.small{font-size:14px;color:#786781}.set-tabs{display:flex;gap:10px;flex-wrap:wrap;margin:22px 0 17px}button{min-height:46px;padding:10px 18px;border:2px solid #85609b;border-radius:10px;background:#fff;color:#60417a;font:700 16px system-ui;cursor:pointer}button[aria-pressed=true]{background:#775195;color:white;border-color:#775195}button.primary{background:#775195;color:white}button:disabled{opacity:.5;cursor:default}:focus-visible{outline:3px solid #cc6e31;outline-offset:3px}.tray{background:#fffefd;border:2px solid #e1bf9d;border-radius:24px;padding:22px 10px 17px;box-shadow:0 7px 0 #efdbc0}.counters{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));max-width:640px;margin:0 auto;align-items:start;min-height:150px}.counter{border:0;background:none;padding:6px 0;min-height:85px;width:100%;min-width:0;color:#41315e;display:flex;align-items:center;flex-direction:column;font-size:12px;border-radius:10px}.counter[aria-pressed=true]{background:#f3e9fb;color:#41315e}.disc{height:47px;width:47px;border:3px solid #ad654b;border-radius:50%;background:#efb193;display:grid;place-items:center;color:#6b3931;font-size:25px;font-weight:800}.counter .id{font-size:11px;margin-top:6px}.counter .mark{font-size:13px;min-height:20px}.counters.scattered{grid-template-columns:repeat(4,minmax(0,1fr));max-width:430px;min-height:220px}.empty-tray{min-height:150px;display:grid;place-items:center;color:#9b8b98;font-size:20px}.tray-footer{display:flex;gap:12px;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:0 10px}.arrangement{font-size:14px;margin:0;color:#786781}.work{display:grid;grid-template-columns:1fr 1fr;gap:25px;margin-top:28px}.panel{background:#fffefd;border:1px solid #e6d6dc;border-radius:15px;padding:23px}.choices{display:flex;gap:9px;flex-wrap:wrap}.choices button{flex:1;min-width:54px}.number-choice{font-size:28px}.words button{font-size:17px;padding:10px}.feedback{margin-top:22px;background:#f0e6f6;border-left:5px solid #a17abb;padding:19px;border-radius:6px}.feedback strong{display:block;font-size:20px}.feedback p{font-size:15px;margin:6px 0}.actions{display:flex;gap:9px;flex-wrap:wrap;margin-top:20px}.actions button{flex:1}.hint{margin-top:13px;font-size:15px}.explain{margin-top:25px;padding:20px;border-top:1px solid #e3c9c6}label{font-size:14px;font-weight:650;display:block}textarea{font:16px/1.5 system-ui;width:100%;min-height:80px;padding:11px;border:1px solid #af98b6;border-radius:7px;display:block;margin:7px 0;background:#fffefd;color:#41315e}details{margin-top:22px;border-top:1px solid #e3c9c6;padding-top:16px}summary{font-weight:700;cursor:pointer;min-height:44px}.footer{font-size:13px;color:#786781;margin:25px 0}[hidden]{display:none!important}@media(max-width:650px){main{padding:23px 14px}.work{grid-template-columns:1fr;gap:18px}.panel{padding:20px}.disc{width:37px;height:37px;font-size:22px}.counter{min-height:85px}.set-tabs button{flex:1;padding:10px}.tray-footer button{width:100%}.counters{min-height:140px}.tray{padding-top:20px}}@media(max-width:380px){main{padding:20px 12px}.panel{padding:17px}.disc{width:34px;height:34px}.tray-footer{padding:0 4px}.number-choice{padding:8px}}
</style></head><body><main><p class="eyebrow">Count · choose · rearrange</p><h1>How many counters are in this tray?</h1><p>Mark each counter once, then choose its numeral and number name.</p><div class="set-tabs"><button type="button" id="set-empty" aria-pressed="false">Empty tray</button><button type="button" id="set-three" aria-pressed="false">Three counters</button><button type="button" id="set-seven" aria-pressed="true">Seven counters</button></div><section class="tray" aria-label="Countable counter tray"><div id="counters" class="counters"></div><div id="empty-tray" class="empty-tray" hidden>No counters in this tray.</div><div class="tray-footer"><p id="arrangement" class="arrangement">Seven counters in a row. Tap a counter to toggle its mark.</p><button type="button" id="arrange">Scatter the same seven</button></div><p id="set-description" class="small" style="padding:12px 10px 0;margin:0">Seven counters: S1, S2, S3, S4, S5, S6, S7. Each is shown once.</p><p id="mark-status" class="small" style="padding:0 10px;margin-top:7px">No counters marked.</p></section><div class="work"><section class="panel"><h2>1. Choose the numeral</h2><div class="choices"><button type="button" id="number-0" class="number-choice" aria-pressed="false">0</button><button type="button" id="number-3" class="number-choice" aria-pressed="false">3</button><button type="button" id="number-7" class="number-choice" aria-pressed="false">7</button><button type="button" id="number-8" class="number-choice" aria-pressed="false">8</button></div></section><section class="panel"><h2>2. Choose the number name</h2><div class="choices words"><button type="button" id="word-zero" aria-pressed="false">zero</button><button type="button" id="word-three" aria-pressed="false">three</button><button type="button" id="word-seven" aria-pressed="false">seven</button><button type="button" id="word-eight" aria-pressed="false">eight</button></div></section></div><div class="actions"><button type="button" id="check" class="primary">Check my choices</button><button type="button" id="hint">Counting hint</button><button type="button" id="reset">Reset practice</button></div><section class="feedback" role="status"><strong id="verdict">Make both choices.</strong><p id="feedback">A blank answer is unanswered, even when the tray is empty.</p></section><p id="hint-text" class="hint" hidden>Mark each counter once as you count. Check whether one was counted twice.</p><section class="explain"><label for="explanation">Tell a partner or teacher how you counted<textarea id="explanation" placeholder="What stayed the same when the counters moved?"></textarea></label><p class="small">Your explanation needs human review. It is not automatically graded.</p></section><details><summary>Teacher key and use notes · separate from the task</summary><p class="small">Empty tray → 0 / zero. T1–T3 → 3 / three. S1–S7 → 7 / seven. The same seven IDs appear once in each arrangement; marks stay with those IDs when they move. Marking changes the aid, not the quantity.</p><p class="small">Original fixed sets, not recorded learner results. The teacher confirms whether numeral and number-name reading demands fit the learners.</p></details><footer class="footer">This local practice does not collect student identities, store answers, report scores, time learners, diagnose counting ability, or establish mastery. Reset clears marks, choices, explanation, and feedback and restores the original seven-counter row.</footer></main><script>
'use strict';const $=id=>document.getElementById(id);const sets={empty:{ids:[],n:0,name:'zero'},three:{ids:['T1','T2','T3'],n:3,name:'three'},seven:{ids:['S1','S2','S3','S4','S5','S6','S7'],n:7,name:'seven'}};let current='seven',scattered=false,marks=new Set(),numeral=null,name=null;
function judge(set,num,word){if(num===null||word===null)return{title:'Incomplete: make both choices.',message:'A blank answer is unanswered; it is not the numeral 0.'};if(num===set.n&&word===set.name)return{title:set.n+' and '+set.name+' match this tray.',message:set.n===7?'The positions can change, but the same seven counter IDs remain.':set.n===0?'An empty tray contains no counters. Its numeral is 0 and its name is zero.':'Each of the three counters is counted once.'};return{title:'Try counting this same set again.',message:num===8?'Mark each counter once as you count. Check whether one was counted twice.':num!==set.n?'Count each counter once, then match the numeral to how many there are.':'The numeral matches. Choose the number name that describes that same quantity.'};}
function pending(){$('verdict').textContent='Not checked.';$('feedback').textContent='Check the current numeral and number-name choices.';$('hint-text').hidden=true;}
function render(){const set=sets[current];$('counters').replaceChildren();$('counters').className='counters'+(scattered?' scattered':'');$('counters').hidden=!set.ids.length;$('empty-tray').hidden=set.ids.length>0;set.ids.forEach((id,i)=>{const b=document.createElement('button');b.type='button';b.id='counter-'+id;b.className='counter';b.setAttribute('aria-label',id+(marks.has(id)?', marked':', unmarked'));b.setAttribute('aria-pressed',String(marks.has(id)));if(scattered){b.style.gridColumn=String([1,3,2,4,1,3,4][i]);b.style.gridRow=String([1,1,2,2,3,3,4][i]);}for(const[text,cls]of[['●','disc'],[id,'id'],[marks.has(id)?'✓ marked':'','mark']]){const span=document.createElement('span');span.textContent=cls==='disc'?(marks.has(id)?'✓':''):text;span.className=cls;b.appendChild(span);}b.addEventListener('click',()=>{if(marks.has(id))marks.delete(id);else marks.add(id);render();});$('counters').appendChild(b);});for(const key of Object.keys(sets))$('set-'+key).setAttribute('aria-pressed',String(current===key));for(const n of[0,3,7,8])$('number-'+n).setAttribute('aria-pressed',String(numeral===n));for(const word of['zero','three','seven','eight'])$('word-'+word).setAttribute('aria-pressed',String(name===word));$('arrange').disabled=current!=='seven';$('arrange').textContent=scattered?'Return to a row':'Scatter the same seven';$('arrangement').textContent=current==='seven'?(scattered?'Same seven counters, rearranged. Marks stay with their IDs.':'Seven counters in a row. Tap a counter to toggle its mark.'):current==='empty'?'The tray contains no counters.':'Three fixed counters. Tap to toggle marks.';$('set-description').textContent=current==='empty'?'A tray containing no counters.':(current==='seven'?'Seven':'Three')+' counters: '+set.ids.join(', ')+'. Each is shown once.';$('mark-status').textContent=marks.size?marks.size+' distinct counter'+(marks.size===1?'':'s')+' marked; quantity unchanged.':'No counters marked.';}
for(const key of Object.keys(sets))$('set-'+key).addEventListener('click',()=>{current=key;scattered=false;marks.clear();numeral=name=null;render();pending();});for(const n of[0,3,7,8])$('number-'+n).addEventListener('click',()=>{numeral=n;render();pending();});for(const word of['zero','three','seven','eight'])$('word-'+word).addEventListener('click',()=>{name=word;render();pending();});$('arrange').addEventListener('click',()=>{if(current!=='seven')return;scattered=!scattered;render();pending();});$('check').addEventListener('click',()=>{const r=judge(sets[current],numeral,name);$('verdict').textContent=r.title;$('feedback').textContent=r.message;});$('hint').addEventListener('click',()=>{$('hint-text').hidden=!$('hint-text').hidden;});$('reset').addEventListener('click',()=>{current='seven';scattered=false;marks.clear();numeral=name=null;$('explanation').value='';render();$('verdict').textContent='Make both choices.';$('feedback').textContent='A blank answer is unanswered, even when the tray is empty.';$('hint-text').hidden=true;});render();
</script></body></html>