Fictional book exchange: four required role-hours, three listed and one uncovered

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"><meta name="nos-demo-layout" content="responsive-lab"><title>Book exchange volunteer coverage</title><style>*{box-sizing:border-box}body{margin:0;font:16px/1.5 system-ui;background:#f5f7fb;color:#273244}main{max-width:850px;margin:auto;padding:22px}h1{font-size:1.8rem;line-height:1.2}h2{font-size:1.2rem}label{display:block;font-weight:700}select{font:inherit;padding:9px;max-width:100%}section{border-top:2px solid #9da9bd;padding:12px 0}#result{background:#e6ebf4;border-left:5px solid #657b9f;padding:14px}pre{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;background:#e6ebf4;padding:14px}</style></head><body><main><h1>Find the uncovered hour</h1><p>Original fictional book exchange, 9:00-11:00 a.m. Date, venue and time zone not supplied. Listed names are fictional assignments, not attendance or confirmed availability.</p><p><strong>Whole event: 4 required role-hours, 3 listed role-hours, 1 unassigned role-hour.</strong></p><label for="role">Inspect role coverage</label><select id="role"><option value="all">Both roles</option><option value="welcome">Welcome table</option><option value="sorting">Book sorting</option></select><p id="result" aria-live="polite"></p><div id="rows"></div><h2>Blank shift record</h2><pre>Event / date / time zone: __________
Role / exact start and end: __________
People required / actual assignments: __________
Supplied availability / confirmation reference: __________
Check-in / role instructions / handoff: __________
Coordinator / change-report route: __________
Attendance / actual hours served (separate): __________</pre><p>Local view only. No sign-ups, saved assignments, notifications or timekeeping. Resolve the gap with the actual coordinator.</p></main><script>const rows=[{id:'W1',role:'welcome',label:'Welcome table',time:'9:00-10:00',name:'Avery'},{id:'W2',role:'welcome',label:'Welcome table',time:'10:00-11:00',name:null},{id:'S1',role:'sorting',label:'Book sorting',time:'9:00-10:00',name:'Blake'},{id:'S2',role:'sorting',label:'Book sorting',time:'10:00-11:00',name:'Casey'}];function render(){const role=document.querySelector('#role').value,shown=rows.filter(r=>role==='all'||r.role===role),listed=shown.filter(r=>r.name).length;window.coverage={role,required:shown.length,listed,gap:shown.length-listed,ids:shown.map(r=>r.id)};document.querySelector('#result').textContent='Selected view: '+shown.length+' required role-hours; '+listed+' listed role-hours; '+(shown.length-listed)+' unassigned role-hours.';document.querySelector('#rows').innerHTML=shown.map(r=>'<section data-shift="'+r.id+'"><h2>'+r.label+' · '+r.time+'</h2><p>Required: 1 person. Listed assignment: '+(r.name||'not supplied')+'.</p></section>').join('');}document.querySelector('#role').addEventListener('change',render);render();</script></body></html>