Rotate the rays, keep the opening
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>Rotate the rays, keep the opening</title><style>
:root{color-scheme:light;--accent:#40578b;--wash:#e9edf9;--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">GEOMETRY BENCH · ANGLE TRANSFORMATIONS</p><h1>Rotate the rays, keep the opening</h1><p>Select a figure. Compare the smaller opening while the whole drawing rotates or its visible segments shorten.</p></header><div class="actions"><button type="button" id="g1">G1</button><button type="button" id="g2">G2</button><button type="button" id="g3">G3</button><button type="button" id="g4">G4</button><button type="button" id="g5">G5</button></div><div class="two"><section class="panel"><h2>Ray-opening model</h2><svg id="drawing" viewBox="0 0 300 280" role="img" aria-label="Two rays and the intended opening"></svg><div id="directions" class="result" role="status" aria-live="polite"></div></section><section class="panel"><h2>Change the display</h2><label for="rotation">Rotate both rays (degrees0–360)</label><input id="rotation" type="text" value="0"><label for="length">Displayed segment length (40–110)</label><input id="length" type="text" value="90"><div class="actions"><button type="button" id="apply">Apply display</button></div><div id="displayState" class="result" role="status" aria-live="polite"></div></section></div><section class="panel"><h2>Measure and classify</h2><label for="degrees">Your opening in degrees1–180</label><input id="degrees" type="text" value=""><label for="category">Category: acute / right / obtuse / straight</label><input id="category" type="text" value=""><label for="reason">Explain the baseline and what changed</label><textarea id="reason" rows="4"></textarea><div class="actions"><button type="button" id="check">Check declared figure</button><button type="button" id="reveal">Reveal current key</button><button type="button" id="reset">Clear answers</button></div><div id="feedback" class="result" role="status" aria-live="polite">Choose a figure and measure.</div><div id="key" class="strip" hidden></div></section><footer>Measure from the selected starting ray. Rotation and displayed segment length preserve the opening.</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 figures=[[50,0,90,'acute'],[50,70,55,'acute'],[90,0,90,'right'],[130,0,90,'obtuse'],[180,0,90,'straight']];let i=0,displayValid=false;function clear(){['degrees','category','reason'].forEach(id=>$(id).value='');$('key').hidden=true;$('feedback').textContent='Measure from the selected starting ray.';}function draw(){displayValid=false;const r=Number($('rotation').value),len=Number($('length').value);if(!$('rotation').value.trim()||!$('length').value.trim()||!Number.isFinite(r)||r<0||r>360||!Number.isFinite(len)||len<40||len>110){$('displayState').textContent='Use rotation0–360 and length40–110.';return;}displayValid=true;const a=figures[i][0],p=(d,l)=>[150+l*Math.cos(d*Math.PI/180),140-l*Math.sin(d*Math.PI/180)],p1=p(r,len),p2=p(r+a,len),q1=p(r,35),q2=p(r+a,35);$('drawing').innerHTML='<path d="M'+p1.join(' ')+' L150 140 L'+p2.join(' ')+'" fill="none" stroke="#40578b" stroke-width="4"/><path d="M'+q1.join(' ')+' A35 35 0 0 0 '+q2.join(' ')+'" fill="none" stroke="#a05f28" stroke-width="3"/><circle cx="150" cy="140" r="5" fill="#202d3b"/><text x="150" y="165" text-anchor="middle">Vertex</text>';$('directions').textContent='G'+(i+1)+' · Starting ray page direction '+r+'°; second ray '+(r+a)+'°.';$('displayState').textContent='Both rays transformed together. Length '+len+' logical pixels.';clear();}figures.forEach((g,n)=>$('g'+(n+1)).addEventListener('click',()=>{i=n;$('rotation').value=String(g[1]);$('length').value=String(g[2]);draw();}));$('apply').addEventListener('click',draw);['rotation','length'].forEach(id=>$(id).addEventListener('input',()=>{displayValid=false;$('feedback').textContent='Display input changed. Apply it before measuring.';$('drawing').replaceChildren();clear();}));['degrees','category','reason'].forEach(id=>$(id).addEventListener('input',()=>{$('feedback').textContent='Answer changed. Check again.';}));$('check').addEventListener('click',()=>{if(!displayValid){$('feedback').textContent='Apply a valid display before checking an angle.';return;}const d=$('degrees').value.trim(),cat=$('category').value.trim().toLowerCase();if(!/^\d+(?:\.\d+)?$/.test(d)||Number(d)<=0||Number(d)>180||!['acute','right','obtuse','straight'].includes(cat)||!$('reason').value.trim()){$('feedback').textContent='Supply a positive degree1–180, a known category and a reason.';return;}const n=Number(Number(d)===figures[i][0])+Number(cat===figures[i][3]);$('feedback').textContent=n+' of 2 declared answers correct. Teacher reviews measurement and reasoning.';});$('reveal').addEventListener('click',()=>{$('key').hidden=!$('key').hidden;$('key').textContent='G'+(i+1)+': '+figures[i][0]+'°; '+figures[i][3]+'. Whole-figure rotation and segment length do not change this opening.';});$('reset').addEventListener('click',clear);draw();
})();
</script></body></html>