Task app scope & quote
HTML for this example
Select the code and use your copy shortcut. Changes in this preview are temporary.
<!doctype html><html lang="en-US"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Task app scope & quote</title><style>*{box-sizing:border-box}html{color-scheme:light}body{margin:0;background:var(--bg,#eef1f4);color:var(--ink,#233449);font:16px/1.5 system-ui,-apple-system,Segoe UI,sans-serif}main{max-width:1040px;margin:auto;padding:26px 28px 44px}header{margin-bottom:20px}h1{font-size:clamp(26px,4vw,36px);letter-spacing:-.035em;line-height:1.15;margin:5px 0 10px}h2{font-size:21px;line-height:1.3;margin:0 0 15px}h3{font-size:17px;margin:0 0 9px}p{margin:8px 0 16px}.kicker{font-size:12px;text-transform:uppercase;letter-spacing:.12em;font-weight:750;color:var(--accent,#315b87)}.muted,small{color:#556473}.panel{margin:20px 0;padding:24px;border:1px solid var(--line,#ccd5df);border-radius:10px;background:#fff}.hero{padding:24px;background:var(--hero,#183b5c);color:#fff;border-radius:12px;margin:18px 0}.hero .kicker,.hero small{color:#d9e5ef}.big{font-size:clamp(32px,5vw,52px);line-height:1.15;font-weight:750;letter-spacing:-.035em;overflow-wrap:anywhere;margin:10px 0 15px}.row{display:flex;flex-wrap:wrap;gap:15px;align-items:end}.row>label{flex:1;min-width:140px}.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.thirds{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px}label{display:block;font-size:14px;font-weight:650}input,select,textarea{font:inherit;font-size:16px;color:inherit;display:block;width:100%;margin-top:6px;padding:11px 12px;border:1px solid #a9b4c1;border-radius:6px;background:white;min-width:0}input[type=checkbox]{display:inline;width:auto;margin:0 8px 0 0;accent-color:var(--accent,#315b87)}textarea{min-height:100px;resize:vertical}button{font:inherit;font-weight:650;min-height:44px;border:1px solid var(--accent,#315b87);border-radius:6px;background:var(--accent,#315b87);color:white;padding:10px 16px;cursor:pointer}button.secondary{background:white;color:var(--accent,#315b87)}button:disabled{opacity:.5;cursor:default}button[aria-pressed=true]{box-shadow:0 0 0 3px #eab655}button:hover:not(:disabled){filter:brightness(.94)}:focus-visible{outline:3px solid #e5a72f;outline-offset:3px}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0 0}[hidden]{display:none!important}.error{color:#a3232a;font-weight:650}.error:not(:empty){padding:12px;background:#fff0ed;border-left:4px solid #ab3439;margin:14px 0}.note{padding:14px;background:#edf2f6;border-radius:6px;margin:14px 0}.mono,pre{font-family:ui-monospace,Consolas,monospace;font-variant-numeric:tabular-nums}pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px;line-height:1.7;margin:0}.mono{overflow-wrap:anywhere}table{width:100%;border-collapse:collapse;table-layout:fixed;font-size:14px}th,td{text-align:left;vertical-align:top;overflow-wrap:anywhere;padding:11px 8px;border-bottom:1px solid #d4dce4}th{font-size:12px;text-transform:uppercase;letter-spacing:.035em;color:#536372}th:first-child,td:first-child{padding-left:0}.tag{display:inline-block;padding:4px 8px;border:1px solid currentColor;border-radius:4px;font-size:12px;font-weight:750}.rule{border-top:1px solid #cbd4dd;padding-top:18px}.line{height:30px;border-bottom:1px solid #aab5bf}.stat{font-size:34px;line-height:1.15;font-weight:750}.stat small{font:14px system-ui;display:block;margin-top:8px}details{margin:20px 0;border-top:1px solid #cbd4dd;padding:18px 0}summary{font-weight:700;cursor:pointer}details p{margin-top:15px}a{color:var(--accent,#315b87)}footer{font-size:13px;color:#556473;margin-top:25px}fieldset{min-width:0;border:1px solid #c8d2db;border-radius:7px;padding:18px;margin:15px 0}legend{font-weight:750;padding:0 6px}@media(max-width:720px){main{padding:20px}.panel,.hero{padding:20px}.thirds{gap:10px}}@media(max-width:540px){main{padding:16px}.grid,.thirds{grid-template-columns:1fr}.panel,.hero{padding:18px}.row{gap:12px}.row>label{min-width:100px}h1{font-size:27px}th,td{padding:10px 5px;font-size:13px}.big{font-size:37px}}.surface{background:white;border:1px solid #ccd5df;border-radius:10px;padding:24px;margin:18px 0}.metrics{display:flex;gap:34px;flex-wrap:wrap}.metric b{font-size:clamp(32px,5vw,52px);line-height:1.1;display:block;letter-spacing:-.04em}.metric span{display:block;margin-top:8px;font-size:14px}.strip{display:grid;grid-template-columns:repeat(10,minmax(0,1fr));gap:7px;margin:22px 0}.unit{padding:10px 3px;text-align:center;background:#e5f0eb;border-bottom:4px solid #327660;font-size:13px;font-weight:700}.unit.rework{background:#fff0d5;border-color:#aa701d}.unit.fail{background:#f9e2e0;border-color:#ab3d35}.ledger-row{display:grid;grid-template-columns:100px 1fr 140px;gap:18px;padding:18px 0;border-bottom:1px solid #d2dbe3;align-items:start}.ledger-row p{margin:5px 0}.amount{text-align:right;font-size:22px;font-weight:750}.pill{display:inline-block;border-radius:20px;background:#e7edf2;padding:5px 10px;font-size:12px;font-weight:700}.timeline{border-left:3px solid #c7d4de;padding:0 0 0 22px;margin:16px 0}.timeline article{padding:10px 0 18px}.timeline h3{margin-bottom:5px}.timeline p{margin:5px 0}.artifact{font-family:Georgia,serif}.warning{background:#fff3db;border-left:4px solid #a66d18;padding:15px}.empty{color:#5d6771;font-style:italic}.check{color:#22694f}.bad{color:#9a332e}button.linklike{padding:8px 12px;min-height:40px;background:white;color:var(--accent,#315b87)}@media(max-width:540px){.surface{padding:18px}.ledger-row{grid-template-columns:65px 1fr;gap:12px}.ledger-row .amount{grid-column:2;text-align:left}.strip{gap:3px}.unit{font-size:11px;padding:8px 0}.metrics{gap:22px}.metric b{font-size:38px}}.scope-sheet{border-top:6px solid #476c6a}.change-box{padding:20px;background:#eaf1ef;border-radius:6px}.scope-sheet .big{font-family:Georgia,serif}.change-box .stat{font-size:29px}</style></head><body style="--bg:#eff4f2;--accent:#3d6d67"><main><header><div class="kicker">Fictional working example</div><h1>Task app scope & quote</h1><p class="muted">Trace the $600 original scope and keep the CSV change unestimated.</p></header><section class="surface scope-sheet"><div class="kicker">QS01 · illustrative USD · no app built here</div><div class="grid"><div><h2>Original priced scope</h2><div class="big">$600.00</div><p>F01 $300 + F02 $120 + F03 $180</p></div><div class="change-box"><h2 id="changeTitle"></h2><div class="stat" id="revised"></div><p id="estimateState"></p></div></div></section><div class="row"><label for="request">Scope view<select id="request"><option value="csv">Original + F04 CSV request</option><option value="original">Original QS01 only</option></select></label><label for="feature">Inspect feature and acceptance<select id="feature"><option value="F01">F01 · Add and edit tasks</option><option value="F02">F02 · Open / Completed filter</option><option value="F03">F03 · Acceptance checks and handoff</option><option value="F04">F04 · Requested CSV import</option></select></label></div><section class="surface"><div id="featureRecord"></div></section><section class="panel"><h2>Clarification draft · unsent</h2><label for="notes">Your questions for the requester<textarea id="notes">Which CSV columns are required? How should invalid rows and duplicate tasks be handled? What encoding and sample file will be supplied?</textarea></label><div class="actions"><button type="button" id="draft">Build local clarification draft</button></div><pre id="message" class="note"></pre><p id="draftState" aria-live="polite"></p></section><details><summary>Change control and honest limits</summary><p>F04 is request CR01 against QS01, not an included feature or accepted change. Implementation, acceptance tests, handoff, price, schedule, reviewer, and decision remain unestimated or unconfirmed. Adding clarification text does not approve scope or produce a revised total.</p><p>The fixture provides expected checks C01 and C02; actual application test results are blank. Editing-specific acceptance criteria, environment, evidence format, handoff contents, and acceptance authority still need agreement. This page builds a quote worksheet, not a task application, CSV parser, agreement, or legal terms.</p></details><footer>Local session only. Nothing is sent, saved, approved, or submitted. Keep maintained source records authoritative.</footer></main><script>const $=id=>document.getElementById(id);const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));const money=n=>'$'+n.toFixed(2);
const features=[{id:'F01',title:'Add and edit tasks',fee:300,expected:'C01: adding a title produces one visible task.',dependency:'Agree title validation, editable fields, and task representation. Editing-specific checks remain unconfirmed.'},{id:'F02',title:'Open / Completed filter',fee:120,expected:'C02: marking a task complete removes it from the Open view.',dependency:'Agree stored task status and filter behavior.'},{id:'F03',title:'Supplied acceptance checks and handoff',fee:180,expected:'Run agreed C01/C02 checks and provide agreed handoff.',dependency:'Confirm environment, evidence format, handoff contents, and acceptance authority.'},{id:'F04',title:'CSV import request',fee:null,expected:'Acceptance criteria not agreed.',dependency:'Confirm column mapping, encoding, invalid rows, duplicates, sample files, verification, and handoff.'}];function totals(includeCSV){const known=features.filter(f=>f.fee!==null).reduce((s,f)=>s+f.fee,0);return {known,revised:includeCSV?null:known}}
function render(){const change=$('request').value==='csv',t=totals(change);$('changeTitle').textContent=change?'F04 · CSV import request':'Original scope selected';$('revised').textContent=change?'Not estimated':money(t.known);$('estimateState').textContent=change?'Known baseline: $600. No complete revised total.':'Original illustrative total. No CSV import included.';const f=features.find(f=>f.id===$('feature').value);$('featureRecord').innerHTML='<div class="kicker">'+f.id+'</div><h2>'+f.title+'</h2><div class="ledger-row"><b>Price</b><span>'+(f.fee===null?'Requested change; no estimate supplied':money(f.fee)+' illustrative fixed line')+'</span><span class="pill">'+(f.fee===null?'Unestimated':'Original scope')+'</span></div><div class="ledger-row"><b>Expected</b><span>'+f.expected+'</span><span>Not executed</span></div><div class="ledger-row"><b>Depends on</b><span>'+f.dependency+'</span><span>Confirm</span></div><p class="empty">Actual application result / evidence / verifier / date: blank.</p>';$('message').textContent='';$('draftState').textContent='Build a new draft for the current scope view.'}
['request','feature'].forEach(x=>$(x).addEventListener('change',render));$('notes').addEventListener('input',()=>{$('message').textContent='';$('draftState').textContent='Questions changed. Rebuild the local draft.'});$('draft').onclick=()=>{const csv=$('request').value==='csv',notes=$('notes').value.trim();if(!notes){$('message').textContent='';$('draftState').textContent='Enter at least one clarification question.';return}$('message').textContent='UNSENT · '+(csv?'CR01 against QS01':'QS01 clarification')+'\nOriginal scope: F01 + F02 + F03 = $600.00.\n'+(csv?'Requested behavior: CSV import (F04). Price, implementation, checks, handoff, and schedule: unestimated.\n':'CSV import is outside this selected original scope.\n')+'Questions:\n'+notes+'\nReviewer / decision: unconfirmed.';$('draftState').textContent='Local draft built. No recipient was contacted and no scope was approved.'};render();</script></body></html>