Classroom evidence hunt

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>Classroom evidence hunt</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}}.hunt-ledger{background:#fffdf6;border:1px solid #d1c6a7;border-top:5px solid #a17a32;padding:24px}.hunt-row{display:grid;grid-template-columns:1.2fr 1fr;gap:8px;padding:16px 0;border-bottom:1px solid #dbd2bb}.hunt-row small{grid-column:1/-1}.object{background:#faf6e9;border:1px dashed #ccbd98;padding:16px}@media(max-width:540px){.hunt-ledger{padding:18px}.hunt-row{grid-template-columns:1fr}}</style></head><body style="--bg:#f5f2e9;--accent:#866329;--ink:#403b2d"><main><header><div class="kicker">Working example</div><h1>Classroom evidence hunt</h1><p class="muted">Match a criterion to a supplied card, and keep “not found” tied to what was checked.</p></header><section class="hunt-ledger"><div class="kicker">Fictional supplied-card demonstration · teacher expectations</div><div class="hunt-row"><b>P1 · Blue writing tool</b><span>O1 · Matched</span><small>Blue pencil: both features support the criterion.</small></div><div class="hunt-row"><b>P2 · Measuring tool</b><span>O3 · Matched</span><small>Ruler with centimeter marks.</small></div><div class="hunt-row"><b>P3 · Green notebook</b><span>Not found in O1–O3</span><small>All three supplied cards checked; O2 is red.</small></div></section><section class="panel"><h2>Supplied objects · seated alternative</h2><div class="thirds"><div class="object"><b>O1 · Pencil</b><p>Blue, with a six-sided body.</p></div><div class="object"><b>O2 · Notebook</b><p>Red and closed.</p></div><div class="object"><b>O3 · Ruler</b><p>Clear, marked in centimeters.</p></div></div></section><section class="panel"><label for="packet">Packet version<select id="packet"><option value="demo">Supplied-card local record</option><option value="real">Blank real-classroom observation sheet</option></select></label><div id="demo"><h2 style="margin-top:20px">Review a local practice record</h2><label for="prompt">Criterion prompt<select id="prompt"><option value="P1">P1 · Blue writing tool</option><option value="P2">P2 · Measuring tool</option><option value="P3">P3 · Green notebook</option></select></label><div class="grid" style="margin-top:16px"><label for="status">Search status<select id="status"><option value="notchecked">Not checked</option><option value="matched">Matched · proposed</option><option value="notfound">Not found · declared scope checked</option><option value="review">Needs review · unresolved</option></select></label><label for="candidate">Candidate card<select id="candidate"><option value="">No candidate recorded</option><option value="O1">O1 · Blue pencil</option><option value="O2">O2 · Red notebook</option><option value="O3">O3 · Clear ruler</option></select></label><label for="evidence">Observed feature / supporting evidence<input id="evidence" value="" inputmode="text" autocomplete="off"></label><label for="source">Source card / location<input id="source" value="" inputmode="text" autocomplete="off"></label><label for="scope">Declared checked scope · enter O1–O3<input id="scope" value="" inputmode="text" autocomplete="off"></label><label for="unresolved">Unresolved detail<input id="unresolved" value="" inputmode="text" autocomplete="off"></label></div><p><label><input id="checked" type="checkbox">I have checked all three supplied cards for this criterion.</label></p><div class="actions"><button type="button" id="inspect">Check record</button><button type="button" id="reset">Reset local records</button></div><p id="finding" class="note" aria-live="polite">P1 is Not checked.</p></div><div id="real" hidden><h2 style="margin-top:24px">Real observation sheet · blank</h2><p>Teacher-approved search area: ____________________</p><p>Record criterion, status, candidate, observed feature, source/location, checked scope, and unresolved detail.</p><div id="blankRows"></div><p>Different supported objects may qualify. Supplied-card expectations are not real classroom findings.</p></div></section><details><summary>Preparation, status meanings, and debrief</summary><p>Use teacher-approved reachable objects or the seated cards. No rummaging, personal clothing inspection, camera, or account is needed. Leave real observations blank until made. A closed notebook does not establish its contents, manufacturer, or origin.</p><p>Not checked means unvisited. Not found requires a declared examined scope; a blank candidate does not imply a completed search. Matched needs an object, evidence, and source. Unknown color remains unresolved. This checker flags structure and known card contradictions; it cannot judge arbitrary prose or verify an actual room.</p><p>Ask why blue alone is insufficient for P1, why clear alone is insufficient for P2, and what was checked before P3 became Not found. Keep the native paper sheet and actual teacher review authoritative.</p></details><footer>Local example · No information is sent or saved.</footer></main><script>const $=id=>document.getElementById(id);const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));function gcd(a,b){return b?gcd(b,a%b):a}function rat(n,d=1n){const g=gcd(n,d);return {n:n/g,d:d/g}}function mul(a,b){return rat(a.n*b.n,a.d*b.d)}function div(a,b){return rat(a.n*b.d,a.d*b.n)}function rounded(r,p=6){const scale=10n**BigInt(p),q=(r.n*scale*2n+r.d)/(2n*r.d),s=q.toString().padStart(p+1,'0');return p?s.slice(0,-p)+'.'+s.slice(-p):s}function show(r,unit=''){if(r.n>0n&&r.n*1000000n<r.d)return '<0.000001 '+unit;return '≈ '+rounded(r,6).replace(/([.][0-9]*?)0+$/,'$1').replace(/[.]$/,'')+' '+unit}function decimal(s,name,max=1000000,places=6){if(!new RegExp('^[0-9]+(?:[.][0-9]{1,'+places+'})?$').test(s)||s.length>35)throw Error(name+': enter a nonnegative dot-decimal number, up to '+places+' decimal places.');let [a,b='']=s.split('.');const r=rat(BigInt(a+b),10n**BigInt(b.length));if(r.n>BigInt(max)*r.d)throw Error(name+': maximum is '+max+'.');return r}function whole(s,name,max){if(!/^[0-9]+$/.test(s)||s.length>15||Number(s)>max)throw Error(name+': enter an integer from 0 to '+max+'.');return Number(s)}function onForm(fn,clear){$('form').addEventListener('submit',e=>{e.preventDefault();fn()});$('form').addEventListener('input',clear);$('form').addEventListener('change',clear)}

const criteria={P1:'Blue writing tool',P2:'Measuring tool',P3:'Green notebook'};const blank=()=>({status:'notchecked',candidate:'',evidence:'',source:'',scope:'',unresolved:'',checked:false});let records={P1:blank(),P2:blank(),P3:blank()},current='P1';function inspect(p,r){if(r.status==='notchecked')return {state:'Not checked',message:'No completed search is declared.'};if(r.candidate&&!['O1','O2','O3'].includes(r.candidate))return {state:'Incomplete',message:'Unsupported supplied card ID.'};if(r.status==='review')return {state:r.unresolved.trim()?'Needs review':'Incomplete',message:r.unresolved.trim()?'Retain the candidate; a teacher must resolve the stated uncertainty.':'Record the unresolved detail.'};if(r.status==='matched'){if(!r.candidate||!r.evidence.trim()||!r.source.trim())return {state:'Incomplete',message:'Matched needs a candidate, evidence, and source.'};const expected={P1:'O1',P2:'O3',P3:null};if(r.candidate!==expected[p])return {state:'Needs review',message:p==='P3'&&r.candidate==='O2'?'Color mismatch: O2 is red, not green. Proposed entry retained.':'The supplied card does not support this criterion. Proposed entry retained.'};return {state:'Recorded for review',message:'Known card supports the criterion. A teacher must still review the entered evidence and source.'}}if(r.status==='notfound'){if(!r.checked||!r.scope.trim()||!r.source.trim())return {state:'Incomplete',message:'Not found needs a declared checked scope, source, and all-card inspection confirmation.'};if(!['O1–O3','O1-O3','O1, O2, O3'].includes(r.scope.trim()))return {state:'Needs review',message:'This supplied-card record can establish only the O1–O3 scope. It cannot verify a room or a different set.'};if(p==='P1'||p==='P2')return {state:'Needs review',message:'The supplied set contains a match: '+(p==='P1'?'O1':'O3')+'. Retain the claim for review.'};return {state:'Bounded not found',message:'No green notebook is described in O1–O3. This does not describe every classroom.'}}return {state:'Incomplete',message:'Choose a supported search status.'}}function save(){const r=records[current];['status','candidate','evidence','source','scope','unresolved'].forEach(x=>r[x]=$(x).value);r.checked=$('checked').checked;$('finding').textContent='Record changed. Check again; no current finding.'}function load(){const r=records[current];['status','candidate','evidence','source','scope','unresolved'].forEach(x=>$(x).value=r[x]);$('checked').checked=r.checked;$('finding').textContent=current+' is '+(r.status==='notchecked'?'Not checked':'pending a current record check')+'.'}['status','candidate','evidence','source','scope','unresolved','checked'].forEach(x=>$(x).addEventListener('input',save));['status','candidate'].forEach(x=>$(x).addEventListener('change',save));$('prompt').onchange=()=>{current=$('prompt').value;load()};$('inspect').onclick=()=>{save();const result=inspect(current,records[current]);if(result.state==='Needs review'){records[current].status='review';$('status').value='review'}$('finding').textContent=result.state+' — '+result.message};$('reset').onclick=()=>{records={P1:blank(),P2:blank(),P3:blank()};current='P1';$('prompt').value='P1';load()};$('packet').onchange=()=>{$('demo').hidden=$('packet').value==='real';$('real').hidden=$('packet').value!=='real'};$('blankRows').innerHTML=Object.entries(criteria).map(([id,c])=>'<div style="margin:24px 0"><b>'+id+' · '+c+'</b><p>Status / candidate / feature / source / checked scope / unresolved detail:</p><div class="line"></div><div class="line"></div></div>').join('');load();</script></body></html>