A fictional exhibition-move communication plan with audience filters and recurring versus triggered updates

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>Exhibition move · communication plan</title><style>
*{box-sizing:border-box}body{margin:0;background:#f1f2ed;color:#2c4037;font:16px/1.6 system-ui,sans-serif}main{max-width:1050px;margin:auto;padding:28px}h1{font:700 clamp(31px,5vw,48px)/1.12 Georgia,serif;margin:12px 0 18px}h2{font-size:24px;line-height:1.3}h3{font-size:19px;margin:0 0 10px}p{margin:8px 0 16px}p,h1,h2,h3,label,button,dd{overflow-wrap:anywhere}.eyebrow{font-size:16px;letter-spacing:.08em;font-weight:750}.panel{padding:22px;background:white;border:1px solid #bbc9bb;border-radius:8px;margin:22px 0}.scope{background:#305143;color:white;padding:20px;border-radius:8px}.toolbar{display:flex;flex-wrap:wrap;gap:10px;margin:16px 0}.grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}.row{border-left:5px solid #688268;padding:18px;margin:16px 0;background:#f4f7ef}.row h3{color:#284f3b}.tag{display:inline-block;background:#e4edde;padding:4px 9px;border-radius:4px;font-weight:700}dl{margin:0}dt{font-weight:750;margin-top:12px}dd{margin:3px 0 12px}.note{background:#e5eddf;padding:16px}.status{border-left:5px solid #b56e36;padding:14px;background:#fff0d9}button,input,textarea{font:inherit}button{min-height:44px;padding:10px 15px;border:1px solid #56735e;border-radius:5px;background:white;color:inherit;cursor:pointer}button[aria-pressed="true"]{color:white;background:#305143}button:hover{box-shadow:inset 0 0 0 1px #305143}button:focus-visible,input:focus-visible,textarea:focus-visible{outline:3px solid #b75d24;outline-offset:3px}label{display:block;font-weight:650;margin:14px 0 6px}input,textarea{display:block;width:100%;min-width:0;min-height:44px;border:1px solid #71846d;border-radius:4px;padding:10px;background:white;color:inherit}textarea{min-height:110px;resize:vertical}.compare{padding:18px;background:#f8f4e9;border-top:5px solid #b3814c}.compare.revised{background:#eef5ea;border-color:#51764e}div,section,article{min-width:0}footer{border-top:1px solid #bbc9bb;padding-top:18px;margin-top:26px}[hidden]{display:none!important}@media(max-width:650px){main{padding:16px}.panel{padding:16px}.grid{grid-template-columns:1fr}.toolbar button{flex:1 1 140px}}
</style></head><body><main><p class="eyebrow">ORIGINAL FICTIONAL PROJECT · PLANNED COMMUNICATION</p><h1>Give each audience the update it needs.</h1><p>A museum is moving an exhibition into another room. Separate the sponsor’s wider project update from the instruction a volunteer needs before an affected shift.</p><div class="scope">The roles, channels and timing below are supplied teaching arrangements. No actual dates, mailing list, sent messages or receipts are supplied. These are plans, not completed communications.</div>
<section class="panel" aria-labelledby="plan-title"><h2 id="plan-title">Who needs what?</h2><div class="toolbar" role="group" aria-label="Audience filter"><button id="audience-all" type="button" aria-pressed="true">All audiences</button><button id="audience-sponsor" type="button" aria-pressed="false">Sponsor</button><button id="audience-team" type="button" aria-pressed="false">Move team</button><button id="audience-hosts" type="button" aria-pressed="false">Volunteer hosts</button></div><label for="audience-search">Narrow the view by audience name</label><input id="audience-search" type="search" placeholder="For example, Volunteer"><p id="filter-status" role="status" aria-live="polite">All audiences · 3 planned activities</p><div id="rows"><article class="row" id="cp1" data-audience="sponsor"><h3>CP1 · Sponsor</h3><span class="tag">Recurring + decision-triggered</span><dl><dt>Information and purpose</dt><dd>Milestone changes, spending decisions, and choices needed for the room move.</dd><dt>Owner</dt><dd>Project lead</dd><dt>Channel</dt><dd>Sponsor review meeting</dd><dt>Cadence or trigger</dt><dd>Weekly during the move; a separate decision request when a choice cannot wait for that meeting.</dd></dl></article><article class="row" id="cp2" data-audience="team"><h3>CP2 · Move team</h3><span class="tag">Session-based + sequence changes</span><dl><dt>Information and purpose</dt><dd>Next handoffs, work sequence, and dependencies affecting the coming work.</dd><dt>Owner</dt><dd>Move coordinator</dd><dt>Channel</dt><dd>Team planning meeting</dd><dt>Cadence or trigger</dt><dd>Before each planned move session; revise the briefing when the sequence changes.</dd></dl></article><article class="row" id="cp3" data-audience="hosts"><h3>CP3 · Volunteer hosts</h3><span class="tag">Change-triggered · before the shift</span><dl><dt>Information and purpose</dt><dd>Confirmed entrance, visitor route, and duties affecting the recipient's assigned shift.</dd><dt>Owner</dt><dd>Volunteer coordinator</dd><dt>Channel</dt><dd>Agreed volunteer email list</dd><dt>Cadence or trigger</dt><dd>When an approved route or duty change affects a shift, before that shift begins.</dd></dl></article></div><p id="empty" class="note" hidden>No matching plan rows. This filter result does not establish that the audience has no communication needs.</p></section>
<section class="panel" aria-labelledby="timing-title"><h2 id="timing-title">Does a weekly update arrive before the work?</h2><p>CP3 needs a confirmed route instruction for the affected shift. Compare two timing arrangements without changing the supplied plan.</p><button id="compare" type="button" aria-expanded="false" aria-controls="timing-comparison">Compare timing</button><div id="timing-comparison" hidden><div class="grid"><article class="compare"><h3>Weekly-only proposal</h3><p>Include route changes in the weekly project summary.</p><p><strong>What the volunteer can rely on:</strong> No link between that summary and the next affected shift is specified.</p></article><article class="compare revised"><h3>Revised teaching plan</h3><p>Send the confirmed route instruction to affected hosts before their next affected shift.</p><p><strong>What the volunteer can rely on:</strong> Timing is tied to the work that needs the instruction.</p></article></div><p class="note">The weekly sponsor update can remain. The shift instruction serves a different action deadline. Confirm approval responsibility and preparation lead time; a table cannot resolve an impossible deadline.</p></div></section>
<section class="panel" aria-labelledby="blank-title"><h2 id="blank-title">Blank scaffold · one activity for your project</h2><p>Record an actual arrangement with the people responsible. This scaffold checks only whether core fields contain text. It cannot confirm a channel, decide approval or schedule delivery.</p><div class="grid"><div><label for="project">Project scope and period</label><textarea id="project"></textarea><label for="audience">Audience and action they need to take</label><textarea id="audience"></textarea><label for="information">Information and purpose</label><textarea id="information"></textarea></div><div><label for="owner">Information owner and backup to confirm</label><textarea id="owner"></textarea><label for="channel">Channel and access or format arrangement</label><textarea id="channel"></textarea><label for="timing">Cadence or trigger and action deadline</label><textarea id="timing"></textarea></div></div><label for="unresolved">Team decisions still needed · approvals, notice, conflicts</label><textarea id="unresolved" placeholder="What needs an owner’s decision before the plan can be used?"></textarea><div class="toolbar"><button id="check" type="button">Check core fields</button><button id="reset" type="button">Clear my scaffold</button></div><p id="status" class="status" role="status" aria-live="polite">Your project scaffold starts blank. No update is sent or scheduled.</p><div id="confirmation" hidden><p>Clear all seven scaffold fields? The fictional plan and timing comparison will stay unchanged.</p><div class="toolbar"><button id="confirm-reset" type="button">Clear typed work</button><button id="keep" type="button">Keep typed work</button></div></div></section><footer>Typing stays only in this open page; reloading clears it. No addresses are collected, and nothing is stored, sent, scheduled, approved or marked complete. Keep actual delivery and acknowledgement records in your normal project system.</footer></main>
<script>(()=>{'use strict';const $=id=>document.getElementById(id);const audiences={all:'All audiences',sponsor:'Sponsor',team:'Move team',hosts:'Volunteer hosts'};let current='all';function filter(){const query=$('audience-search').value.trim().toLowerCase();let count=0;for(const row of document.querySelectorAll('#rows article')){const matches=(current==='all'||row.dataset.audience===current)&&row.querySelector('h3').textContent.toLowerCase().includes(query);row.hidden=!matches;if(matches)count++;}$('empty').hidden=count!==0;$('filter-status').textContent=audiences[current]+' · '+count+' planned '+(count===1?'activity':'activities')+(query?' · audience name contains “'+$('audience-search').value.trim()+'”':'');}for(const key of Object.keys(audiences))$('audience-'+key).addEventListener('click',()=>{current=key;for(const k of Object.keys(audiences))$('audience-'+k).setAttribute('aria-pressed',String(k===key));filter();});$('audience-search').addEventListener('input',filter);$('compare').addEventListener('click',()=>{const open=$('timing-comparison').hidden;$('timing-comparison').hidden=!open;$('compare').setAttribute('aria-expanded',String(open));$('compare').textContent=open?'Hide timing comparison':'Compare timing';});const fields={project:'project scope and period',audience:'audience and action',information:'information and purpose',owner:'information owner',channel:'channel arrangement',timing:'cadence or trigger and deadline'};for(const id of [...Object.keys(fields),'unresolved'])$(id).addEventListener('input',()=>{$('status').textContent='Scaffold changed. Check core fields again; no arrangements have been confirmed.';});$('check').addEventListener('click',()=>{const missing=Object.keys(fields).filter(id=>!$(id).value.trim()).map(id=>fields[id]);$('status').textContent=missing.length?'Still to record: '+missing.join('; ')+'. No arrangements have been confirmed.':'All six core fields contain text. Confirm the owner, channel, timing, approvals and any conflicts with the team; this is not approval or a delivery record.';});$('reset').addEventListener('click',()=>{$('confirmation').hidden=false;$('keep').focus();});$('keep').addEventListener('click',()=>{$('confirmation').hidden=true;$('status').textContent='Kept all your scaffold fields.';$('reset').focus();});$('confirm-reset').addEventListener('click',()=>{for(const id of [...Object.keys(fields),'unresolved'])$(id).value='';$('confirmation').hidden=true;$('status').textContent='Your scaffold was cleared. The fictional plan and current filters are unchanged.';$('project').focus();});})();</script></body></html>