One letter at every crossing
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>One letter at every crossing</title><style>
:root{color-scheme:light;--accent:#67512a;--wash:#f5efd9;--ink:#202d3b;--paper:#fffdf9}*{box-sizing:border-box}body{margin:0;color:var(--ink);background:#eeeae2;font:17px/1.65 system-ui,-apple-system,"Segoe UI",sans-serif}main{max-width:980px;margin:auto;padding:28px 24px 40px}header{border-top:6px solid var(--accent);padding:20px 0 24px}.kicker{color:var(--accent);font-weight:750;letter-spacing:.06em;margin:0 0 8px}h1{font:700 clamp(30px,5vw,46px)/1.15 Georgia,serif;margin:0 0 14px;max-width:780px}h2{font-size:23px;line-height:1.3;margin:0 0 14px}h3{font-size:19px;margin:12px 0 8px}p{margin:0 0 16px}button,input,textarea,select{font:inherit}button{background:white;border:1px solid #87949b;color:var(--ink);border-radius:8px;padding:11px 16px;min-height:48px;cursor:pointer;font-weight:650}button:hover{background:var(--wash)}button[aria-pressed=true],button.primary{background:var(--accent);color:white;border-color:var(--accent)}:focus-visible{outline:3px solid #b45a1e;outline-offset:3px}label{display:block;font-weight:650;margin:14px 0 6px}input:not([type=checkbox]):not([type=radio]),textarea,select{display:block;width:100%;min-width:0;max-width:100%;border:1px solid #80909b;border-radius:7px;padding:11px;background:white;color:var(--ink)}input[type=checkbox],input[type=radio]{width:21px;height:21px;accent-color:var(--accent)}textarea{resize:vertical}.panel{background:var(--paper);border:1px solid #ccd2d1;border-radius:12px;padding:24px;margin-bottom:20px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.two>.panel{margin:0}.two{margin-bottom:20px}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0}.result{padding:18px;background:var(--wash);border-left:5px solid var(--accent);margin-top:18px;white-space:pre-line;overflow-wrap:anywhere}.note{color:#465565;font-size:16px}.strip{padding:18px;background:var(--wash);border-radius:8px;margin-bottom:18px}table{border-collapse:collapse;width:100%;font-size:16px;table-layout:fixed}th,td{text-align:left;padding:10px 8px;border-bottom:1px solid #cbd0d1;overflow-wrap:anywhere;vertical-align:top}th{background:var(--wash)}ol,ul{padding-left:24px}li+li{margin-top:8px}pre{font-size:16px;white-space:pre-wrap;overflow-wrap:anywhere}code{font-size:16px}.grid{display:grid;gap:5px;max-width:440px}.grid button{padding:5px;min-width:0}.grid input{padding:5px!important;text-align:center;font-weight:750}blockquote{font:500 26px/1.5 Georgia,serif;margin:16px 0}footer{font-size:16px;color:#465565;margin-top:22px}[hidden]{display:none!important}svg{display:block;max-width:100%;height:auto}mark{background:#e0efad;color:var(--ink)}@media(max-width:560px){main{padding:18px 12px 28px}.panel{padding:20px 16px}.two{grid-template-columns:minmax(0,1fr)}h1{font-size:32px}.actions button{flex:1 1 135px}th,td{padding:8px 5px}.grid button{min-height:40px}blockquote{font-size:24px}}
</style></head><body><main><header><p class="kicker">CROSSWORD STUDIO · THREE ORIGINAL CLUES</p><h1>One letter at every crossing</h1><p>Fill the nine white cells. Across and Down share the same input at every crossing.</p></header><div class="two"><section class="panel"><h2>Original clue grid</h2><div class="grid" style="grid-template-columns:repeat(6,minmax(0,1fr))"><input id="x00" type="text" aria-label="Row 1 column 1" autocomplete="off" spellcheck="false"><input id="x01" type="text" aria-label="Row 1 column 2" autocomplete="off" spellcheck="false"><input id="x02" type="text" aria-label="Row 1 column 3" autocomplete="off" spellcheck="false"><input id="x03" type="text" aria-label="Row 1 column 4" autocomplete="off" spellcheck="false"><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><input id="x12" type="text" aria-label="Row 2 column 3" autocomplete="off" spellcheck="false"><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><span aria-label="Blocked cell" style="background:#24313d;min-height:44px;border-radius:3px"></span><input id="x22" type="text" aria-label="Row 3 column 3" autocomplete="off" spellcheck="false"><input id="x23" type="text" aria-label="Row 3 column 4" autocomplete="off" spellcheck="false"><input id="x24" type="text" aria-label="Row 3 column 5" autocomplete="off" spellcheck="false"><input id="x25" type="text" aria-label="Row 3 column 6" autocomplete="off" spellcheck="false"></div><div class="actions"><button type="button" id="prev">Previous cell</button><button type="button" id="next">Next cell</button></div><div id="active" class="result" role="status" aria-live="polite"></div></section><section class="panel"><h2>Clues</h2><button type="button" id="clue0">1 Across · Bright point in the night sky</button><button type="button" id="clue1">2 Down · Creative work such as drawing</button><button type="button" id="clue2">3 Across · Woody plant with a trunk</button><div id="previews" class="result" role="status" aria-live="polite"></div></section></div><section class="panel"><h2>Check the shared values</h2><p>One ASCII letter per white cell. Lowercase is normalized. Invalid completed edits are rejected; composition is checked on completion.</p><div class="actions"><button type="button" id="check">Check puzzle</button><button type="button" id="reset">Reset cells</button></div><div id="feedback" class="result" role="status" aria-live="polite">Not checked.</div></section><footer>Original fictional example. Changes remain in this open page and are not saved.</footer><noscript>JavaScript is required for the local controls. The accompanying article contains worked examples.</noscript></main><script>
(()=>{'use strict';const $=id=>document.getElementById(id);
const keys=['00','01','02','03','12','22','23','24','25'],answers=['STAR','ART','TREE'],paths=[['00','01','02','03'],['02','12','22'],['22','23','24','25']],values=Object.fromEntries(keys.map(k=>[k,'']));let active=0,cell='00',composing=false;function render(){$('previews').textContent=paths.map((p,i)=>(i===0?'1 Across':i===1?'2 Down':'3 Across')+': '+p.map(k=>values[k]||'_').join('')).join(' / ');$('active').textContent='Active clue '+(active+1)+'; cell row '+(Number(cell[0])+1)+' column '+(Number(cell[1])+1);}$('feedback').textContent='Not checked.';function accept(k){const n=$('x'+k),v=n.value;if(!/^[a-zA-Z]?$/.test(v)){n.value=values[k];$('feedback').textContent='Use one ASCII letter or erase the cell; completed edit rejected.';return;}values[k]=v.toUpperCase();n.value=values[k];$('feedback').textContent='Values changed. Check again.';render();}keys.forEach(k=>{const n=$('x'+k);n.addEventListener('input',e=>{if(!composing&&!e.isComposing)accept(k);});n.addEventListener('compositionstart',()=>{composing=true;});n.addEventListener('compositionend',()=>{composing=false;accept(k);});n.addEventListener('focus',()=>{cell=k;render();});n.addEventListener('keydown',e=>{if(composing||e.isComposing)return;const dirs={ArrowLeft:[0,-1],ArrowRight:[0,1],ArrowUp:[-1,0],ArrowDown:[1,0]};if(!dirs[e.key])return;e.preventDefault();let r=Number(k[0]),c=Number(k[1]);const d=dirs[e.key];while(true){r+=d[0];c+=d[1];if(r<0||r>2||c<0||c>5)return;const target=String(r)+c;if(keys.includes(target)){$('x'+target).focus();return;}}});});[0,1,2].forEach(i=>$('clue'+i).addEventListener('click',()=>{active=i;cell=paths[i][0];$('x'+cell).focus();render();}));function move(d){const p=paths[active],i=Math.max(0,p.indexOf(cell));cell=p[Math.max(0,Math.min(p.length-1,i+d))];$('x'+cell).focus();render();}$('prev').addEventListener('click',()=>move(-1));$('next').addEventListener('click',()=>move(1));$('check').addEventListener('click',()=>{if(composing){$('feedback').textContent='Finish the current composition before checking.';return;}const states=paths.map((p,i)=>{const v=p.map(k=>values[k]).join('');return p.some(k=>!values[k])?'incomplete':v===answers[i]?'correct':'wrong';});$('feedback').textContent=states.map((s,i)=>'Clue '+(i+1)+': '+s).join(' / ')+(states.every(s=>s==='correct')?' / Complete: 3 clues, 9 shared cells.':'');});$('reset').addEventListener('click',()=>{keys.forEach(k=>{values[k]='';$('x'+k).value='';});active=0;cell='00';composing=false;$('feedback').textContent='Not checked.';$('x00').focus();render();});render();
})();
</script></body></html>