Request practice • communication lesson — Model a request that states one's own need, asks about another person's need and proposes an agreed turn-taking plan; record actual…

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>Request practice • communication lesson</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:#a4433e;--tint:#fff0e9;--bg:#fffaf7;--ink:#453631;--line:#ead7cc}h1{font-family:Georgia,serif;letter-spacing:-.025em}.role-stage{display:grid;grid-template-columns:1fr 130px 1fr;gap:18px;align-items:center}.role{padding:20px;background:white;border:1px solid #ead7cc;border-radius:18px}blockquote{margin:12px 0;font:22px/1.5 Georgia,serif}.shared-marker{text-align:center}.shared-marker span{display:block;color:#c72e35;font-size:52px;transform:rotate(-20deg)}.shared-marker b,.shared-marker small{display:block}.speech-sheet{margin:20px 0;padding:24px;background:white;border-bottom:4px solid #d19275}.speech-parts{display:flex;gap:16px}.speech-parts>div{flex:1;background:#fff6ef;padding:15px}.speech-parts p{font-size:14px}.blank-record dt{font-weight:700;margin-top:18px}.blank-record dd{margin:6px 0;padding:9px;border-bottom:1px dashed #c8b6a9;color:#75685d}@media(max-width:720px){.role-stage{grid-template-columns:1fr}.shared-marker{order:-1}.shared-marker span{display:none}.speech-parts{display:block}.speech-parts>div{margin-bottom:8px}}</style></head><body><main>
<header><span class="eyebrow">Classroom communication / teacher planning copy</span><h1>A request leaves room for a response.</h1><p class="intro">Rehearse a need, a question and a possible next turn using fictional roles.</p></header>
<section class="role-stage"><div class="role"><span class="eyebrow">Mara</span><blockquote>“I feel frustrated. I need the marker for my label.”</blockquote></div><div class="shared-marker"><span aria-hidden="true">▰</span><b>One red marker</b><small>Shared paper poster</small></div><div class="role"><span class="eyebrow">Jo</span><blockquote>“I want to finish the heading.”</blockquote></div></section>
<section class="speech-sheet"><div class="controls"><button type="button" id="model" class="secondary">Model request</button><button type="button" id="contrast" class="secondary">Contrast wording</button></div><blockquote id="speech"></blockquote><div class="speech-parts" id="parts"></div><p id="agreement" class="note"></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="30"><div class="schedule-row"><div><b>Read the role facts</b><small>Name the single red marker and each supplied need.</small></div><div><label for="minutes-0">Minutes</label><input id="minutes-0" type="number" value="5"></div><b class="range" id="range-0"></b></div><div class="schedule-row"><div><b>Model and contrast</b><small>Trace need, other-person question, next turn, and agreement.</small></div><div><label for="minutes-1">Minutes</label><input id="minutes-1" type="number" value="5"></div><b class="range" id="range-1"></b></div><div class="schedule-row"><div><b>Paired rehearsal</b><small>Use the cards; record actual words and support only if observed.</small></div><div><label for="minutes-2">Minutes</label><input id="minutes-2" type="number" value="8"></div><b class="range" id="range-2"></b></div><div class="schedule-row"><div><b>Replay after feedback</b><small>Revise one observable part and retain the earlier wording.</small></div><div><label for="minutes-3">Minutes</label><input id="minutes-3" type="number" value="8"></div><b class="range" id="range-3"></b></div><div class="schedule-row"><div><b>Exit transfer</b><small>Ari needs scissors for a title; Dev needs them for a border.</small></div><div><label for="minutes-4">Minutes</label><input id="minutes-4" type="number" value="4"></div><b class="range" id="range-4"></b></div><p id="schedule-error" class="error" role="alert"></p></section><section class="panel"><h2>Exit role cards</h2><p><b>Ari:</b> wants shared scissors to cut a title.</p><p><b>Dev:</b> wants them to cut a border.</p><p>Ask: What request, other-person question and next turn could work? What actual response would establish agreement?</p><small>Confirm teacher-approved materials and procedures before enactment.</small></section></div>
<section class="panel"><h2>Observation sheet stays unfilled</h2><p>Use the separate record in the school workflow. Displaying model words does not create a learner observation.</p><dl class="blank-record"><dt>Actual words / response form</dt><dd>Not observed</dd><dt>Other person’s actual response</dt><dd>Not observed</dd><dt>Support provided</dt><dd>Not recorded</dd><dt>Proposed turn and agreement</dt><dd>Not observed</dd><dt>Earlier wording → revised wording / reason</dt><dd>Not observed</dd></dl><label for="access">Planned participation / access note</label><input id="access" type="text" value="Offer observing, pointing, writing, or a supported home-language response."><label for="context">Class / approved material details (confirm before use)</label><input id="context" type="text" value=""><p>Teacher criteria: own need; asks and hears the other need; workable next turn; seeks agreement. Multiple respectful phrasings can meet these criteria.</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>Fictional role feelings are supplied facts. Jo’s feeling is not supplied. This planning copy does not recognize speech or emotions, score empathy, collect learner evidence, establish effectiveness, or confirm agreement. No personal conflict disclosure is required; maintained school records remain authoritative.</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=['Read the role facts','Model and contrast','Paired rehearsal','Replay after feedback','Exit transfer'];
function sample(mode){const model=mode==='model';txt('speech',model?'“I want a turn for my label. What do you still need to finish? Could we take two-minute turns?”':'“You are selfish. Give it to me.”');$('parts').innerHTML=model?'<div><b>Own need</b><p>I want a turn for my label.</p></div><div><b>Other need</b><p>What do you still need to finish?</p></div><div><b>Proposed next turn</b><p>Could we take two-minute turns?</p></div>':'<div><b>Revise the wording</b><p>State the task need, ask what the other person needs, and invite a joint next turn. Discuss these words, not the person’s character.</p></div>';txt('agreement',model?'Agreement not established: two-minute turns are a proposal. Ask for Jo’s actual response; revise if needed.':'No invitation to agree is present. A demand does not establish a shared plan.');$('model').setAttribute('aria-pressed',String(model));$('contrast').setAttribute('aria-pressed',String(!model))}
on('model','click',()=>sample('model'));on('contrast','click',()=>sample('contrast'));
on('prepare','click',()=>{const values=timing();if(!scheduleValid){txt('export-error','Resolve the timetable before preparing the lesson.');return}$('export-text').value='PROPOSED REQUEST-PRACTICE LESSON\n'+phases.map((p,i)=>p+': '+values[i]+' minutes').join('\n')+'\nFictional roles: Mara needs the one red marker for her label; her card says she feels frustrated. Jo wants to finish the heading; no feeling is supplied.\nModel: I want a turn for my label. What do you still need to finish? Could we take two-minute turns?\nAgreement: NOT OBSERVED; proposal only.\nPlanned access: '+$('access').value+'\nClass/material confirmation: '+($('context').value||'TO CONFIRM')+'\nActual words/response form: ______\nOther person’s response: ______\nSupport used: ______\nProposed turn / actual agreement response: ______\nEarlier words / revision / reason: ______\nExit: Ari wants scissors for a title; Dev wants them for a border. Confirm approved materials and procedures.\nNo personal conflict disclosure; teacher reviews observable communication, not feelings.';txt('export-error','Planning text prepared; actual observation fields remain blank.')});
for(const n of ['access','context'])on(n,'input',()=>{$('export-text').value='';txt('export-error','Inputs changed; prepare the current planning text.')});sample('model');

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>