From 4a6aeaca5f493b6aba8fa9749161013ad64a9d4f Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 12 Jul 2026 00:17:40 -0500 Subject: feat(gallery): add R08-R11 from hi-fi and cockpit references Four more reference-batch widgets as inline SVG, from pasted hardware references (a hi-fi chrome level window, aviation instrument clusters, and a vintage altimeter): - R08 chrome MIN/MAX indicator: polished ring, brushed metal dome, cog hub, dark pointer sweeping MIN to MAX. - R09 black-face aviation gauge: amber ticks and numerals on black, painted green/amber/red zone arcs per the airspeed-indicator scheme, glowing amber needle. - R10 data matrix readout: a lit amber data block with labeled fields; click cycles SYS/NET/TIME pages, and the TIME page runs off the real clock. - R11 warning flag window: a striped barber-pole slides into the window when tripped, the mechanical alarm idiom as distinct from a lamp. I verified all four in headless Chrome: both meters track drags, the pages cycle, the flag trips and clears, no console exceptions. The gallery is at 64 cards. --- docs/prototypes/panel-widget-gallery.html | 128 ++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index fac4762..2ce0faf 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -769,6 +769,12 @@ card(M,'R01','Moving-coil VU meter', card(M,'R07','Round panel meter', ``, 'the porthole lab meter. Cream dial in a round black bezel, printed dB arc, black needle. Drag up/down to drive it; readout shows dB. After a modulator front meter.'); +card(M,'R08','Chrome MIN/MAX indicator', + ``, + 'the hi-fi trim window. Polished chrome ring, brushed dome, a dark pointer sweeping MIN to MAX over the metal. Drag up/down; readout shows the position. After a hi-fi amplifier level window.'); +card(M,'R09','Black-face aviation gauge', + ``, + 'amber on black, zone-marked. The cockpit round: amber ticks and numerals on a black face, painted caution and limit sectors, amber needle. Drag up/down; readout tracks. After a flight-instrument cluster.'); /* ============ INDICATORS & READOUTS ============ */ const I=$('indicators'); @@ -825,6 +831,12 @@ card(I,'N27','Frequency-dial scale', card(I,'N28','Patch-bay jack field', `
`, 'routing shown as patches. A grid of jacks with cables between connected pairs. Click one jack then another to add/remove a cable.'); +card(I,'R10','Data matrix readout', + ``, + 'a page of amber fields. The console data block — several labeled values on one lit matrix. Click to cycle pages; readout names the page. After a cockpit data readout.'); +card(I,'R11','Warning flag window', + ``, + 'the mechanical alarm flag. A striped barber-pole slides into a window when the condition trips — not a lamp, a flag. Click to trip and clear it. After the VIB flag on an altimeter.'); /* ============ CONTROL WIRING ============ */ /* 01 toggle */ @@ -1271,6 +1283,122 @@ function setRnd(v){const t=Math.max(0,Math.min(1,v/100));rndT=t; const db=vuDb(t);setRd('R07',(db>0?'+':'')+db.toFixed(1)+' dB');} dragDelta($('rndm'),()=>rndT*100,setRnd,{min:0,max:100});setRnd(50); +/* R08 chrome MIN/MAX indicator */ +let chrV=50,chrPtr=null; +(function(){const s=$('chrmm'),cx=55,cy=58; + const defs=svgEl(s,'defs',{}); + const ring=svgEl(defs,'linearGradient',{id:'chrRing',x1:0,y1:0,x2:0,y2:1}); + svgEl(ring,'stop',{offset:'0','stop-color':'#eceef0'}); + svgEl(ring,'stop',{offset:'.5','stop-color':'#9aa0a8'}); + svgEl(ring,'stop',{offset:'1','stop-color':'#54585e'}); + const dome=svgEl(defs,'radialGradient',{id:'chrDome',cx:'48%',cy:'20%',r:'85%'}); + svgEl(dome,'stop',{offset:'0','stop-color':'#e6e8ec'}); + svgEl(dome,'stop',{offset:'1','stop-color':'#82878f'}); + svgEl(s,'circle',{cx,cy:54,r:47,fill:'url(#chrRing)'}); + svgEl(s,'circle',{cx,cy:54,r:40,fill:'#101214',stroke:'#2c2f33','stroke-width':1}); + svgEl(s,'path',{d:`M 21 60 A 34 34 0 0 1 89 60 Z`,fill:'url(#chrDome)',stroke:'#55595f','stroke-width':.5}); + for(const r of [14,22,30]) + svgEl(s,'path',{d:`M ${cx-r} 60 A ${r} ${r} 0 0 1 ${cx+r} 60`,fill:'none',stroke:'rgba(255,255,255,.13)','stroke-width':.7}); + chrPtr=svgEl(s,'line',{x1:cx,y1:cy-10,x2:cx,y2:cy-31,stroke:'#17191b','stroke-width':2.2,'stroke-linecap':'round'}); + svgEl(s,'circle',{cx,cy,r:6,fill:'#23262a'}); + for(let k=0;k<8;k++){const [x,y]=polar(cx,cy,6,k*45); + svgEl(s,'circle',{cx:x,cy:y,r:1.3,fill:'#23262a'});} + svgEl(s,'circle',{cx,cy,r:1.6,fill:'#0c0d0e'}); + svgEl(s,'text',{x:24,y:66,'text-anchor':'middle','font-size':6,'letter-spacing':'.05em', + 'font-family':'var(--mono)',fill:'#d7dade'}).textContent='MIN'; + svgEl(s,'text',{x:86,y:66,'text-anchor':'middle','font-size':6,'letter-spacing':'.05em', + 'font-family':'var(--mono)',fill:'#d7dade'}).textContent='MAX'; + svgEl(s,'text',{x:cx,y:84,'text-anchor':'middle','font-size':7,'font-style':'italic', + 'font-family':'var(--mono)',fill:'#787c82'}).textContent='dupre.'; + svgEl(s,'ellipse',{cx:47,cy:34,rx:22,ry:9,fill:'rgba(255,255,255,.10)',transform:'rotate(-16,47,34)'});})(); +function setChr(v){chrV=Math.max(0,Math.min(100,v)); + chrPtr.setAttribute('transform',`rotate(${-55+chrV/100*110},55,58)`); + setRd('R08',chrV<=2?'MIN':chrV>=98?'MAX':Math.round(chrV)+'%');} +dragDelta($('chrmm'),()=>chrV,setChr,{min:0,max:100});setChr(50); + +/* R09 black-face aviation gauge: zone arcs per the airspeed-indicator scheme */ +let avV=52,avNeedle=null; +(function(){const s=$('avgauge'),cx=55,cy=52,sweep=t=>-135+t*270; + const defs=svgEl(s,'defs',{}); + const fl=svgEl(defs,'filter',{id:'avGlow',x:'-60%',y:'-60%',width:'220%',height:'220%'}); + svgEl(fl,'feGaussianBlur',{in:'SourceGraphic',stdDeviation:1.4}); + svgEl(s,'circle',{cx,cy,r:47,fill:'#1b1917',stroke:'#060505','stroke-width':2}); + svgEl(s,'circle',{cx,cy,r:41,fill:'#0a0908',stroke:'#3a352c','stroke-width':1}); + const zone=(t1,t2,color)=>{const [x1,y1]=polar(cx,cy,37,sweep(t1)),[x2,y2]=polar(cx,cy,37,sweep(t2)); + svgEl(s,'path',{d:`M ${x1} ${y1} A 37 37 0 ${(t2-t1)>.5?1:0} 1 ${x2} ${y2}`,fill:'none',stroke:color,'stroke-width':3,opacity:.85});}; + zone(.15,.6,'var(--pass)');zone(.6,.85,'var(--gold)');zone(.85,1,'var(--fail)'); + for(let i=0;i<=40;i++){const t=i/40,major=i%5===0,a=sweep(t); + const [x1,y1]=polar(cx,cy,40,a),[x2,y2]=polar(cx,cy,major?32:36,a); + svgEl(s,'line',{x1,y1,x2,y2,stroke:'var(--gold)','stroke-width':major?1.6:.8,opacity:major?1:.7}); + if(major){const [nx,ny]=polar(cx,cy,25,a); + svgEl(s,'text',{x:nx,y:ny+2.4,'text-anchor':'middle','font-size':6.5,'font-family':'var(--mono)', + fill:'var(--gold-hi)'}).textContent=i/5;}} + svgEl(s,'text',{x:cx,y:cy+16,'text-anchor':'middle','font-size':5.5,'letter-spacing':'.14em', + 'font-family':'var(--mono)',fill:'var(--gold)',opacity:.8}).textContent='×100 RPM'; + avNeedle=svgEl(s,'g',{}); + svgEl(avNeedle,'line',{x1:cx,y1:cy+8,x2:cx,y2:cy-30,stroke:'var(--gold-hi)','stroke-width':4, + 'stroke-linecap':'round',opacity:.5,filter:'url(#avGlow)'}); + svgEl(avNeedle,'line',{x1:cx,y1:cy+8,x2:cx,y2:cy-30,stroke:'var(--gold-hi)','stroke-width':2.2, + 'stroke-linecap':'round'}); + svgEl(s,'circle',{cx,cy,r:5,fill:'#1b1917',stroke:'#3a352c'}); + svgEl(s,'ellipse',{cx:cx-10,cy:cy-24,rx:18,ry:8,fill:'rgba(255,255,255,.05)',transform:`rotate(-18,${cx-10},${cy-24})`});})(); +function setAv(v){avV=Math.max(0,Math.min(100,v)); + avNeedle.setAttribute('transform',`rotate(${-135+avV/100*270},55,52)`); + setRd('R09',(avV/100*8).toFixed(1)+' ×100 rpm');} +dragDelta($('avgauge'),()=>avV,setAv,{min:0,max:100});setAv(52); + +/* R10 data matrix readout */ +const DMX_PAGES=[ + ['SYS',()=>['CPU 42 MEM 61','DSK 58 TMP 47C','ARCH 6.18 LTS']], + ['NET',()=>['WIFI @HYATT 300M','VPN UP DNS OK','BT 2 PAIRED']], + ['TIME',()=>{const d=new Date(),p=n=>String(n).padStart(2,'0'); + return [`${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())}`, + `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`, + 'UP 14D 06:12'];}]]; +let dmxI=0,dmxLines=[]; +(function(){const s=$('dmx'); + const defs=svgEl(s,'defs',{}); + const fl=svgEl(defs,'filter',{id:'dmxGlow',x:'-30%',y:'-30%',width:'160%',height:'160%'}); + svgEl(fl,'feGaussianBlur',{in:'SourceGraphic',stdDeviation:1.1}); + const bg=svgEl(defs,'linearGradient',{id:'dmxBg',x1:0,y1:0,x2:0,y2:1}); + svgEl(bg,'stop',{offset:'0','stop-color':'#140d06'}); + svgEl(bg,'stop',{offset:'1','stop-color':'#0a0705'}); + svgEl(s,'rect',{x:1,y:1,width:188,height:72,rx:5,fill:'url(#dmxBg)',stroke:'#2c261d'}); + for(let r=0;r<3;r++){ + const glow=svgEl(s,'text',{x:12,y:24+r*18,'font-size':9,'letter-spacing':'.15em', + 'font-family':'var(--mono)',fill:'var(--gold-hi)',opacity:.6,filter:'url(#dmxGlow)'}); + const crisp=svgEl(s,'text',{x:12,y:24+r*18,'font-size':9,'letter-spacing':'.15em', + 'font-family':'var(--mono)',fill:'var(--gold-hi)'}); + dmxLines.push([glow,crisp]);} + $('dmx').onclick=()=>setDmx((dmxI+1)%DMX_PAGES.length);})(); +function setDmx(i){dmxI=i;const [name,rowsFn]=DMX_PAGES[i]; + rowsFn().forEach((txt,r)=>{dmxLines[r][0].textContent=txt;dmxLines[r][1].textContent=txt;}); + setRd('R10','page '+name);} +setDmx(0); +if(!matchMedia('(prefers-reduced-motion: reduce)').matches) + setInterval(()=>{if(DMX_PAGES[dmxI][0]==='TIME')setDmx(dmxI);},1000); + +/* R11 warning flag window */ +let flagOn=false,flagStripes=null; +(function(){const s=$('wflag'); + const defs=svgEl(s,'defs',{}); + const pat=svgEl(defs,'pattern',{id:'barber',width:10,height:10,patternUnits:'userSpaceOnUse', + patternTransform:'rotate(45)'}); + svgEl(pat,'rect',{x:0,y:0,width:10,height:10,fill:'#17130c'}); + svgEl(pat,'rect',{x:0,y:0,width:5,height:10,fill:'var(--gold)'}); + const clip=svgEl(defs,'clipPath',{id:'flagWin'}); + svgEl(clip,'rect',{x:14,y:20,width:56,height:24}); + svgEl(s,'rect',{x:11,y:17,width:62,height:30,rx:3,fill:'#0a0908',stroke:'#2c261d','stroke-width':2}); + const g=svgEl(s,'g',{'clip-path':'url(#flagWin)'}); + flagStripes=svgEl(g,'rect',{x:14,y:20,width:56,height:24,fill:'url(#barber)'}); + flagStripes.style.transition='transform .18s';flagStripes.style.transform='translateX(-58px)'; + svgEl(s,'text',{x:92,y:35,'text-anchor':'middle','font-size':7,'letter-spacing':'.14em', + 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent='VIB'; + $('wflag').onclick=()=>setFlag(!flagOn);})(); +function setFlag(on){flagOn=on;flagStripes.style.transform=on?'translateX(0)':'translateX(-58px)'; + setRd('R11',on?'FLAG':'clear');} +setFlag(false); + /* ============ 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