Slateboard • adoption evidence — Prepare a customer adoption review that links a defined workflow, distinct qualifying users, eligible population, measurement window 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>Slateboard • adoption 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}} .sheet{background:white;border:1px solid var(--line,#d6e0e7);padding:26px}.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.tiles>article{padding:20px;background:white;border:1px solid var(--line,#d6e0e7)}.badge{display:inline-block;border-radius:30px;padding:4px 11px;background:var(--tint,#e3f3fa);font-size:13px;font-weight:750}.preview{white-space:pre-wrap;overflow-wrap:anywhere}.schedule-row{display:grid;grid-template-columns:1fr 100px 100px;gap:15px;align-items:center;border-bottom:1px solid var(--line,#d6e0e7);padding:12px 0}.schedule-row label{margin:0}.schedule-row small{display:block}.schedule-row input{margin-top:6px}.export textarea{min-height:180px}.note{border-left:4px solid var(--accent,#176783);background:var(--tint,#e3f3fa);padding:16px}svg{max-width:100%;height:auto}button{overflow-wrap:anywhere}h2,h3,p{overflow-wrap:anywhere}@media(max-width:720px){.tiles{grid-template-columns:1fr}.schedule-row{grid-template-columns:1fr 80px}.schedule-row .range{grid-column:1/3}.sheet{padding:20px}}@media(max-width:400px){.sheet{padding:16px}}
body{--accent:#315f91;--tint:#e9f0fa;--bg:#f3f6fa;--ink:#25394e}.adoption-hero{display:grid;grid-template-columns:1fr 1.2fr;gap:32px;padding:30px;background:#fff;border-top:5px solid #315f91;box-shadow:0 8px 25px #2033420a}.adoption-hero .big{font-size:64px;color:#315f91}.users{display:grid;grid-template-columns:1fr 1fr;gap:10px}.user{background:#f0f3f7;padding:12px;border:1px solid #b6c5d6;border-radius:6px;font-weight:700}.user.used{border-left:5px solid #315f91;background:#e9f0fa}.user small{display:block;font-weight:400;font-size:12px}@media(max-width:720px){.adoption-hero{grid-template-columns:1fr;padding:22px;gap:16px}}</style></head><body><main>
<header><span class="eyebrow">Slateboard / fictional account review</span><h1>Who completed the agreed workflow?</h1><p class="intro">Completed weekly-plan exports, counted once per eligible user in the selected calendar window.</p></header>
<div class="account-tabs controls"><button type="button" id="account-a" class="secondary">A01 · measured</button><button type="button" id="account-b" class="secondary">B01 · unknown</button><button type="button" id="account-c" class="secondary">C01 · no eligible users</button></div>
<section class="adoption-hero"><div><span id="account-label" class="eyebrow"></span><div class="big" id="rate" aria-live="polite"></div><p id="basis"></p><p id="coverage"></p></div><div><h2>Eligible users</h2><div id="users" class="users"></div><p id="window-label"></p></div></section>
<div class="grid"><section class="panel"><h2>Inspect the measurement window</h2><div class="grid"><div><label for="start">First included date</label><input id="start" type="date" value="2026-10-06"></div><div><label for="end">Last included date</label><input id="end" type="date" value="2026-10-12"></div></div><div class="controls"><button type="button" id="calculate">Apply window</button><button type="button" id="reset" class="secondary">Reset review</button></div><p id="error" class="error" role="alert"></p><small>Coverage is supplied only for October 6–12. Narrower windows retain that coverage; broader windows are unknown. Local date-only boundaries, inclusive.</small></section>
<section class="panel"><h2>Portfolio evidence</h2><p><b>1 measured · 1 unknown · 1 not applicable</b> in the original window.</p><p>Do not pool 2 ÷ 8 into a portfolio adoption rate: B01's event coverage is unavailable.</p><p id="trend" class="note">Trend withheld: prior October 1–5 is 1/4 = 25%, but five days is not a comparable seven-day week.</p></section></div>
<section class="sheet"><span class="eyebrow">Preserved event ledger</span><h2 id="ledger-title"></h2><div class="table-wrap"><table><thead><tr><th>Event / user</th><th>Calendar date</th><th>Source action</th><th>Window decision</th></tr></thead><tbody id="ledger"></tbody></table></div></section>
<section class="panel"><h2>Next conversation, grounded in evidence</h2><p id="action"></p><p><b>Intended outcome:</b> shorter team planning. Baseline, measurement method and actual result: TO CONFIRM.</p><p>Workflow usage alone does not establish satisfaction, outcome achievement or renewal likelihood.</p></section>
<footer>Original sanitized companion, snapshot October 13, 2026. Planned follow-ups have not been sent. No event ingestion, live account connection, health scoring or persistent edits. Real timestamp/time-zone policy and maintained account records require confirmation.</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=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[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()}
function isoDay(s){if(!/^\d{4}-\d{2}-\d{2}$/.test(s))throw Error('Use a real calendar date as YYYY-MM-DD.');const d=new Date(s+'T00:00:00Z');if(!Number.isFinite(d.getTime())||d.toISOString().slice(0,10)!==s)throw Error('Use a real calendar date as YYYY-MM-DD.');return d.getTime()/86400000}
const events=[{id:'E01',user:'U01',date:'2026-10-06',kind:'Completed plan export'},{id:'E02',user:'U01',date:'2026-10-07',kind:'Completed plan export'},{id:'E03',user:'U02',date:'2026-10-12',kind:'Completed plan export'},{id:'E04',user:'U03',date:'2026-10-13',kind:'Completed plan export'},{id:'E05',user:'U04',date:'2026-10-08',kind:'Login'}];
const accounts={A01:{users:['U01','U02','U03','U04'],coverage:true,owner:'Mia',next:'Ask what prevented intended users from completing the agreed plan-export workflow during this window.'},B01:{users:['U05','U06','U07','U08'],coverage:false,owner:'Leo',next:'Resolve the event-coverage gap before interpreting usage.'},C01:{users:[],coverage:true,owner:'Mia',next:'Confirm rollout scope before interpreting an empty eligible population.'}};
let account='A01';
function adoption(a,start,end,rows){const s=isoDay(start),e=isoDay(end);if(s>e)throw Error('First included date must not follow the last included date.');if(e>isoDay('2026-10-13'))throw Error('The selected window extends beyond this supplied snapshot.');const covered=a.coverage&&s>=isoDay('2026-10-06')&&e<=isoDay('2026-10-12');const qualified=rows.filter(r=>a.users.includes(r.user)&&r.kind==='Completed plan export'&&isoDay(r.date)>=s&&isoDay(r.date)<=e);const users=[...new Set(qualified.map(r=>r.user))];return {covered,qualified,users,state:a.users.length===0?'Not applicable':covered?'Measured':'Unknown',rate:a.users.length&&covered?100*users.length/a.users.length:null}}
function pending(){for(const n of ['rate','basis','coverage','window-label','account-label'])txt(n,n==='rate'?'Pending window':'');$('users').innerHTML='';$('ledger').innerHTML='';txt('ledger-title','Apply a valid window');txt('action','');txt('error','')}
function calculate(){try{const a=accounts[account],s=$('start').value,e=$('end').value,r=adoption(a,s,e,account==='A01'?events:[]);txt('account-label',account+' · '+r.state);txt('rate',r.rate===null?r.state:r.rate+'%');txt('basis',r.rate===null?(r.state==='Unknown'?'Eligible denominator: '+a.users.length+'; qualifying-user count is unknown.':'Zero eligible users; a percentage is not applicable.'):(r.users.length+' distinct '+(r.users.length===1?'user':'users')+' ÷ '+a.users.length+' eligible · '+r.qualified.length+' qualifying '+(r.qualified.length===1?'event':'events')));txt('coverage',r.covered?'Event coverage complete for this window.':a.users.length?'Event coverage unavailable for this window.':'Confirm rollout scope; no eligible users supplied.');txt('window-label',s+' through '+e+' · inclusive');$('users').innerHTML=a.users.length?a.users.map(u=>'<span class="user '+(r.covered&&r.users.includes(u)?'used':'')+'">'+u+'<small>'+(r.covered?(r.users.includes(u)?'Completed export':'No qualifying export'):'Unknown usage')+'</small></span>').join(''):'<p>No eligible user IDs.</p>';txt('ledger-title',account+' source events · '+(account==='A01'?5:0)+' supplied records');$('ledger').innerHTML=account==='A01'?events.map(x=>{const inWindow=x.date>=s&&x.date<=e;const reason=!inWindow?'Outside selected window':x.kind!=='Completed plan export'?'Nonqualifying action':'Qualifies · '+(r.qualified.find(q=>q.user===x.user).id!==x.id?'same '+x.user+'; not another distinct user':'eligible user');return '<tr><td><b>'+x.id+'</b> / '+x.user+'</td><td>'+x.date+'</td><td>'+x.kind+'</td><td>'+reason+'</td></tr>'}).join(''):'<tr><td colspan="4">'+(account==='B01'?'No event coverage supplied; absence of rows is not measured zero.':'No eligible population supplied.')+'</td></tr>';txt('action',a.owner+' · planned, not sent: '+a.next);for(const [n,v]of [['account-a','A01'],['account-b','B01'],['account-c','C01']])$(n).setAttribute('aria-pressed',String(v===account));txt('error','')}catch(e){pending();txt('rate','No accepted window');txt('error',e.message)}}
for(const [n,v]of [['account-a','A01'],['account-b','B01'],['account-c','C01']])on(n,'click',()=>{account=v;calculate()});for(const n of ['start','end']){on(n,'input',pending);enter(n,calculate)}on('calculate','click',calculate);on('reset','click',()=>{account='A01';$('start').value='2026-10-06';$('end').value='2026-10-12';calculate()});calculate();
</script></body></html>