RS01 • lesson study protocol — Define a research question, anticipate different learner reasoning, assign evidence collection and compare actual observations with…

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>RS01 • lesson study protocol</title><style>*{box-sizing:border-box}body{margin:0;background:var(--bg,#f3f7fa);color:var(--ink,#203342);font:16px/1.55 system-ui,Segoe UI,sans-serif}main{max-width:1100px;margin:auto;padding:28px 30px 50px}h1{font-size:clamp(27px,3.5vw,40px);line-height:1.18;letter-spacing:-.035em;margin:8px 0 12px}h2{font-size:21px;line-height:1.35;margin:0 0 16px}h3{font-size:18px}.eyebrow{color:var(--accent,#176783);font-size:12px;letter-spacing:.12em;font-weight:800;text-transform:uppercase}.intro,.muted,small{color:#516272}.intro{margin:0 0 24px}.panel{padding:24px;border:1px solid var(--line,#d6e0e7);border-radius:12px;background:white;margin:18px 0}.grid{display:grid;grid-template-columns:1fr 1fr;gap:22px}.grid>*{min-width:0}.controls{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0}button,input,textarea,select{font:inherit}button{border:1px solid var(--accent,#176783);background:var(--accent,#176783);color:white;padding:10px 16px;min-height:44px;border-radius:7px;font-weight:700;cursor:pointer}button.secondary{background:white;color:var(--accent,#176783)}button[aria-pressed=true]{background:var(--tint,#e3f2f8);color:var(--ink,#203342);box-shadow:inset 0 0 0 2px var(--accent,#176783)}button:hover{filter:brightness(.96)}:focus-visible{outline:3px solid #d56b00;outline-offset:3px}label{display:block;margin:12px 0 5px;font-size:14px;font-weight:650}input:not([type=checkbox]),select,textarea{width:100%;padding:10px 12px;min-height:44px;border:1px solid #94a5b2;background:white;color:inherit;border-radius:7px}textarea{resize:vertical;min-height:120px}input[type=checkbox]{width:20px;height:20px;margin-right:9px}label.inline{display:flex;align-items:center;font-weight:500;gap:7px}.result{padding:24px;background:var(--tint,#e3f2f8);border:1px solid var(--line,#c8dce7);border-radius:12px}.big{font-size:clamp(30px,5vw,48px);font-weight:780;line-height:1.25;letter-spacing:-.035em;margin:10px 0}.trace{font:15px/1.7 ui-monospace,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.error{color:#a12820;font-weight:650;min-height:24px}.table-wrap{overflow-x:auto}table{border-collapse:collapse;width:100%;font-size:15px}th,td{text-align:left;border-bottom:1px solid var(--line,#d6e0e7);padding:12px 9px;vertical-align:top}th{font-size:12px;text-transform:uppercase;letter-spacing:.03em;color:#516272}code,pre,.code{font:14px/1.65 ui-monospace,Consolas,monospace}pre{white-space:pre-wrap;overflow-wrap:anywhere;background:var(--tint,#eef3f7);padding:16px;border-radius:6px}details{border-top:1px solid var(--line,#d6e0e7);margin:24px 0;padding-top:16px}summary{cursor:pointer;font-weight:700;min-height:44px}footer{border-top:1px solid var(--line,#d6e0e7);margin-top:26px;padding-top:16px;font-size:13px;color:#516272}.bar{height:16px;background:#dce4ea;border-radius:20px;overflow:hidden;margin:12px 0}.bar span{display:block;height:100%;background:var(--accent,#176783)}[hidden]{display:none!important}@media(max-width:720px){main{padding:20px}.grid{grid-template-columns:1fr;gap:12px}.panel,.result{padding:20px}}@media(max-width:400px){main{padding:16px}.panel,.result{padding:16px}button{padding:10px 13px}} .sheet{background:white;border:1px solid var(--line,#d6e0e7);padding:26px}.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.tiles>article{padding:20px;background:white;border:1px solid var(--line,#d6e0e7)}.badge{display:inline-block;border-radius:30px;padding:4px 11px;background:var(--tint,#e3f3fa);font-size:13px;font-weight:750}.preview{white-space:pre-wrap;overflow-wrap:anywhere}.schedule-row{display:grid;grid-template-columns:1fr 100px 100px;gap:15px;align-items:center;border-bottom:1px solid var(--line,#d6e0e7);padding:12px 0}.schedule-row label{margin:0}.schedule-row small{display:block}.schedule-row input{margin-top:6px}.export textarea{min-height:180px}.note{border-left:4px solid var(--accent,#176783);background:var(--tint,#e3f3fa);padding:16px}svg{max-width:100%;height:auto}button{overflow-wrap:anywhere}h2,h3,p{overflow-wrap:anywhere}@media(max-width:720px){.tiles{grid-template-columns:1fr}.schedule-row{grid-template-columns:1fr 80px}.schedule-row .range{grid-column:1/3}.sheet{padding:20px}}@media(max-width:400px){.sheet{padding:16px}}
body{--accent:#596c40;--tint:#edf2e4;--bg:#f4f5ef;--ink:#35412d;--line:#d0d8c6}h1{font-family:Georgia,serif}.protocol-hero{display:grid;grid-template-columns:1.1fr 1fr;gap:28px;padding:26px;background:white;border-top:5px solid #596c40}.protocol-hero blockquote{font:24px/1.5 Georgia,serif;margin:20px 0}.trays{display:grid;grid-template-columns:1fr 1fr;gap:12px}.trays>div{border:3px solid #b5c19f;border-radius:14px;background:#f6f8f1;padding:15px}.token-row{display:flex;gap:7px;flex-wrap:wrap;min-height:55px;padding:15px 0}.token{width:23px;height:23px;border-radius:50%;background:#b16b3b;border:2px solid #8f5029}.prediction{padding:14px;border-top:1px solid #d6decf}.prediction p{margin:5px 0}.prediction small{display:block}@media(max-width:720px){.protocol-hero{grid-template-columns:1fr;padding:20px}.token{width:20px;height:20px}}</style></head><body><main>
<header><span class="eyebrow">Research lesson / planning packet RS01</span><h1>Follow the reasoning, phase by phase.</h1><p class="intro">When we ask learners to show how their counts account for all items, what reasoning does their explanation make visible?</p></header>
<section class="protocol-hero"><div><span class="eyebrow">Task key / planning demonstration</span><h2>Eight tokens. Two trays.</h2><p>One token in each tray per complete round. Make as many complete equal rounds as possible.</p><div class="trays"><div><b>Tray 1</b><div id="tray-1" class="token-row"></div></div><div><b>Tray 2</b><div id="tray-2" class="token-row"></div></div></div><p id="token-result" class="note" aria-live="polite"></p><div class="controls"><button type="button" id="another-round">Add one complete round</button><button type="button" id="three-rounds" class="secondary">Show 3-round case</button><button type="button" id="reset-tokens" class="secondary">Reset tokens</button></div></div><div><span class="badge">Hypothesis, not a finding</span><blockquote>“How does your arrangement account for all eight?”</blockquote><p>The team proposes that this prompt may reveal more explicit counting reasoning.</p><div class="prediction"><b>P01 · anticipated</b><p>“Four because half of eight.”</p><small>Investigate whether the explanation accounts for all eight.</small></div><div class="prediction"><b>P02 · anticipated</b><p>“Three each and two left.”</p><small>Investigate whether the two remaining tokens are connected to another round.</small></div></div></section>
<section class="panel"><h2>Coverage follows the same permitted cases</h2><div class="controls"><button type="button" id="initial" class="secondary">Initial reasoning / O01</button><button type="button" id="after" class="secondary">After prompt / O02</button><button type="button" id="debrief" class="secondary">Evidence discussion / R01</button></div><h3 id="coverage-title"></h3><p id="coverage-detail"></p><p class="note">If phases cannot be connected for the same permitted case, record the gap. Unrelated before/after comments do not establish a change in one learner.</p></section>
<div class="grid"><div><section class="panel"><h2>Editable teaching sequence</h2><b id="total" aria-live="polite"></b><label for="budget">Available planned minutes</label><input id="budget" type="number" value=""><div class="schedule-row"><div><b>Present the task</b><small>T01 presents eight tokens and two trays; O01 records task context.</small></div><div><label for="minutes-0">Minutes</label><input id="minutes-0" type="number" value=""></div><b class="range" id="range-0"></b></div><div class="schedule-row"><div><b>Initial arrangement</b><small>O01 records exact arrangement / explanation for permitted cases.</small></div><div><label for="minutes-1">Minutes</label><input id="minutes-1" type="number" value=""></div><b class="range" id="range-1"></b></div><div class="schedule-row"><div><b>Ask the proposed prompt</b><small>T01 asks: How does your arrangement account for all eight?</small></div><div><label for="minutes-2">Minutes</label><input id="minutes-2" type="number" value=""></div><b class="range" id="range-2"></b></div><div class="schedule-row"><div><b>Further explanation</b><small>O02 follows the same permitted cases, words, work and support.</small></div><div><label for="minutes-3">Minutes</label><input id="minutes-3" type="number" value=""></div><b class="range" id="range-3"></b></div><div class="schedule-row"><div><b>Retain work references</b><small>T01 / observers preserve permitted references for R01 debrief.</small></div><div><label for="minutes-4">Minutes</label><input id="minutes-4" type="number" value=""></div><b class="range" id="range-4"></b></div><p id="schedule-error" class="error" role="alert"></p></section><small>Actual timings were not supplied. Enter proposed local allocations with your team; these are planning times, not observation timestamps.</small></div><section class="sheet"><h2>Blank observation and debrief protocol</h2><p><b>Actual observation:</b> not recorded.</p><p>For each event: time; permitted case ID; phase; exact words or visible action; work reference; prompt/support; separate interpretation.</p><h3>After reviewing actual records</h3><ol><li>Initial reasoning, with evidence references.</li><li>After-prompt reasoning for connected cases.</li><li>Comparison with P01, P02 and unexpected thinking.</li><li>Contrary cases, absent responses, missed coverage and support.</li><li>Bounded conclusion about RS01 and remaining uncertainty.</li><li>Revision linked to evidence and a next-cycle question.</li></ol><p>Findings, conclusion and revision decision: <b>blank until evidence review</b>.</p><label for="context">Class / curriculum / materials / permissions (to confirm)</label><input id="context" type="text" value=""><label for="case-plan">Planned permitted case-linking process</label><input id="case-plan" type="text" value="Use the same school-permitted case IDs across O01 and O02 records."><p>“No response observed” and “observer missed this phase” remain different evidence states.</p></section></div>
<section class="panel export"><h2>Manual-copy planning text</h2><button type="button" id="prepare">Prepare text</button><button type="button" id="select-text" class="secondary">Select text</button><p id="export-error" class="error" role="alert"></p><label for="export-text">Generated plain text</label><textarea id="export-text" readonly></textarea><small>Select the text, then copy manually. Nothing is saved or sent.</small></section>
<footer>Token controls demonstrate supplied arithmetic; they never create learner observations. P01/P02 are predictions, not actual quotes. Before/after differences alone do not prove the prompt caused learning. No teacher rating, diagnosis, completed cycle or saved observation is claimed. Actual people, permissions, context and maintained school records remain to confirm.</footer>
</main><script>const $=id=>document.getElementById(id);const on=(id,e,fn)=>$(id).addEventListener(e,fn);const txt=(id,v)=>$(id).textContent=v;const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));const positive=x=>String(x).trim()!==''&&Number.isFinite(Number(x))&&Number(x)>0;const num=x=>Number(x.toPrecision(10)).toString();function enter(id,fn){on(id,'keydown',e=>{if(e.key==='Enter'&&!e.isComposing&&e.keyCode!==229){e.preventDefault();fn()}})}function selectText(id){$(id).focus();$(id).select()}
function isoDay(s){if(!/^\d{4}-\d{2}-\d{2}$/.test(s))throw Error('Use a real calendar date as YYYY-MM-DD.');const d=new Date(s+'T00:00:00Z');if(!Number.isFinite(d.getTime())||d.toISOString().slice(0,10)!==s)throw Error('Use a real calendar date as YYYY-MM-DD.');return d.getTime()/86400000}


const phases=['Present the task','Initial arrangement','Ask the proposed prompt','Further explanation','Retain work references'];let rounds=4;
function tokenState(n){if(!Number.isInteger(n)||n<0||n>4)throw Error('Use zero to four complete rounds.');return {each:n,used:n*2,left:8-n*2,more:n<4}}
function renderTokens(){const s=tokenState(rounds);for(const n of ['tray-1','tray-2'])$(n).innerHTML=Array.from({length:s.each},()=>'<span class="token" aria-hidden="true"></span>').join('')||'<small>Empty</small>';txt('token-result',s.each+' in each tray · '+s.used+' used · '+s.left+' remaining. '+(s.more?'Another complete round is possible.':'All eight accounted for; four complete rounds.'))}
on('another-round','click',()=>{if(rounds<4){rounds++;renderTokens()}else txt('token-result','4 in each tray · 8 used · 0 remaining. No further complete round is possible.')});on('three-rounds','click',()=>{rounds=3;renderTokens()});on('reset-tokens','click',()=>{rounds=0;renderTokens()});
function coverage(phase){const data={initial:['O01 · initial arrangement and explanation','Record task context, time, exact words/actions and work reference. Actual observer and permitted case IDs: TO CONFIRM. T01 presents the task.'],after:['O02 · after the proposed prompt','Follow the same permitted cases after T01 asks the prompt. Retain exact words/actions, work references and all additional support; do not paste predictions as observations.'],debrief:['R01 · evidence-led debrief','Compare connected initial/after records with P01/P02 and unexpected reasoning. Separate evidence from interpretation and revision; preserve contrary cases and gaps. Actual facilitator: TO CONFIRM.']};txt('coverage-title',data[phase][0]);txt('coverage-detail',data[phase][1]);for(const n of ['initial','after','debrief'])$(n).setAttribute('aria-pressed',String(n===phase))}
for(const n of ['initial','after','debrief'])on(n,'click',()=>coverage(n));
for(const n of ['context','case-plan'])on(n,'input',()=>{$('export-text').value='';txt('export-error','Planning inputs changed; prepare again.')});
on('prepare','click',()=>{const values=timing();if(!scheduleValid){txt('export-error','Supply and reconcile the planned timetable before preparing text.');return}$('export-text').value='PROPOSED LESSON STUDY PACKET / RS01\nQuestion: When we ask learners to show how their counts account for all items, what reasoning does their explanation make visible?\nTask: eight paper tokens, two trays, one in each per complete round, maximum four each.\nProposed prompt: How does your arrangement account for all eight?\nP01 anticipated, not observed: Four because half of eight.\nP02 anticipated, not observed: Three each and two left. Six used, two remain, another round possible.\n'+phases.map((p,i)=>p+': '+values[i]+' planned min').join('\n')+'\nProposed roles: T01 teach; O01 initial reasoning; O02 after-prompt reasoning; R01 evidence debrief. Actual people: TO CONFIRM.\nCase-linking plan: '+$('case-plan').value+'\nClass/curriculum/materials/permissions: '+($('context').value||'TO CONFIRM')+'\nACTUAL OBSERVATION BLANK: time ___ / permitted case ID ___ / phase ___ / exact words or action ___ / work reference ___ / prompt or support ___ / separate interpretation ___\nDEBRIEF BLANK: initial evidence ___ / connected after evidence ___ / prediction comparison ___ / unexpected and contrary cases ___ / absent response or missed coverage ___ / support ___ / bounded conclusion ___ / uncertainty ___ / revision with evidence references ___ / next-cycle question ___\nBefore/after alone is not causal proof. No response observed is different from missed observation; neither alone establishes failure. No actual study finding or teacher rating.';txt('export-error','Planning packet prepared; actual observation and conclusion fields remain blank.')});renderTokens();coverage('initial');

let scheduleValid=false;
function timing(){scheduleValid=false;$('export-text').value='';txt('export-error','');try{const values=phases.map((p,i)=>{const s=$('minutes-'+i).value;if(!/^\d+$/.test(s)||!Number.isSafeInteger(Number(s))||Number(s)<1||Number(s)>240)throw Error('Enter whole minutes from 1 to 240 for every phase.');return Number(s)});const b=$('budget').value;if(!/^\d+$/.test(b)||Number(b)<1||Number(b)>1200)throw Error('Enter an available budget from 1 to 1200 whole minutes.');let at=0;values.forEach((v,i)=>{txt('range-'+i,at+'–'+(at+v)+' min');at+=v});scheduleValid=at===Number(b);txt('total',scheduleValid?at+'-minute plan ready':at+' scheduled / '+b+' available');txt('schedule-error',scheduleValid?'':'Adjust the allocations or available budget before preparing a plan.');return values}catch(e){for(let i=0;i<phases.length;i++)txt('range-'+i,'Time pending');txt('total','Timing needs input');txt('schedule-error',e.message);return null}}
for(let i=0;i<phases.length;i++)on('minutes-'+i,'input',timing);on('budget','input',timing);
on('select-text','click',()=>selectText('export-text'));
timing();</script></body></html>