Paper bridge studio • plan and evidence — Define a design problem with supplied success criteria and material/time constraints, compare prototypes through the same test and justify…

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>Paper bridge studio • plan and evidence</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}} .paper{background:white;padding:26px;border:1px solid var(--line,#d6e0e7)}.badge{display:inline-block;padding:4px 10px;border-radius:20px;background:var(--tint,#e3f2f8);font-size:13px;font-weight:700}.feedback{padding:18px;background:var(--tint,#e3f2f8);border-left:4px solid var(--accent,#176783);line-height:1.7}.schedule-row{display:grid;grid-template-columns:70px 1fr 90px;gap:14px;padding:16px 0;border-bottom:1px solid var(--line,#d6e0e7);align-items:start}.schedule-row label{margin:0}.schedule-row small{display:block;margin-top:6px}.schedule-row b{font-size:17px}.schedule-time{font-weight:700;font-variant-numeric:tabular-nums}.export{margin:24px 0}.export textarea{min-height:180px}.choice-list{display:flex;gap:10px;flex-wrap:wrap;margin:18px 0}.choice-list button{background:white;color:var(--ink,#203342);border-color:var(--line,#94a5b2)}@media(max-width:400px){.schedule-row{grid-template-columns:48px 1fr 65px;gap:9px}.schedule-row input{padding:8px}}
body{--accent:#30666b;--bg:#f0f6f5;--ink:#233e42;--tint:#e0efec;--line:#c8ddda}.challenge{background:white;border:1px solid #c8ddda;border-radius:8px;overflow:hidden}.criteria{display:grid;grid-template-columns:repeat(3,1fr);background:#30666b;color:white}.criteria div{padding:18px;text-align:center;border-right:1px solid #699195}.criteria b{font-size:clamp(22px,3vw,31px);display:block}.criteria span{display:block;font-size:13px}.prototypes{display:grid;grid-template-columns:1fr 1fr;gap:20px;padding:22px}.prototypes article{min-width:0}.prototypes svg{width:100%;height:125px;display:block}.prototypes rect{fill:#a2b8b4}.sheet{fill:none;stroke:#d78c39;stroke-width:5;stroke-linejoin:round}.measure{fill:none;stroke:#31585b;stroke-width:1}.prototypes p{font-size:14px;margin:0}.untested{margin:0;padding:14px 22px;background:#f1f6f4;font-size:14px}.trial{border-top:4px solid #d78c39;padding-top:18px}.panel{border-radius:5px}@media(max-width:400px){.criteria div{padding:12px 6px}.criteria span{font-size:11px}.prototypes{gap:10px;padding:16px}.prototypes .badge{font-size:11px;padding:3px 7px}.prototypes svg{height:95px}}</style></head><body><main>
<header><span class="eyebrow">Engineering design lesson / original classroom challenge</span><h1>Build a bridge. Test the same rule.</h1><p class="intro">Two proposed constructions, one shared criterion, and a revision supported by the evidence you record.</p></header>
<section class="challenge"><div class="criteria"><div><b>10 cm</b><span>fixed gap</span></div><div><b>3 tokens</b><span>identical, teacher-selected</span></div><div><b>20 sec</b><span>hold duration</span></div></div><div class="prototypes"><article><span class="badge">A · Proposed flat sheet</span><svg viewBox="0 0 320 125" role="img" aria-label="Proposed flat sheet between two fixed supports, spanning a 10 centimeter gap."><rect x="20" y="68" width="60" height="45"/><rect x="240" y="68" width="60" height="45"/><path class="sheet" d="M40 64 L280 64"/><path class="measure" d="M80 105 L240 105 M80 99 L80 111 M240 99 L240 111"/></svg><p>One flat supplied sheet.</p></article><article><span class="badge">B · Proposed channel fold</span><svg viewBox="0 0 320 125" role="img" aria-label="Proposed paper channel, formed by folding the same permitted sheet's long edges upward, between the same fixed supports."><rect x="20" y="68" width="60" height="45"/><rect x="240" y="68" width="60" height="45"/><path class="sheet" d="M40 52 L280 52 M40 52 L40 66 L280 66 L280 52"/><path class="measure" d="M80 105 L240 105 M80 99 L80 111 M240 99 L240 111"/></svg><p>Both long edges folded upward.</p></article></div><p class="untested" id="prototype-status"><b>Both designs are untested.</b> One sheet per prototype; no adhesive. Neither sketch predicts a winner.</p></section>
<section class="panel"><h2>Lesson sequence</h2><label for="available">Available lesson minutes</label><input id="available" type="number" value="45" ><p class="badge" id="schedule-summary">45-minute plan ready</p><p id="schedule-error" class="error" role="alert"></p><div class="schedule-row"><span id="range-0" class="schedule-time"></span><div><b>Define the problem</b><p>Present the 10 cm span and three-token, 20-second success criterion.</p><small>Learner action: Explain what the bridge must do.</small></div><div><label for="mins-0">Minutes</label><input id="mins-0" type="number" value="5" min="1" max="180"></div></div><div class="schedule-row"><span id="range-1" class="schedule-time"></span><div><b>Criteria and constraints</b><p>Separate success from the one-sheet/no-adhesive constraints. Confirm sheet, token, placement, and timing details.</p><small>Learner action: Identify missing setup inputs and read the shared test conditions.</small></div><div><label for="mins-1">Minutes</label><input id="mins-1" type="number" value="5" min="1" max="180"></div></div><div class="schedule-row"><span id="range-2" class="schedule-time"></span><div><b>Sketch two proposals</b><p>Compare the flat sheet and the upturned-long-edge channel sketch, without predicting a winner.</p><small>Learner action: Draw the proposed construction and name one feature to compare.</small></div><div><label for="mins-2">Minutes</label><input id="mins-2" type="number" value="8" min="1" max="180"></div></div><div class="schedule-row"><span id="range-3" class="schedule-time"></span><div><b>Build</b><p>Supply teacher-authorized materials and fixed supports.</p><small>Learner action: Build within the supplied one-sheet/no-adhesive constraints.</small></div><div><label for="mins-3">Minutes</label><input id="mins-3" type="number" value="10" min="1" max="180"></div></div><div class="schedule-row"><span id="range-4" class="schedule-time"></span><div><b>Test and propose a revision</b><p>Keep gap, tokens, placement, and timing procedure identical; record observations. Retest only if time permits.</p><small>Learner action: Record a trial and connect one proposed construction change to evidence.</small></div><div><label for="mins-4">Minutes</label><input id="mins-4" type="number" value="8" min="1" max="180"></div></div><div class="schedule-row"><span id="range-5" class="schedule-time"></span><div><b>Share evidence</b><p>Ask what observation supports the next change.</p><small>Learner action: Explain the observed result and a reason for the proposal.</small></div><div><label for="mins-5">Minutes</label><input id="mins-5" type="number" value="5" min="1" max="180"></div></div><div class="schedule-row"><span id="range-6" class="schedule-time"></span><div><b>Cleanup</b><p>Use the teacher-supplied material-return routine.</p><small>Learner action: Return materials as directed.</small></div><div><label for="mins-6">Minutes</label><input id="mins-6" type="number" value="4" min="1" max="180"></div></div></section>
<section class="panel"><h2>Judge a hypothetical trial</h2><p>This arithmetic example is separate from the blank classroom records below.</p><div class="grid"><div><label for="hyp-seconds">Hypothetical hold duration (seconds)</label><input id="hyp-seconds" type="number" value="8" ><button type="button" id="judge-hyp">Check 20-second criterion</button></div><p id="hyp-result" class="feedback" aria-live="polite">Example only: 8 seconds does not meet the 20-second duration criterion.</p></div></section>
<section class="panel"><h2>Record the actual test when it happens</h2><p>Use the same three tokens, placement, gap, sheet specification, and timing procedure for both prototypes. These fields start without observed outcomes.</p><div class="grid"><article class="trial"><h3>Prototype A · supplied trial</h3><label for="seconds-A">Observed duration (seconds)</label><input id="seconds-A" type="number" value="" ><label for="gap-A">Measured gap (cm)</label><input id="gap-A" type="number" value="10" ><label for="tokens-A">Tokens used</label><input id="tokens-A" type="number" value="3" ><label for="sheet-A">Sheet specification — same permitted sheet type</label><input id="sheet-A" type="text" value="" placeholder="Teacher to confirm"><label for="place-A">Token set and placement identifier</label><input id="place-A" type="text" value="" placeholder="Teacher to confirm"><label class="inline"><input type="checkbox" id="allowed-A">One permitted sheet; no adhesive; fixed supports and timing procedure confirmed.</label><label for="time-A">Observation time / trial reference — if supplied</label><input id="time-A" type="text" value=""><label for="note-A">Observation note — blank until provided</label><textarea id="note-A" rows="3"></textarea></article><article class="trial"><h3>Prototype B · supplied trial</h3><label for="seconds-B">Observed duration (seconds)</label><input id="seconds-B" type="number" value="" ><label for="gap-B">Measured gap (cm)</label><input id="gap-B" type="number" value="10" ><label for="tokens-B">Tokens used</label><input id="tokens-B" type="number" value="3" ><label for="sheet-B">Sheet specification — same permitted sheet type</label><input id="sheet-B" type="text" value="" placeholder="Teacher to confirm"><label for="place-B">Token set and placement identifier</label><input id="place-B" type="text" value="" placeholder="Teacher to confirm"><label class="inline"><input type="checkbox" id="allowed-B">One permitted sheet; no adhesive; fixed supports and timing procedure confirmed.</label><label for="time-B">Observation time / trial reference — if supplied</label><input id="time-B" type="text" value=""><label for="note-B">Observation note — blank until provided</label><textarea id="note-B" rows="3"></textarea></article></div><div class="controls"><button type="button" id="assess">Review supplied trials</button><button type="button" id="clear-trials" class="secondary">Clear trial records</button></div><p id="trial-result" class="feedback" aria-live="polite">No classroom trial outcomes recorded.</p><p id="trial-error" class="error" role="alert"></p><label for="feature">One construction feature proposed for revision</label><textarea id="feature" rows="3"></textarea><label for="reason">Observation supporting that proposal</label><textarea id="reason" rows="3"></textarea></section>
<section class="panel export"><h2>Lesson and revision record</h2><div class="controls"><button type="button" id="prepare">Prepare text</button><button type="button" id="select-text" class="secondary">Select text</button></div><p id="export-error" class="error" role="alert"></p><label for="export-text">Exact generated plain text</label><textarea id="export-text" readonly rows="9"></textarea><small>Select the text, then copy it manually into your required format. Nothing is saved or sent.</small></section>
<footer>Illustrative lesson, not a performed experiment, physics simulation, strength rating, or structural certification. Teacher confirms actual materials/setup before class. No invented retest, approval, or learning gain. Supplied observations stay local and are not saved or collected.</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()}
const phases=[["Define the problem", 5, "Present the 10 cm span and three-token, 20-second success criterion.", "Explain what the bridge must do."], ["Criteria and constraints", 5, "Separate success from the one-sheet/no-adhesive constraints. Confirm sheet, token, placement, and timing details.", "Identify missing setup inputs and read the shared test conditions."], ["Sketch two proposals", 8, "Compare the flat sheet and the upturned-long-edge channel sketch, without predicting a winner.", "Draw the proposed construction and name one feature to compare."], ["Build", 10, "Supply teacher-authorized materials and fixed supports.", "Build within the supplied one-sheet/no-adhesive constraints."], ["Test and propose a revision", 8, "Keep gap, tokens, placement, and timing procedure identical; record observations. Retest only if time permits.", "Record a trial and connect one proposed construction change to evidence."], ["Share evidence", 5, "Ask what observation supports the next change.", "Explain the observed result and a reason for the proposal."], ["Cleanup", 4, "Use the teacher-supplied material-return routine.", "Return materials as directed."]];

let scheduleValid=false;
function scheduleState(values,available){if(!/^[1-9]\d*$/.test(String(available))||Number(available)>480)throw Error('Available minutes must be a whole number from 1 to 480.');if(values.some(x=>!/^[1-9]\d*$/.test(String(x))||Number(x)>180))throw Error('Each phase needs 1–180 whole minutes.');const total=values.reduce((a,x)=>a+Number(x),0);let start=0;const ranges=values.map(x=>{const s=start;start+=Number(x);return s+'–'+start});return {total,ranges,ready:total===Number(available)}}
function updateSchedule(){try{const s=scheduleState(phases.map((_,i)=>$('mins-'+i).value),$('available').value);scheduleValid=s.ready;phases.forEach((_,i)=>txt('range-'+i,s.ranges[i]));txt('schedule-summary',s.ready?s.total+'-minute plan ready':s.total+' scheduled / '+$('available').value+' available');txt('schedule-error',s.ready?'':'Adjust phase minutes or available time before preparing the plan.')}catch(e){scheduleValid=false;phases.forEach((_,i)=>txt('range-'+i,'—'));txt('schedule-summary','Schedule needs input');txt('schedule-error',e.message)}if($('export-text'))$('export-text').value=''}
function planText(){if(!scheduleValid)throw Error('Resolve the timetable before preparing the plan.');return phases.map((p,i)=>$('range-'+i).textContent+' min · '+p[0]+'\nTeacher: '+p[2]+'\nLearner: '+p[3]).join('\n\n')}
on('available','input',updateSchedule);phases.forEach((_,i)=>on('mins-'+i,'input',updateSchedule));updateSchedule();

function durationResult(s){if(String(s).trim()===''||!Number.isFinite(Number(s))||Number(s)<0)throw Error('Supply a finite nonnegative duration.');return Number(s)>=20?'meets the 20-second duration criterion':'does not meet the 20-second duration criterion'}
function hypothetical(){try{txt('hyp-result','Example only: '+$('hyp-seconds').value+' seconds '+durationResult($('hyp-seconds').value)+'. This alone is not a maximum load or a real test.')}catch(e){txt('hyp-result','No hypothetical result: '+e.message)}}
function trialData(letter){const s=$('seconds-'+letter).value;if(!s.trim())return null;const gap=Number($('gap-'+letter).value),tokens=Number($('tokens-'+letter).value),sheet=$('sheet-'+letter).value.trim(),placement=$('place-'+letter).value.trim();durationResult(s);if(!$('gap-'+letter).value.trim()||!Number.isFinite(gap)||gap<=0||!Number.isInteger(tokens)||tokens<=0)throw Error('Trial '+letter+': supply a positive gap and whole token count.');if(!sheet||!placement||!$('allowed-'+letter).checked)throw Error('Trial '+letter+': confirm sheet, token set/placement, supports, one-sheet/no-adhesive constraints, and timing.');return {seconds:Number(s),gap,tokens,sheet,placement,allowed:true}}
function compareTrials(a,b){if(!a&&!b)return 'No classroom trial outcomes recorded.';const result=(t,l)=>!t?'Prototype '+l+': no outcome supplied.':t.gap!==10||t.tokens!==3?'Prototype '+l+': conditions differ from the 10 cm / 3-token challenge; no criterion acceptance.':'Prototype '+l+': '+t.seconds+' seconds '+durationResult(t.seconds)+'.';let text=result(a,'A')+' '+result(b,'B');if(a&&b){const same=a.gap===b.gap&&a.tokens===b.tokens&&a.sheet===b.sheet&&a.placement===b.placement;text+=' '+(same?'Recorded conditions match; compare only these supplied trials.':'Conditions differ. Do not attribute the difference solely to the construction.')}return text+' No maximum strength, winning design, or future performance is established.'}
let trialSummary='No classroom trial outcomes recorded.';
function pendingTrials(){trialSummary=null;txt('prototype-status','Trial inputs changed; no current reviewed outcome.');txt('trial-result','Trial inputs changed. Review the supplied records again.');txt('trial-error','');$('export-text').value=''}
function assess(){try{const a=trialData('A'),b=trialData('B');trialSummary=compareTrials(a,b);txt('prototype-status',a||b?'Supplied trial records appear below; the sketches are illustrations, not performed tests.':'Both designs are untested. One sheet per prototype; no adhesive. Neither sketch predicts a winner.');txt('trial-result',trialSummary);txt('trial-error','')}catch(e){trialSummary=null;txt('trial-result','No current accepted trial comparison.');txt('trial-error',e.message)}}
on('hyp-seconds','input',()=>txt('hyp-result','Hypothetical input changed. Check the criterion again.'));on('judge-hyp','click',hypothetical);
for(const l of ['A','B'])for(const n of ['seconds','gap','tokens','sheet','place','allowed','note','time']){on(n+'-'+l,'input',pendingTrials);on(n+'-'+l,'change',pendingTrials)}
for(const n of ['feature','reason'])on(n,'input',()=>{$('export-text').value='';txt('export-error','')});
on('assess','click',assess);on('clear-trials','click',()=>{for(const l of ['A','B']){for(const n of ['seconds','sheet','place','note','time'])$(n+'-'+l).value='';$('gap-'+l).value='10';$('tokens-'+l).value='3';$('allowed-'+l).checked=false}$('feature').value='';$('reason').value='';$('export-text').value='';assess()});
on('prepare','click',()=>{try{if(trialSummary===null)throw Error('Review the current supplied trials before preparing the record.');const proposal=$('feature').value.trim(),reason=$('reason').value.trim();if(Boolean(proposal)!==Boolean(reason))throw Error('Keep a proposed feature change together with its supporting observation.');let text='PAPER BRIDGE DESIGN LESSON\nCriterion: span 10 cm; hold 3 identical teacher-selected lightweight tokens for at least 20 seconds.\nConstraints: one permitted sheet per prototype, no adhesive, fixed supports; same sheet specification, token set/placement and timing procedure.\nA flat / B upturned-long-edge channel: proposed, not proven.\n\n'+planText()+'\n\nTrial record: '+trialSummary;for(const l of ['A','B'])text+='\n'+l+' sheet: '+($('sheet-'+l).value||'TO CONFIRM')+'; token set/placement: '+($('place-'+l).value||'TO CONFIRM')+'; trial time/reference: '+($('time-'+l).value||'NOT RECORDED')+'; note: '+($('note-'+l).value||'NOT RECORDED');text+='\nProposed feature change: '+(proposal||'NOT SUPPLIED')+'\nSupporting observation: '+(reason||'NOT SUPPLIED')+'\nNo retest recorded.';$('export-text').value=text;txt('export-error','')}catch(e){$('export-text').value='';txt('export-error',e.message)}});on('select-text','click',()=>selectText('export-text'));hypothetical();
</script></body></html>