QV01: landscape edit, vertical change

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>QV01: landscape edit, vertical change</title><style>*{box-sizing:border-box}:root{--ink:#26353e;--muted:#526771;--accent:#285f77;--line:#d0dade;--soft:#edf3f5;color-scheme:light}body{margin:0;background:#f2f5f5;color:var(--ink);font:16px/1.5 system-ui,-apple-system,"Segoe UI",sans-serif}main{max-width:1120px;margin:auto;padding:28px 32px 64px}header{margin-bottom:20px}h1{font-size:clamp(1.5rem,3vw,2.1rem);line-height:1.2;letter-spacing:-.035em;margin:0 0 8px}header p{margin:0}h2{font-size:1.2rem;line-height:1.3;margin:0 0 16px}h3{font-size:1rem;margin:0 0 8px}p{margin:9px 0 16px}.panel{background:white;border:1px solid var(--line);border-radius:10px;padding:24px}.grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:24px}.fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.below{margin-top:24px}.muted,small{color:var(--muted)}.big{font-size:clamp(2rem,5vw,3.6rem);font-weight:750;line-height:1.14;letter-spacing:-.04em;margin:9px 0;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.subresult{font-size:1.2rem;font-weight:700}.formula{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;overflow-wrap:anywhere}label{display:block;font-size:.9rem;font-weight:650}input,select,textarea,button{font:inherit}input,select,textarea{display:block;width:100%;min-width:0;margin-top:6px;padding:10px 12px;border:1px solid #879da8;border-radius:6px;background:white;color:var(--ink)}input,select{min-height:46px}textarea{line-height:1.6;resize:vertical}button{min-height:44px;padding:9px 15px;border:1px solid var(--accent);border-radius:6px;background:var(--accent);color:white;font-weight:650;cursor:pointer}button.secondary{background:white;color:var(--accent)}button:disabled{opacity:.5;cursor:not-allowed}:focus-visible{outline:3px solid #bf6a22;outline-offset:3px}.actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}.check{display:flex;align-items:flex-start;gap:10px;font-weight:500}.check input{width:20px;height:20px;min-height:20px;margin:2px 0 0;flex:none;accent-color:var(--accent)}.badge{display:inline-block;background:var(--soft);color:var(--accent);font-size:.78rem;font-weight:700;padding:4px 9px;border-radius:24px}.error{min-height:24px;color:#a52f29;font-weight:650;margin:8px 0 0}.status{font-size:.88rem;color:var(--muted)}.note{background:#fff3de;border-left:3px solid #b47e3d;padding:12px 16px;color:#63491f}.rule{border-top:1px solid var(--line);margin:18px 0}table{border-collapse:collapse;width:100%;font-size:.92rem}th{font-size:.82rem;color:var(--muted);text-align:left}th,td{border-bottom:1px solid var(--line);padding:10px 8px;vertical-align:top}th:first-child,td:first-child{padding-left:0}details{border-top:1px solid var(--line);padding:16px 0}summary{font-weight:650;cursor:pointer}svg{display:block;width:100%;height:auto}figure{margin:0}figcaption{font-size:.84rem;color:var(--muted);margin-top:10px}pre{white-space:pre-wrap;overflow-wrap:anywhere;font:.86rem/1.6 ui-monospace,Consolas,monospace;background:#eaf0f3;border-radius:6px;padding:18px}ol{padding-left:24px}li{margin:7px 0}[hidden]{display:none!important}@media(max-width:720px){main{padding:22px 20px 44px}.grid{grid-template-columns:1fr;gap:18px}.panel{padding:20px}}@media(max-width:400px){main{padding:18px 16px 36px}.panel{padding:16px}.big{font-size:2.3rem}.fields{gap:12px}th,td{padding:8px 5px}}@media print{body{background:white}main{padding:0;max-width:none}.actions,button{display:none}.panel{break-inside:avoid}details>*{display:block}}:root{--accent:#665979}body{background:#f2f0f5}.video-quote{display:grid;grid-template-columns:1.2fr 1fr;gap:24px;background:#fff;border-top:5px solid #806f96;padding:26px}.format-pair{display:flex;align-items:center;justify-content:center;gap:22px}.format-pair>div{text-align:center;max-width:150px}.format-pair small{display:block;font-size:.78rem;margin-top:9px}.frame{display:grid;place-content:center;background:#e9e1f0;border:2px solid #91809e;color:#5d4b70;font-size:.82rem;font-weight:700;text-align:center}.frame.landscape{width:144px;aspect-ratio:16/9}.frame.portrait{width:81px;aspect-ratio:9/16;margin:auto}.excluded .frame{border-style:dashed;background:#f3f0f6;color:#7b7384}.included .frame{background:#e8ddf0;border-style:solid}.output-lines article{border-left:3px solid #b3a0c2;padding:0 0 0 16px;margin:16px 0}.output-lines p{margin:7px 0}@media(max-width:720px){.video-quote{grid-template-columns:1fr;padding:20px}.format-pair{justify-content:flex-start;gap:28px}.frame.portrait{width:60px}.frame.landscape{width:125px}}</style></head><body><main><header><h1>QV01: landscape edit, vertical change</h1><p>Fictional draft quote: separate capture hours, finished content, edit scope, and export dimensions.</p></header>
<section class="video-quote"><div><span>Known subtotal · before unconfirmed taxes/expenses</span><div class="big" id="subtotal" aria-live="polite">$440.00</div><span id="revision" class="badge">QV01 · original scope · Draft</span><p id="math" class="formula">2 capture hours × $100 + $240 edit</p></div><div class="format-pair"><div><div class="frame landscape">V01<br>1920 × 1080</div><small>Landscape · retained</small></div><div id="verticalFrame"><div class="frame portrait">V02<br>1080 × 1920</div><small id="verticalLabel">Optional change · not included</small></div></div></section>
<section class="panel below"><label class="check" for="vertical"><input type="checkbox" id="vertical">Compare V02: additional vertical reframing and graphics review</label><div class="fields below"><label for="hours">Interview capture hours<input id="hours" value="2" inputmode="decimal"></label><label for="captureRate">Assumed USD per capture hour<input id="captureRate" value="100.00" inputmode="decimal"></label><label for="editFee">V01 fixed edit fee (USD)<input id="editFee" value="240.00" inputmode="decimal"></label><label for="verticalFee">V02 extra edit proposal (USD)<input id="verticalFee" value="80.00" inputmode="decimal"></label></div><div class="actions"><button type="button" id="reset" class="secondary">Restore supplied quote</button></div><p id="error" class="error" role="status"></p></section>
<section class="below panel"><h2>Named output scope</h2><div class="output-lines"><article><b>V01 · original landscape</b><p>One edit, up to 60 seconds of finished content. One 1920 × 1080 export is included in its edit fee.</p></article><article id="verticalScope" hidden><b>V02 · requested vertical version</b><p>1080 × 1920. Requires its own reframing and graphics review; finished duration must be confirmed against V01’s brief. V01 remains included.</p></article></div><p>One consolidated correction round is supplied for this example. Actual reviewer, timing, correction/new-scope boundary, and acceptance criteria: TO CONFIRM.</p><p class="status">Frame diagrams are aspect-ratio illustrations, not actual videos or evidence of a finished edit.</p></section>
<section class="grid below"><div class="panel"><h2>Capture and source-input brief</h2><p>Shot list, interview plan, audio inputs, dates, source asset identities, intended uses, and permission evidence: <b>TO CONFIRM</b>.</p><p>Raw footage, project files, captions, and music rights are excluded unless separately supplied and scoped. Missing permission is not a license.</p></div><div class="panel"><h2>Preserved original and change record</h2><p>Supplied baseline: 2 × $100 + $240 = $440. Proposed V02 extra: +$80 = $520. All rates are illustrative.</p><p id="changeRecord"></p><p>Actual approver / decision / acceptance / delivery: ____________________</p></div></section><details class="below"><summary>Quote calculation limits</summary><p>Capture hours do not change the up-to-60-second V01 content limit. Export dimensions alone do not complete reframing. This unsaved comparison accepts capture hours up to 1000 with two decimal places and USD rates/fees up to 1 million with two places. Capture line amounts round to cents before adding fixed fees. Missing price inputs are not zero. No booking, payment, signature, sending, licensing determination, or completed service is implied.</p></details></main><script>const $=id=>document.getElementById(id),put=(id,s)=>{$(id).textContent=s};
function esc(s){return String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}
function gcd(a,b){a=a<0n?-a:a;b=b<0n?-b:b;while(b){[a,b]=[b,a%b]}return a||1n;}
function R(n,d=1n){n=BigInt(n);d=BigInt(d);if(d===0n)throw Error('Undefined denominator.');if(d<0n){n=-n;d=-d}const g=gcd(n,d);return {n:n/g,d:d/g};}
function mul(a,b){return R(a.n*b.n,a.d*b.d)}function div(a,b){return R(a.n*b.d,a.d*b.n)}function add(a,b){return R(a.n*b.d+b.n*a.d,a.d*b.d)}function sub(a,b){return R(a.n*b.d-b.n*a.d,a.d*b.d)}function cmp(a,b){const x=a.n*b.d-b.n*a.d;return x<0n?-1:x>0n?1:0}
function parse(s,{max=1000000,positive=false,places=6}={}){const t=String(s).trim();if(!t)throw Error('Enter a value; blank is not zero.');const re=new RegExp('^[0-9]+(?:\.[0-9]{1,'+places+'})?$');if(!re.test(t))throw Error('Use digits and a US decimal point, up to '+places+' places; no signs, commas, or exponents.');const v=Number(t);if(!Number.isFinite(v)||v>max||(positive&&v===0))throw Error('Value must be '+(positive?'greater than zero':'nonnegative')+' and at most '+max+'.');const [a,b='']=t.split('.');return R(BigInt(a+b),10n**BigInt(b.length));}
function format(a,places=6){const neg=a.n<0n,n=neg?-a.n:a.n,scale=10n**BigInt(places),v=n*scale,q=v/a.d,rem=v%a.d,k=q+(rem*2n>=a.d?1n:0n);const f=(k%scale).toString().padStart(places,'0').replace(/0+$/,'');return {text:(neg&&k!==0n?'-':'')+(k/scale)+(f?'.'+f:''),approx:rem!==0n};}
function exact(a){let d=a.d;while(d%2n===0n)d/=2n;while(d%5n===0n)d/=5n;if(d!==1n)return a.n+'/'+a.d;let places=0,p=1n;while(p%a.d!==0n&&places<40){p*=10n;places++}return format(a,places).text;}
function display(a,places=6){if(a.n>0n&&cmp(a,R(1n,10n**BigInt(places)))<0)return '< '+format(R(1n,10n**BigInt(places)),places).text;const f=format(a,places);return (f.approx?'≈ ':'')+f.text;}
function listen(ids,fn){ids.forEach(id=>{ $(id).addEventListener('input',fn);$(id).addEventListener('change',fn); });}

function cents(s){return BigInt(format(mul(parse(s,{max:1000000,places:2}),R(100n)),0).text)}function usd(c){return '$'+(Number(c)/100).toLocaleString('en-US',{minimumFractionDigits:2,maximumFractionDigits:2})}
function videoQuote(hours,rate,edit,verticalFee,vertical){const h=parse(hours,{max:1000,places:2}),r=cents(rate),e=cents(edit),v=vertical?cents(verticalFee):0n,capture=BigInt(format(mul(h,R(r)),0).text);return {capture,edit:e,extra:vertical?v:0n,total:capture+e+(vertical?v:0n),hours:h};}
function update(){const vertical=$('vertical').checked;$('verticalScope').hidden=!vertical;$('verticalFrame').setAttribute('class',vertical?'included':'excluded');put('verticalLabel',vertical?'Proposed extra edit · not approved':'Optional change · not included');try{const q=videoQuote($('hours').value,$('captureRate').value,$('editFee').value,$('verticalFee').value,vertical);put('subtotal',usd(q.total));put('revision',vertical?'QV01 · V02 change scenario · Draft':'QV01 · original-scope scenario · Draft');put('math',exact(q.hours)+' capture hours → '+usd(q.capture)+' + '+usd(q.edit)+' V01 edit'+(vertical?' + '+usd(q.extra)+' V02 edit':''));put('changeRecord',vertical?'Proposed V02 extra '+usd(q.extra)+'. Capture remains '+exact(q.hours)+' hours and V01’s content limit stays up to 60 seconds. No approval or completed edit is recorded.':'V01 retained. No vertical edit is included in the current scenario.');put('error','');}catch(e){put('subtotal','NOT CALCULABLE');put('math','');put('changeRecord','No current price comparison; fix missing or invalid inputs.');put('error',e.message);}}
listen(['hours','captureRate','editFee','verticalFee','vertical'],update);$('reset').addEventListener('click',()=>{$('hours').value='2';$('captureRate').value='100.00';$('editFee').value='240.00';$('verticalFee').value='80.00';$('vertical').checked=false;update()});globalThis.Tool={videoQuote,update};update();</script></body></html>