Feet & inches workbench

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>Feet & inches workbench</title><style>*{box-sizing:border-box}html{color-scheme:light}body{margin:0;background:var(--bg,#f3f4f5);color:var(--ink,#192838);font:16px/1.5 system-ui,-apple-system,Segoe UI,sans-serif}main{max-width:1040px;margin:auto;padding:28px 28px 48px}header{margin-bottom:20px}h1{font-size:clamp(25px,4vw,36px);line-height:1.15;letter-spacing:-.035em;margin:6px 0 9px}h2{font-size:21px;line-height:1.25;margin:0 0 16px}h3{font-size:17px;margin:0 0 10px}p{margin:8px 0 16px}.eyebrow{font-size:12px;font-weight:750;text-transform:uppercase;letter-spacing:.12em;color:var(--accent,#275e86)}.subtle,small{color:#536170}.panel{padding:24px;background:white;border:1px solid var(--line,#d5dce2);border-radius:12px;margin:18px 0}.result{background:var(--result,#132f47);color:white;padding:26px;border-radius:14px;margin:18px 0}.result .subtle,.result small{color:#d7e3ed}.big{font-size:clamp(32px,6vw,56px);font-weight:750;line-height:1.15;letter-spacing:-.035em;margin:8px 0 14px;overflow-wrap:anywhere}.mono,pre,code{font-family:ui-monospace,Consolas,monospace;font-variant-numeric:tabular-nums}.mono{overflow-wrap:anywhere}pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px;line-height:1.7;margin:0}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.triple{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.fields{display:flex;gap:16px;flex-wrap:wrap;align-items:end}.fields>label{flex:1;min-width:130px}label{display:block;font-size:14px;font-weight:650}input,select,textarea{display:block;width:100%;font:inherit;font-size:16px;color:inherit;background:white;border:1px solid #a9b4bf;border-radius:6px;padding:11px 12px;margin-top:6px;min-width:0}input[type=checkbox]{display:inline;width:auto;margin:0 9px 0 0;accent-color:var(--accent,#275e86)}textarea{min-height:100px;resize:vertical}button{font:inherit;font-weight:650;padding:10px 17px;border:1px solid var(--accent,#275e86);background:var(--accent,#275e86);color:white;border-radius:6px;cursor:pointer;min-height:44px}button.secondary{background:white;color:var(--accent,#275e86)}button:disabled{opacity:.5;cursor:default}button:hover{filter:brightness(.94)}:focus-visible{outline:3px solid #e9a733;outline-offset:3px}.actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}.error{color:#a32325;font-weight:650;min-height:0}.error:not(:empty){padding:12px;border-left:4px solid #ae3237;background:#fff2f0;margin:14px 0}[hidden]{display:none!important}fieldset{border:1px solid #ccd4da;border-radius:8px;padding:18px;margin:0;min-width:0}legend{padding:0 7px;font-weight:750}table{width:100%;border-collapse:collapse;font-size:14px;table-layout:fixed}th{text-align:left;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:#536170}td,th{padding:12px 9px;border-bottom:1px solid #d9dfe4;vertical-align:top;overflow-wrap:anywhere}th:first-child,td:first-child{padding-left:0}dl{margin:0}dl>div{padding:10px 0;border-bottom:1px solid #d9dfe4}dt{font-size:13px;color:#536170}dd{margin:4px 0 0;font-weight:650}details{margin:20px 0;padding:18px 0;border-top:1px solid #cbd2d8}summary{cursor:pointer;font-weight:700}details p{margin-top:16px}a{color:var(--accent,#275e86)}.tag{display:inline-block;font-size:12px;font-weight:750;letter-spacing:.03em;border:1px solid currentColor;border-radius:5px;padding:4px 8px}.rule{border-top:1px solid #d9dfe4;padding-top:20px}.line{height:30px;border-bottom:1px solid #aab4be}.split-stat{display:flex;justify-content:space-between;gap:20px;align-items:baseline;flex-wrap:wrap}.result h2{color:white}.result table td,.result table th{border-color:#ffffff35;color:white}.result .eyebrow{color:#d7e3ed}.readout{padding:16px;background:#f0f4f6;border-radius:6px;margin-top:14px}.empty{padding:22px;border:1px dashed #a6b0ba;border-radius:8px;color:#536170;margin:18px 0}footer{font-size:13px;color:#536170;margin-top:24px}@media(max-width:720px){main{padding:20px}.panel,.result{padding:20px}.grid{gap:14px}.triple{gap:10px}}@media(max-width:540px){main{padding:16px}.grid{grid-template-columns:1fr}.panel,.result{padding:18px;border-radius:9px}.fields{gap:12px}.fields>label{min-width:100px}h1{font-size:27px}th,td{padding:10px 5px;font-size:13px}.triple{grid-template-columns:1fr}.big{font-size:38px}}.result{background-image:repeating-linear-gradient(90deg,transparent 0,transparent 23px,#ffffff0b 23px,#ffffff0b 24px);border-bottom:5px solid #c48a47}fieldset .fields{display:grid;grid-template-columns:1fr}.result .big{font-family:Georgia,serif}</style></head><body style="--bg:#f4f0e9;--accent:#845328;--result:#3e352e"><main><header><div class="eyebrow">Working example</div><h1>Feet & inches workbench</h1><p class="subtle">Carry feet, inches, and eighths using exact integer arithmetic.</p></header><section id="result" class="result" aria-live="polite"><div class="eyebrow" id="opLabel">Addition · exact compound length</div><div class="big" id="length"></div><p class="mono" id="tickline"></p></section><p id="error" class="error" role="alert"></p><p id="empty" class="empty" hidden>Inputs changed. Calculate to see the current result.</p><form id="form" class="panel" novalidate><div class="grid"><fieldset><legend>Length A</legend><div class="fields"><label for="af">Whole feet · 0–100<input id="af" value="2" inputmode="decimal" autocomplete="off"></label><label for="ai">Whole inches · 0–11<input id="ai" value="10" inputmode="decimal" autocomplete="off"></label><label for="ae">Eighths numerator · 0–7<input id="ae" value="3" inputmode="decimal" autocomplete="off"></label></div><small>Fraction denominator is fixed at 8.</small></fieldset><fieldset><legend>Length B</legend><div class="fields"><label for="bf">Whole feet · 0–100<input id="bf" value="1" inputmode="decimal" autocomplete="off"></label><label for="bi">Whole inches · 0–11<input id="bi" value="4" inputmode="decimal" autocomplete="off"></label><label for="be">Eighths numerator · 0–7<input id="be" value="7" inputmode="decimal" autocomplete="off"></label></div><small>Fraction denominator is fixed at 8.</small></fieldset></div><label for="operation" style="margin-top:18px">Operation<select id="operation"><option value="add">Addition · A + B</option><option value="ab">Subtract · A − B</option><option value="ba">Subtract · B − A</option></select></label><div class="actions"><button>Compute</button><button type="button" class="secondary" id="reset">Reset operands</button></div></form><section class="panel"><h2>Calculation record</h2><pre id="trace"></pre></section><details><summary>Input rules and measurement limits</summary><p>All six fields require whole numbers, including explicit zeros. Feet: 0–100; inches: 0–11; eighth numerator: 0–7. Enter 3 in the eighth field for 3/8 inch. Out-of-range inches are rejected rather than silently carried.</p><p>One foot is 96 eighth-inch ticks. Fractions are reduced only after arithmetic; a negative difference uses one sign around the whole length. Arithmetic on supplied numbers does not establish measurement accuracy, fit tolerance, or cutting allowance.</p></details><footer>Local review copy · No data is sent or saved.</footer></main><script>const $=id=>document.getElementById(id);const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));function round(n,d){return (2n*n+d)/(2n*d)}function dec(n,d,p=6){let x=round(n*10n**BigInt(p),d).toString().padStart(p+1,'0');return p?x.slice(0,-p)+'.'+x.slice(-p):x}function exact(n,d){let a=n/d,r=n%d,s='';for(let i=0;r&&i<36;i++){r*=10n;s+=r/d;r%=d}return a+(s?'.'+s:'')+(r?'…':'')}function num(s,name,max=1000000000,places=9,zero=false){if(!new RegExp('^[0-9]+(?:[.][0-9]{1,'+places+'})?$').test(s)||s.length>35)throw Error(name+': use a '+(zero?'nonnegative':'positive')+' dot-decimal number.');let [a,b='']=s.split('.'),d=10n**BigInt(b.length),n=BigInt(a+b);if((zero?n<0n:n<=0n)||n>BigInt(max)*d)throw Error(name+': value outside the supported range.');return {n,d,v:Number(n)/Number(d)}}function clear(){ $('result').hidden=true;$('trace').textContent='';$('empty').hidden=false;$('error').textContent='';}function reveal(){ $('result').hidden=false;$('empty').hidden=true;$('error').textContent='';}function error(e){clear();$('error').textContent=e.message;}function bindForm(run){$('form').addEventListener('submit',e=>{e.preventDefault();run()});$('form').addEventListener('input',clear);$('form').addEventListener('change',clear);}

function component(s,max,name){if(!/^[0-9]+$/.test(s)||s.length>6||Number(s)>max)throw Error(name+': enter a whole number from 0 to '+max+'.');return Number(s)}function ticks(v,name){return component(v[0],100,name+' feet')*96+component(v[1],11,name+' inches')*8+component(v[2],7,name+' eighths')}function gcd(a,b){return b?gcd(b,a%b):a}function compound(t){const n=Math.abs(t),feet=Math.floor(n/96),inches=Math.floor(n%96/8),e=n%8,g=gcd(e,8),s=feet+' ft '+inches+(e?' '+e/g+'/'+8/g:'')+' in';return t<0?'−('+s+')':s}function lengths(a,b,op){const A=ticks(a,'A'),B=ticks(b,'B');if(!['add','ab','ba'].includes(op))throw Error('Choose a supported operation.');const total=op==='add'?A+B:op==='ab'?A-B:B-A;return {A,B,total,answer:compound(total)}}
function run(){try{const a=['af','ai','ae'].map(x=>$(x).value),b=['bf','bi','be'].map(x=>$(x).value),op=$('operation').value,r=lengths(a,b,op);reveal();$('length').textContent=r.answer;$('opLabel').textContent=$('operation').options[$('operation').selectedIndex].text+' · exact result';$('tickline').textContent=(op==='ba'?r.B:r.A)+(op==='add'?' + ':' − ')+(op==='ba'?r.A:r.B)+' = '+r.total+' ticks';const n=Math.abs(r.total),f=Math.floor(n/96),i=Math.floor(n%96/8),e=n%8;$('trace').textContent='A: 96 × '+a[0]+' + 8 × '+a[1]+' + '+a[2]+' = '+r.A+' ticks\nB: 96 × '+b[0]+' + 8 × '+b[1]+' + '+b[2]+' = '+r.B+' ticks\n\n'+$('tickline').textContent+'\nMagnitude: '+n+' = '+f+' × 96 + '+i+' × 8 + '+e+'\n'+(e?'Remaining fraction '+e+'/8 reduced in the result.':'No fractional remainder.')+'\nExact result: '+r.answer;}catch(e){error(e)}}bindForm(run);$('reset').onclick=()=>{['af','ai','ae','bf','bi','be'].forEach((x,i)=>$(x).value=[2,10,3,1,4,7][i]);$('operation').value='add';clear()};run();</script>
<script>
// Local calculation controls: no native form submission or sandbox permissions required.
(()=>{const form=document.getElementById('form');if(!form)throw Error('Calculation form missing');const dispatch=()=>form.dispatchEvent(new Event('submit',{bubbles:true,cancelable:true}));const buttons=[...form.querySelectorAll('button')].filter(button=>button.type==='submit');if(buttons.length!==1)throw Error('Expected one calculation control');for(const button of buttons){button.type='button';button.addEventListener('click',dispatch);}form.addEventListener('keydown',event=>{if(event.key==='Enter'&&!event.isComposing&&['INPUT','SELECT'].includes(event.target.tagName)){event.preventDefault();dispatch();}});})();
</script>
</body></html>