Cedar Speaking Club · agenda — Map prepared speakers to evaluators, identify who receives control next and check that a locally chosen meeting schedule fits its allotted…

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>Cedar Speaking Club · agenda</title><style>*{box-sizing:border-box}body{margin:0;font:16px/1.5 Arial,sans-serif;color:var(--ink);background:var(--bg)}main{max-width:1180px;margin:auto;padding:26px 28px 50px}h1,h2,h3,p{margin:0}h1{font-size:34px;line-height:1.15;letter-spacing:-.025em}h2{font-size:23px;margin-bottom:12px}h3{font-size:17px}header{margin-bottom:22px}header p{margin-top:8px}button,input,select,textarea{font:inherit}button{cursor:pointer;min-height:44px;padding:9px 15px;border:1px solid var(--line);border-radius:7px;background:white;color:var(--ink)}button:hover{filter:brightness(.94)}button.active,.primary{background:var(--accent);color:white;border-color:var(--accent)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid #117ec1;outline-offset:3px}input,select,textarea{max-width:100%;padding:9px;border:1px solid #8c9caa;border-radius:5px;background:white;color:var(--ink)}input{width:100%;min-width:0}textarea{width:100%;resize:vertical}label{display:block;font-size:14px;font-weight:bold;margin:12px 0 5px}.small,small{font-size:13px;color:var(--muted)}.eyebrow{font-size:12px;letter-spacing:.13em;text-transform:uppercase;margin-bottom:8px;font-weight:bold}.toolbar{display:flex;gap:8px;flex-wrap:wrap;margin:16px 0}.split{display:grid;grid-template-columns:1.5fr 1fr;gap:24px;align-items:start}.paper{background:white;border:1px solid var(--line);padding:25px;border-radius:10px}.fields{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}.message{padding:12px 14px;border-left:4px solid var(--accent);background:var(--tint);margin:15px 0;overflow-wrap:anywhere}.big{font-size:40px;font-weight:700;line-height:1.2}table{border-collapse:collapse;width:100%;font-size:14px}th,td{text-align:left;padding:11px 8px;border-bottom:1px solid var(--line);vertical-align:top}th{font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}footer{margin-top:28px;padding-top:18px;border-top:1px solid var(--line);font-size:13px;color:var(--muted)}footer p+p{margin-top:8px}[hidden]{display:none!important}.stack{display:grid;gap:12px}.tag{font-size:12px;padding:4px 8px;border-radius:20px;background:var(--tint);display:inline-block}.section{margin-top:26px}.error{color:#a32727}svg{max-width:100%;height:auto;display:block}button[disabled]{opacity:.5;cursor:default}@media(max-width:800px){main{padding:22px 18px}.split{grid-template-columns:1fr}h1{font-size:30px}.paper{padding:20px}}@media(max-width:450px){main{padding:18px 12px}h1{font-size:27px}.fields{gap:0 10px}.paper{padding:16px}.big{font-size:34px}th,td{padding:9px 5px}.toolbar button{flex:1;padding:8px}}
:root{--bg:#f0eef4;--ink:#302842;--muted:#6c627c;--accent:#6d3f7c;--line:#dcd3e5;--tint:#f5edf9}h1,h2{font-family:Georgia,serif}.agenda{border-radius:0;border-top:6px solid #6d3f7c}.agenda-row{display:grid;grid-template-columns:75px 1fr 70px;gap:12px;padding:12px 0;border-top:1px solid #e5dfea}.agenda-row input{padding:5px}.agenda-row label{margin:0}.range{font-weight:bold;color:#6d3f7c}.agenda-row small{display:block;margin-top:3px}.roster{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.roster label{margin-top:0}.totalbar{display:flex;gap:18px;align-items:center}.rolebox{padding:13px;border:1px solid var(--line);border-radius:6px}@media(max-width:600px){.roster{grid-template-columns:1fr 1fr}.agenda-row{grid-template-columns:57px 1fr 56px;gap:7px}.agenda-row h3{font-size:15px}}
.split>*{min-width:0}.fields{grid-template-columns:repeat(2,minmax(0,1fr))}.rolebox{min-width:0}
@media(max-width:450px){.roster{grid-template-columns:minmax(0,1fr)}.agenda-row{grid-template-columns:minmax(0,1fr) 80px}.agenda-row>span{grid-row:1;grid-column:1}.agenda-row>div:nth-child(2){grid-row:2;grid-column:1/-1}.agenda-row>div:last-child{grid-row:1;grid-column:2}}
</style></head><body><main><header><div class="eyebrow">Fictional Cedar Speaking Club · local draft v1</div><h1>An hour with clear handoffs.</h1><p>Inspect the schedule, evaluator links and next host together.</p></header><div class="split"><article class="paper agenda"><div class="totalbar"><div class="big" id="total">60 min</div><div id="discrepancy"></div></div><div id="duration-error" class="error" role="status"></div><div class="section"><div class="agenda-row"><span id="range-0" class="range"></span><div><h3>Welcome and opening</h3><small>Presiding officer → Toastmaster</small></div><div><label for="duration-0" class="small">Minutes</label><input id="duration-0" value="4" inputmode="numeric" aria-label="Welcome and opening duration in minutes"></div></div><div class="agenda-row"><span id="range-1" class="range"></span><div><h3>Role introductions</h3><small>Toastmaster retains control</small></div><div><label for="duration-1" class="small">Minutes</label><input id="duration-1" value="5" inputmode="numeric" aria-label="Role introductions duration in minutes"></div></div><div class="agenda-row"><span id="range-2" class="range"></span><div><h3>Prepared speeches</h3><small>S1/S2 → Toastmaster → Topicsmaster</small><small>Includes introductions, transitions and feedback.</small></div><div><label for="duration-2" class="small">Minutes</label><input id="duration-2" value="16" inputmode="numeric" aria-label="Prepared speeches duration in minutes"></div></div><div class="agenda-row"><span id="range-3" class="range"></span><div><h3>Table Topics</h3><small>Topicsmaster → Toastmaster → General evaluator</small></div><div><label for="duration-3" class="small">Minutes</label><input id="duration-3" value="15" inputmode="numeric" aria-label="Table Topics duration in minutes"></div></div><div class="agenda-row"><span id="range-4" class="range"></span><div><h3>Evaluations and role reports</h3><small>Evaluators/reporters → General evaluator → Toastmaster</small></div><div><label for="duration-4" class="small">Minutes</label><input id="duration-4" value="13" inputmode="numeric" aria-label="Evaluations and role reports duration in minutes"></div></div><div class="agenda-row"><span id="range-5" class="range"></span><div><h3>Wrap-up</h3><small>Toastmaster → Presiding officer</small></div><div><label for="duration-5" class="small">Minutes</label><input id="duration-5" value="4" inputmode="numeric" aria-label="Wrap-up duration in minutes"></div></div><div class="agenda-row"><span id="range-6" class="range"></span><div><h3>Closing</h3><small>Presiding officer → Adjourned</small></div><div><label for="duration-6" class="small">Minutes</label><input id="duration-6" value="3" inputmode="numeric" aria-label="Closing duration in minutes"></div></div></div></article><aside class="stack"><section class="paper"><h2>Speaker → evaluator</h2><label for="link-1">S1 evaluator slot</label><input id="link-1" value="E1" aria-describedby="pair-status"><label for="objective-1">S1 supplied objective / source</label><input id="objective-1" placeholder="Unconfirmed"><label for="link-2">S2 evaluator slot</label><input id="link-2" value="E2" aria-describedby="pair-status"><label for="objective-2">S2 supplied objective / source</label><input id="objective-2" placeholder="Unconfirmed"><p class="message" id="pair-status"></p></section><section class="paper"><h2>Individual speech fit</h2><div class="fields"><div><label for="fit-0">S1 speech (min)</label><input id="fit-0" inputmode="decimal" placeholder="Unknown"></div><div><label for="fit-1">S2 speech (min)</label><input id="fit-1" inputmode="decimal" placeholder="Unknown"></div><div><label for="fit-2">Introductions / transitions (min)</label><input id="fit-2" inputmode="decimal" placeholder="Unknown"></div><div><label for="fit-3">Feedback allowance (min)</label><input id="fit-3" inputmode="decimal" placeholder="Unknown"></div></div><p class="message" id="fit-status"></p><p class="small">Use actual supplied timing; no project duration is inferred.</p></section></aside></div><section class="paper section"><h2>Role roster · acceptance remains separate</h2><div class="roster"><div class="rolebox"><label for="role-0">Presiding officer name</label><input id="role-0" placeholder="Unconfirmed"><label for="accept-0" class="small">Acceptance</label><select id="accept-0"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-1">Toastmaster name</label><input id="role-1" placeholder="Unconfirmed"><label for="accept-1" class="small">Acceptance</label><select id="accept-1"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-2">Topicsmaster name</label><input id="role-2" placeholder="Unconfirmed"><label for="accept-2" class="small">Acceptance</label><select id="accept-2"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-3">General evaluator name</label><input id="role-3" placeholder="Unconfirmed"><label for="accept-3" class="small">Acceptance</label><select id="accept-3"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-4">Timer name</label><input id="role-4" placeholder="Unconfirmed"><label for="accept-4" class="small">Acceptance</label><select id="accept-4"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-5">Grammarian name</label><input id="role-5" placeholder="Unconfirmed"><label for="accept-5" class="small">Acceptance</label><select id="accept-5"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-6">Ah-Counter name</label><input id="role-6" placeholder="Unconfirmed"><label for="accept-6" class="small">Acceptance</label><select id="accept-6"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-7">S1 name</label><input id="role-7" placeholder="Unconfirmed"><label for="accept-7" class="small">Acceptance</label><select id="accept-7"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-8">S2 name</label><input id="role-8" placeholder="Unconfirmed"><label for="accept-8" class="small">Acceptance</label><select id="accept-8"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-9">E1 name</label><input id="role-9" placeholder="Unconfirmed"><label for="accept-9" class="small">Acceptance</label><select id="accept-9"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div><div class="rolebox"><label for="role-10">E2 name</label><input id="role-10" placeholder="Unconfirmed"><label for="accept-10" class="small">Acceptance</label><select id="accept-10"><option value="">Unconfirmed</option><option value="yes">Organizer confirmed</option></select></div></div><p id="roster-status" class="message"></p><button type="button" id="reset">Reset demonstration</button></section><footer><p>Actual date, start time, venue and organizer: TO CONFIRM. This original local schedule is illustrative, not an official required order or current Pathways/certification rule. Speaker and evaluator slots are not confirmed people.</p><p>Self-contained HTML inspector; native DOCX/PDF agenda and print approval remain separate. No timer, sending, saved responses or automatic acceptance. Internal transitions stay inside the displayed segment budgets.</p></footer></main><script>'use strict';const $=id=>document.getElementById(id);const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));const initial=[4,5,16,15,13,4,3],names=["Welcome and opening","Role introductions","Prepared speeches","Table Topics","Evaluations and role reports","Wrap-up","Closing"];function schedule(values){let end=0;const ranges=[];for(let i=0;i<values.length;i++){if(!/^\d+$/.test(values[i])||Number(values[i])<1||Number(values[i])>600)return {error:names[i]+': enter a positive whole-minute duration (1–600).'};const start=end;end+=Number(values[i]);ranges.push([start,end]);}return {total:end,ranges};}
function render(){const r=schedule(initial.map((_,i)=>$('duration-'+i).value.trim()));$('duration-error').textContent=r.error||'';$('total').textContent=r.error?'Unconfirmed':r.total+' min';$('discrepancy').textContent=r.error?'Dependent ranges unconfirmed':r.total===60?'Aggregate hour fits':r.total>60?'Over allotted hour by '+(r.total-60)+' minutes':'Under allotted hour by '+(60-r.total)+' minutes';initial.forEach((_,i)=>$('range-'+i).textContent=r.error?'—':r.ranges[i].map(n=>String(n).padStart(2,'0')).join('–'));const flags=[1,2].map(i=>{const link=$('link-'+i).value.trim();return !link?'S'+i+': Missing evaluator link':!['E1','E2'].includes(link)?'S'+i+': Unknown evaluator slot':!$('role-'+(link==='E1'?9:10)).value.trim()?'S'+i+' → '+link+': Evaluator person unconfirmed':$('accept-'+(link==='E1'?9:10)).value!=='yes'?'S'+i+' → '+link+': Acceptance unconfirmed':'S'+i+' → '+link+': Organizer confirmed';});$('pair-status').textContent=flags.join('. ');const fit=[0,1,2,3].map(i=>$('fit-'+i).value.trim());$('fit-status').textContent=fit.some(v=>!v)?'Individual speech fit: Unconfirmed — supply both speech durations and both allowances.':fit.some(v=>!Number.isFinite(Number(v))||Number(v)<0)?'Individual speech fit: invalid supplied timing.':r.error?'Individual speech fit: aggregate block unconfirmed.':(()=>{let sum=fit.reduce((s,v)=>s+Number(v),0),budget=Number($('duration-2').value);return 'Supplied total '+sum+' min / '+budget+' min block · '+(sum<=budget?'Fits supplied block':'Exceeds block by '+(sum-budget)+' min');})();const missing=Array.from({length:11},(_,i)=>!$('role-'+i).value.trim()||$('accept-'+i).value!=='yes').filter(Boolean).length;$('roster-status').textContent=missing+' role assignments unconfirmed. Objectives and timing require their own supplied records.';}
function reset(){initial.forEach((n,i)=>$('duration-'+i).value=String(n));[1,2].forEach(i=>{$('link-'+i).value='E'+i;$('objective-'+i).value='';});[0,1,2,3].forEach(i=>$('fit-'+i).value='');Array.from({length:11},(_,i)=>{$('role-'+i).value='';$('accept-'+i).value='';});render();}initial.forEach((_,i)=>$('duration-'+i).addEventListener('input',render));[1,2].forEach(i=>['link-','objective-'].forEach(prefix=>$(prefix+i).addEventListener('input',render)));Array.from({length:11},(_,i)=>['role-','accept-'].forEach(prefix=>$(prefix+i).addEventListener('input',render)));[0,1,2,3].forEach(i=>$('fit-'+i).addEventListener('input',render));$('reset').addEventListener('click',reset);reset();globalThis.App={schedule,render,reset};</script></body></html>