Field trip • Learning Gallery planning brief — Build a purpose-linked visit brief with travel/activity timing, distinct permission and headcount checkpoints, responsible roles and…
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>Field trip • Learning Gallery planning brief</title><style>*{box-sizing:border-box}body{margin:0;background:var(--bg,#eef3f6);color:#172a39;font:16px/1.5 system-ui,sans-serif}main{max-width:1200px;margin:auto;padding:28px}h1{font-size:clamp(27px,4vw,42px);line-height:1.12;margin:8px 0 12px;letter-spacing:-.035em}h2{font-size:23px;line-height:1.2;margin:0 0 18px}h3{font-size:17px;margin:14px 0 8px}p{margin:8px 0 16px}.eyebrow{font-size:12px;text-transform:uppercase;letter-spacing:.15em;font-weight:800;color:var(--accent,#176b71)}.lead{max-width:75ch;color:#405568}.panel{background:#fff;border:1px solid #cdd9e1;border-radius:14px;padding:24px;margin:18px 0}.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.wide{grid-template-columns:1.6fr 1fr}.metric-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.metric{border-left:4px solid var(--accent,#176b71);background:#f4f8fa;padding:18px}.big{display:block;font-size:36px;font-weight:800;line-height:1.2}.muted,small{color:#536879;font-size:14px}.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}button{background:var(--accent,#176b71);color:white;border:2px solid transparent;border-radius:8px;padding:10px 16px;min-height:44px;cursor:pointer;font:inherit;font-weight:650}button.secondary{background:#e8eff4;color:#172a39}button:disabled{opacity:.48;cursor:default}button[aria-pressed=true]{outline:3px solid #172a39;outline-offset:2px}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible{outline:3px solid #de7616;outline-offset:3px}label{display:block;font-weight:650;margin:12px 0 6px}input,select,textarea{font:inherit;color:inherit;border:1px solid #8b9eae;border-radius:6px;background:white;padding:10px;width:100%;min-height:44px}textarea{resize:vertical;min-height:110px}input[type=checkbox]{width:22px;min-height:22px;vertical-align:middle}table{border-collapse:collapse;width:100%;font-size:14px}th{text-align:left;background:#eff4f7;color:#3d5261}th,td{padding:12px;border-bottom:1px solid #dce5eb;vertical-align:top}.scroll{overflow-x:auto}caption{text-align:left;margin-bottom:12px;font-weight:700}.notice{background:#eef5f9;border-left:4px solid #628ba1;padding:14px;margin:14px 0}.error{color:#9c2924;font-weight:650}.pill{display:inline-block;border-radius:30px;padding:4px 10px;background:#e5f3ee;color:#17614f;font-size:13px;font-weight:750}.draft{white-space:pre-wrap;font:17px/1.65 Georgia,serif}.rule{display:block;width:100%;text-align:left;margin:10px 0}.rule strong{font-size:26px}details{margin:18px 0}summary{cursor:pointer;font-weight:700;padding:12px;background:#e9eff3;border-radius:6px;min-height:44px}footer{margin:30px 0;color:#536879;font-size:14px}ol,ul{padding-left:23px}.time-input{max-width:90px}.section-no{font-size:52px;color:#b5c8d5;font-weight:800;line-height:1}.tag{font-weight:700;color:var(--accent,#176b71)}[hidden]{display:none!important}@media(max-width:760px){main{padding:18px}.grid,.wide{grid-template-columns:1fr}.metric-grid{grid-template-columns:1fr}.panel{padding:18px}.big{font-size:30px}th,td{padding:9px}}:root{--accent:#24786c;--bg:#eef5f0}.sample{display:flex;align-items:center;justify-content:center;gap:40px;background:#faf6ed;border:1px solid #dccfb3;min-height:175px;margin:20px 0}.circle{width:75px;height:75px;border-radius:50%;background:#2874ad}.square{width:75px;height:75px;background:#c5403d}.metric{margin-bottom:12px}</style></head><body><main>
<span class="eyebrow">Proposed educational visit / fictional Learning Gallery</span><h1>A visit with time to look closely.</h1><p class="lead">Plan one visible-feature observation and one question for the host.</p>
<section class="panel"><div class="grid wide"><div><h2>Proposed local itinerary</h2><label for="start-time">Planned departure time — date and local time zone unconfirmed</label><input id="start-time" type="time" value="09:00"><div class="scroll"><table><thead><tr><th>Activity</th><th>Planned minutes</th><th>Local time</th></tr></thead><tbody><tr><td>Outbound travel</td><td><label for="minutes-0" class="muted">Outbound travel duration</label><input class="time-input" id="minutes-0" type="number" min="1" max="240" value="30"></td><td id="range-0"></td></tr><tr><td>Orientation</td><td><label for="minutes-1" class="muted">Orientation duration</label><input class="time-input" id="minutes-1" type="number" min="1" max="240" value="10"></td><td id="range-1"></td></tr><tr><td>Observation task</td><td><label for="minutes-2" class="muted">Observation task duration</label><input class="time-input" id="minutes-2" type="number" min="1" max="240" value="40"></td><td id="range-2"></td></tr><tr><td>Questions and reflection</td><td><label for="minutes-3" class="muted">Questions and reflection duration</label><input class="time-input" id="minutes-3" type="number" min="1" max="240" value="20"></td><td id="range-3"></td></tr><tr><td>Buffer</td><td><label for="minutes-4" class="muted">Buffer duration</label><input class="time-input" id="minutes-4" type="number" min="1" max="240" value="20"></td><td id="range-4"></td></tr><tr><td>Return travel</td><td><label for="minutes-5" class="muted">Return travel duration</label><input class="time-input" id="minutes-5" type="number" min="1" max="240" value="30"></td><td id="range-5"></td></tr></tbody></table></div><button type="button" id="restore-itinerary" class="secondary">Restore proposed itinerary</button></div><div><span class="pill">Proposal · no booking or approval recorded</span><div class="metric">Travel<strong class="big" id="travel"></strong></div><div class="metric">On site, including buffer<strong class="big" id="on-site"></strong></div><div class="metric">Whole visit<strong class="big" id="whole"></strong></div><p id="trip-error" class="error" role="status"></p><p class="muted">The 20-minute buffer is planned slack, not completed learning. Route and travel times have not been validated.</p></div></div></section>
<div class="grid"><section class="panel"><h2>Practice noticing / not guessing</h2><div class="sample" role="img" aria-label="Fictional rehearsal card: one blue circle and one red square"><span class="circle"></span><span class="square"></span></div><p>Fictional rehearsal card, not an actual exhibit. Which statement is supported by what is visible?</p><div class="row"><button type="button" id="observe-feature">The card contains a red square</button><button type="button" id="infer-purpose" class="secondary">Red means danger here</button></div><p id="practice-feedback" class="notice" aria-live="polite">Choose a statement to compare observation with explanation.</p><p>For a purpose claim, ask the host: “Why were these colors chosen?” The host’s answer is not supplied.</p></section><section class="panel"><h2>At the destination / learner evidence</h2><label for="observation">One actual visible feature (leave blank before the visit)</label><textarea id="observation"></textarea><label for="host-question">One question to ask the host</label><textarea id="host-question"></textarea><label for="host-answer">Actual host answer, if given</label><textarea id="host-answer"></textarea><label for="reflection">After the visit: distinguish your observation from the host’s explanation</label><textarea id="reflection"></textarea></section></div>
<section class="panel"><h2>Preparation / confirmations still needed</h2><div class="grid"><div><label for="visit-date">Actual visit date</label><input id="visit-date" type="date" value=""><label for="zone">Confirmed local time zone</label><input id="zone" type="text" value=""><label for="host-booking">Host booking evidence</label><input id="host-booking" type="text" value=""><label for="transport">Authorized transport evidence</label><input id="transport" type="text" value=""></div><div><p><strong>Teacher lead:</strong> confirm purpose, approval, permission, supervision and approved record workflow.</p><p><strong>Host liaison:</strong> confirm booking, exhibits, timing and access.</p><label for="teacher-owner">Actual teacher lead</label><input id="teacher-owner" type="text" value=""><label for="host-owner">Actual host liaison</label><input id="host-owner" type="text" value=""><label for="transport-owner">Actual authorized transport role / owner</label><input id="transport-owner" type="text" value=""></div></div><p>No supervision ratio, emergency procedure or safety approval is supplied by this specimen. Confirm the applicable school requirements through the authorized workflow.</p></section>
<section class="panel"><h2>Permission records ≠ attendance</h2><div class="grid"><div><table><thead><tr><th>Fictional record</th><th>Permission status</th></tr></thead><tbody><tr><td>S01</td><td>Received</td></tr><tr><td>S02</td><td>Received</td></tr><tr><td>S03</td><td>Pending</td></tr></tbody></table><p class="notice">2 of 3 permission records received. Ask the teacher lead about S03. This is not an attendance count, approval or readiness-to-go decision.</p></div><div><h3>Actual checkpoint counts / supplied evidence only</h3><label for="departure-count">Departure count — unknown until checked</label><input id="departure-count" type="number" value=""><label for="arrival-count">Arrival count — unknown until checked</label><input id="arrival-count" type="number" value=""><label for="return-count">Return count — unknown until checked</label><input id="return-count" type="number" value=""><label for="reconciliation">Private roster reconciliation reference / unresolved count question (no names)</label><textarea id="reconciliation"></textarea><p id="counts-state" class="notice" aria-live="polite"></p></div></div></section>
<section class="panel"><h2>Working visit brief</h2><label for="brief-text">Itinerary, learning task and confirmation questions</label><textarea id="brief-text" readonly></textarea><button type="button" id="select-brief-text" class="secondary">Select text</button><p id="brief-text-status" class="muted">Select the text, then use your device’s copy command. Nothing is saved.</p></section><footer>This local planning companion does not book a visit, approve transport, collect permission or certify safety. Keep roster identities, contact and medical details in the school’s approved private workflow. Nothing entered here is saved.</footer></main><script>const $=id=>document.getElementById(id);const on=(id,fn)=>$(id).addEventListener('click',fn);const text=(id,value)=>$(id).textContent=value;const bind=(id,fn,event='input')=>$(id).addEventListener(event,fn);const selectText=id=>{if(!$(id).value){text(id+'-status','Complete the required fields before selecting text.');return;}$(id).focus();$(id).select();text(id+'-status','Text selected. Use your device’s copy command; nothing has been sent or saved.');};
const names=["Outbound travel","Orientation","Observation task","Questions and reflection","Buffer","Return travel"],defaults=[30,10,40,20,20,30];function minute(v){if(!/^\d{2}:\d{2}$/.test(v))return null;const [h,m]=v.split(':').map(Number);return h<24&&m<60?h*60+m:null;}const clock=n=>String(Math.floor(n/60)).padStart(2,'0')+':'+String(n%60).padStart(2,'0');function itinerary(start,values){if(start===null||!Number.isFinite(start)||values.some(v=>!/^\d+$/.test(String(v))||+v<1||+v>240))return null;let end=start;const blocks=values.map(v=>{const row={start:end,end:end+(+v)};end=row.end;return row;});if(end>=1440)return null;return {blocks,travel:+values[0]+(+values[5]),onsite:values.slice(1,5).reduce((a,v)=>a+(+v),0),total:end-start,end};}function countState(){const ids=['departure-count','arrival-count','return-count'],v=ids.map(k=>$(k).value);if(v.some(x=>x!==''&&!/^\d+$/.test(x)))return 'Invalid checkpoint count — use nonnegative whole numbers or leave unknown.';if(v.some(x=>x===''))return 'Actual counts incomplete / unknown. Permission records do not fill these fields.';if(new Set(v.map(Number)).size!==1)return 'Counts differ — reconcile against the private approved roster. No attendance or safety conclusion has been made.';return $('reconciliation').value.trim()?'Equal counts recorded with a supplied reconciliation note. Identity reconciliation and authorization still require the approved school workflow.':'Equal counts alone do not establish identity reconciliation. Add the approved private roster reference or unresolved question.';}function update(){const r=itinerary(minute($('start-time').value),defaults.map((_,i)=>$('minutes-'+i).value));text('travel',r?r.travel+' min':'—');text('on-site',r?r.onsite+' min':'—');text('whole',r?r.total+' min':'—');text('trip-error',r?'':'Itinerary incomplete — use 1–240 whole minutes per stage and finish before midnight.');defaults.forEach((_,i)=>text('range-'+i,r?clock(r.blocks[i].start)+'–'+clock(r.blocks[i].end):'—'));const counts=countState();text('counts-state',counts);$('brief-text').value=r?'PROPOSED LEARNING GALLERY VISIT\nDate: '+($('visit-date').value||'[TO CONFIRM]')+'\nLocal time zone: '+($('zone').value||'[TO CONFIRM]')+'\n'+names.map((n,i)=>clock(r.blocks[i].start)+'–'+clock(r.blocks[i].end)+' '+n).join('\n')+'\nTravel '+r.travel+' min; on site '+r.onsite+' min including buffer; total '+r.total+' min.\nLearning task: record one visible feature and one question for the host. Do not infer the exhibit’s purpose.\nHost booking: '+($('host-booking').value||'[TO CONFIRM]')+'\nTransport authorization: '+($('transport').value||'[TO CONFIRM]')+'\nTeacher lead: '+($('teacher-owner').value||'[TO CONFIRM]')+'\nHost liaison: '+($('host-owner').value||'[TO CONFIRM]')+'\nTransport owner: '+($('transport-owner').value||'[TO CONFIRM]')+'\nPermission specimen: 2 of 3 received; S03 pending. Ask teacher lead. Not attendance.\nActual departure count: '+($('departure-count').value||'[unknown]')+'\nActual arrival count: '+($('arrival-count').value||'[unknown]')+'\nActual return count: '+($('return-count').value||'[unknown]')+'\nCheckpoint review: '+counts+'\nReconciliation reference: '+($('reconciliation').value||'[not supplied]')+'\nActual observation: '+($('observation').value||'[not recorded]')+'\nHost question: '+($('host-question').value||'[not recorded]')+'\nHost answer: '+($('host-answer').value||'[not recorded]')+'\nReflection: '+($('reflection').value||'[not recorded]')+'\nConfirm school purpose approval, permission, supervision, access, timings and record workflow before proceeding.':'';}['start-time','visit-date','zone','host-booking','transport','teacher-owner','host-owner','transport-owner','departure-count','arrival-count','return-count','reconciliation','observation','host-question','host-answer','reflection'].forEach(k=>bind(k,update));defaults.forEach((_,i)=>bind('minutes-'+i,update));on('restore-itinerary',()=>{$('start-time').value='09:00';defaults.forEach((v,i)=>$('minutes-'+i).value=String(v));update();});on('observe-feature',()=>text('practice-feedback','Supported observation: the fictional card contains a red square. Why the colors were chosen is not established.'));on('infer-purpose',()=>text('practice-feedback','Unconfirmed explanation: the card does not establish that red means danger. Ask the host why the colors were chosen.'));on('select-brief-text',()=>selectText('brief-text'));update();globalThis.app={itinerary,minute,countState};</script></body></html>