From 8aedc95043c69955f2e23e51a555ff2fb177a514 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 12 Jul 2026 00:39:50 -0500 Subject: feat(gallery): add R17 round CRT scope The round-tube scope after a 1950s bench oscilloscope (reference filed in the catalogue's working directory): pale phosphor face in a screwed porthole bezel, dark graticule, and a bright live trace with a soft glow underlay. The kit's rectangular N11 scope is the modern face; this is the pre-60s one, light screen instead of dark. I verified it in headless Chrome: the trace animates and Vpp tracks the envelope, no console exceptions. --- docs/prototypes/panel-widget-gallery.html | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'docs') diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index 04cd0cf..be79a0a 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -790,6 +790,9 @@ card(M,'R09','Black-face aviation gauge', card(M,'R13','Edgewise strip meter', ``, 'a needle on a vertical scale. The parchment strip reads attenuation down a compressed log scale; the bar rides its edge. Drag up/down; readout shows dB. After a channel-strip gain-reduction meter.'); +card(M,'R17','Round CRT scope', + ``, + 'the round-tube scope. Pale phosphor face in a screwed porthole bezel, dark graticule, a bright live trace. Runs live; readout shows Vpp. After a 1950s bench oscilloscope.'); /* ============ INDICATORS & READOUTS ============ */ const I=$('indicators'); @@ -1599,6 +1602,35 @@ function kpPress(k){ if(kpBuf.length<6){kpBuf+=k;kpRender();setRd('R16',kpBuf);}} kpRender();setRd('R16','enter a code'); +/* R17 round CRT scope: pale phosphor face, live trace */ +let rcrtPh=0,rcrtTrace=null; +(function(){const s=$('rcrt'),cx=55,cy=52; + const defs=svgEl(s,'defs',{}); + const ph=svgEl(defs,'radialGradient',{id:'rcrtFace',cx:'50%',cy:'44%',r:'70%'}); + svgEl(ph,'stop',{offset:'0','stop-color':'#b9d8c0'}); + svgEl(ph,'stop',{offset:'1','stop-color':'#8bb296'}); + const clip=svgEl(defs,'clipPath',{id:'rcrtClip'}); + svgEl(clip,'circle',{cx,cy,r:38}); + svgEl(s,'circle',{cx,cy,r:48,fill:'#141110',stroke:'#060505','stroke-width':2}); + for(let k=0;k<4;k++){const [x,y]=polar(cx,cy,43,45+k*90); + svgEl(s,'circle',{cx:x,cy:y,r:2.6,fill:'url(#sfScrew)',stroke:'#0a0908','stroke-width':.5});} + svgEl(s,'circle',{cx,cy,r:38,fill:'url(#rcrtFace)'}); + const g=svgEl(s,'g',{'clip-path':'url(#rcrtClip)'}); + for(let i=-4;i<=4;i++){ + svgEl(g,'line',{x1:cx+i*9,y1:cy-38,x2:cx+i*9,y2:cy+38,stroke:'#3d5c46','stroke-width':i===0?.9:.5,opacity:.8}); + svgEl(g,'line',{x1:cx-38,y1:cy+i*9,x2:cx+38,y2:cy+i*9,stroke:'#3d5c46','stroke-width':i===0?.9:.5,opacity:.8});} + svgEl(g,'polyline',{id:'rcrtGlow',points:'',fill:'none',stroke:'#eef7ee','stroke-width':3,opacity:.35,filter:'url(#avGlow)'}); + rcrtTrace=svgEl(g,'polyline',{points:'',fill:'none',stroke:'#f4fcf4','stroke-width':1.3}); + svgEl(s,'ellipse',{cx:cx-10,cy:cy-16,rx:20,ry:10,fill:'rgba(255,255,255,.10)',transform:`rotate(-20,${cx-10},${cy-16})`});})(); +function tickRcrt(){rcrtPh+=0.12;const amp=8+3*Math.sin(rcrtPh*0.35);let pts=''; + for(let x=-38;x<=38;x+=2){const y=Math.sin(x*0.55+rcrtPh*2.5)*amp; + pts+=`${55+x},${(52+y).toFixed(1)} `;} + rcrtTrace.setAttribute('points',pts.trim()); + document.getElementById('rcrtGlow').setAttribute('points',pts.trim()); + setRd('R17','Vpp '+Math.round(amp*2*4.5));} +tickRcrt(); +if(!matchMedia('(prefers-reduced-motion: reduce)').matches)setInterval(tickRcrt,80); + /* ============ LIVE SIGNAL LOOPS ============ */ buildBars($('vuL'),16);buildBars($('vuR'),16);$('mini').innerHTML=''; (function(){const eq=$('eq');for(let b=0;b<11;b++){const band=document.createElement('span');band.className='band'; -- cgit v1.2.3