diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-12 21:45:32 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-12 21:45:32 -0500 |
| commit | 313496ba52424b883de3b528130a85382fa726c0 (patch) | |
| tree | 2434e18dab4ca317ae7070593b83889359370f6e /docs/prototypes/panel-widget-gallery.html | |
| parent | fb94b0fe842d42cf7145d23ad0f0d2a3f8f23c76 (diff) | |
| download | archsetup-313496ba52424b883de3b528130a85382fa726c0.tar.gz archsetup-313496ba52424b883de3b528130a85382fa726c0.zip | |
refactor(gallery): extract controls R16, R18-R24 into GW builders
Entry keypad, thumb-slide pair, waveform region editor, drum roller, LED program row, three-position slide, spun knob, and stomp switch. The drum roller's per-instance clip paths get a uid() helper so two instances can coexist; the region editor's screen-family chips now reach the widget through the card handle (card.gw.el) instead of a stage id, and probe-fams drives its post-recolor check through the handle's set(). Behavioral pass now 78 checks; both probes green.
Diffstat (limited to 'docs/prototypes/panel-widget-gallery.html')
| -rw-r--r-- | docs/prototypes/panel-widget-gallery.html | 292 |
1 files changed, 9 insertions, 283 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index b192fb0..709b2e8 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -1638,28 +1638,28 @@ card(C,'R15','Multi-band dial', (st,rd)=>GW.multiBandDial(st,{onChange:(v,t)=>rd(t)}), '<b>four scales, one needle.</b> Nested band arcs on a cream face; the active ring reads bold. Drag the left dial to tune; click the bandspread dial to switch bands. After a shortwave receiver dial pair.'); card(C,'R16','Entry keypad', - `<svg id="keypad" class="rsvg" viewBox="0 0 150 190" width="150" height="190"></svg>`, + (st,rd)=>GW.entryKeypad(st,{onChange:(v,t)=>rd(t)}), '<b>a composed entry instrument.</b> Worn keycaps feed the amber display; the lamp watches the buffer; the amber keys confirm and clear. Click the keys. After an industrial keypad prop.'); card(C,'R18','Thumb-slide attenuator pair', - `<svg id="thumbsl" class="rsvg" viewBox="0 0 130 150" width="130" height="150"></svg>`, + (st,rd)=>GW.thumbSlide(st,{onChange:(v,t)=>rd(t)}), '<b>a lit column of numbers, a thumb tab.</b> The scale glows inside the rail; the cream tab rides beside it and the nearest figure lights. Drag either channel. After a compressor blend/mix pair.'); card(C,'R19','Waveform region editor', - `<svg id="wregion" class="rsvg" viewBox="0 0 190 100" width="190" height="100"></svg>`, + (st,rd)=>GW.waveRegion(st,{start:22,end:76,onChange:(v,t)=>rd(t)}), '<b>pick a region on the wave.</b> The monochrome LCD shows the sample; drag near either flag to move START or END, and the selection draws bright. After a sampler edit screen.'); card(C,'R20','Drum roller selector', - `<svg id="drumr" class="rsvg" viewBox="0 0 130 140" width="130" height="140"></svg>`, + (st,rd)=>GW.drumRoller(st,{onChange:(v,t)=>rd(t)}), '<b>roll to the number.</b> The numbered drum shows through a tall window and the center value sits on an inverted chip. Drag either drum. After an equalizer tone selector.'); card(C,'R21','LED program row', - `<svg id="ledrow" class="rsvg" viewBox="0 0 190 58" width="190" height="58"></svg>`, + (st,rd)=>GW.ledRow(st,{index:5,onChange:(v,t)=>rd(t)}), '<b>identical keys, one lit dot.</b> The LED above the button carries the selection, not the key itself — the classic program-select row. Click a key; readout names the program. After a digital reverb’s program bank.'); card(C,'R22','Three-position slide', - `<svg id="varslide" class="rsvg press" viewBox="0 0 110 64" width="110" height="64"></svg>`, + (st,rd)=>GW.pillSlide(st,{index:1,onChange:(v,t)=>rd(t)}), '<b>a detented pill, three stops.</b> The chrome pill parks at A, AB, or B, and the LED pair below tells the truth — both light on AB. Click a position. After a drum machine variation switch.'); card(C,'R23','Spun-aluminum knob', - `<svg id="spunk" class="rsvg drag" viewBox="0 0 110 110" width="110" height="110"></svg>`, + (st,rd)=>GW.spunKnob(st,{value:62,onChange:(v,t)=>rd(t)}), '<b>bright metal, machined rings.</b> A spun face with concentric tooling marks in a knurled grip ring, red index over dot ticks. Drag up/down. After a boutique pedal knob, confirmed by an avionics cluster.'); card(C,'R24','Stomp switch + jewel', - `<svg id="stomp" class="rsvg press" viewBox="0 0 110 110" width="110" height="110"></svg>`, + (st,rd)=>GW.stompSwitch(st,{on:false,onChange:(v,t)=>rd(t)}), '<b>the engage pair.</b> A chrome dome stomp and the faceted jewel that reports it — press to engage, the jewel lights; press again to bypass. Click it. After a tremolo pedal footswitch.'); card(C,'R27','Winged gain selector', `<svg id="wingk" class="rsvg drag" viewBox="0 0 110 110" width="110" height="110"></svg>`, @@ -2270,48 +2270,6 @@ setEdge(.62); -/* R16 entry keypad: worn keys feed the amber display; lamps watch state */ -let kpBuf='',kpDisp=null,kpLampTop=null,kpLampBot=null; -(function(){const s=$('keypad'); - const defs=svgEl(s,'defs',{}); - const kg=svgEl(defs,'linearGradient',{id:'kpKey',x1:0,y1:0,x2:0,y2:1}); - svgEl(kg,'stop',{offset:'0','stop-color':'#dbd8cf'}); - svgEl(kg,'stop',{offset:'1','stop-color':'#a29d92'}); - const ag=svgEl(defs,'linearGradient',{id:'kpAmber',x1:0,y1:0,x2:0,y2:1}); - svgEl(ag,'stop',{offset:'0','stop-color':'var(--amber-grad-top)'}); - svgEl(ag,'stop',{offset:'1','stop-color':'var(--amber-grad-mid)'}); - // lamp pod - const lamp=cy=>{const l=svgEl(s,'circle',{cx:13,cy,r:6.5,fill:'#3a0f0a',stroke:'#14100e','stroke-width':1.5});return l;}; - kpLampTop=lamp(20);kpLampBot=lamp(38); - // display window - svgEl(s,'rect',{x:26,y:8,width:116,height:32,rx:5,fill:'#0a0806',stroke:'#2c261d','stroke-width':2}); - kpDisp=svgEl(s,'text',{x:84,y:31,'text-anchor':'middle','font-size':16,'letter-spacing':'.22em', - 'font-family':'var(--mono)',fill:'var(--gold-hi)'}); - // key plate - svgEl(s,'rect',{x:24,y:48,width:118,height:138,rx:8,fill:'#1a1714',stroke:'#0a0908','stroke-width':1.5}); - const KEYS=[['1','2','3'],['4','5','6'],['7','8','9'],['✓','0','✗']]; - const jitter=[-2,1,-1,2,0,-2,1,-1,2,0,-1,1]; - KEYS.forEach((row,r)=>row.forEach((k,c)=>{ - const x=47+c*36,y=68+r*32,amber=(k==='✓'||k==='✗'); - const g=svgEl(s,'g',{});g.style.cursor='pointer';g.style.transition='transform .07s'; - svgEl(g,'rect',{x:x-14,y:y-11,width:28,height:24,rx:4,fill:amber?'url(#kpAmber)':'url(#kpKey)', - stroke:'#4e4a42','stroke-width':1,'stroke-opacity':.8}); - svgEl(g,'text',{x,y:y+6,'text-anchor':'middle','font-size':13,'font-weight':700, - 'font-family':'var(--mono)',fill:k==='✓'?'#3f5a1f':k==='✗'?'#7a2a1a':'#2b2721', - transform:`rotate(${jitter[r*3+c]},${x},${y})`}).textContent=k; - g.addEventListener('click',()=>{g.style.transform='translateY(1.5px)'; - setTimeout(()=>g.style.transform='',80);kpPress(k);});})); - })(); -function kpRender(){kpDisp.textContent=kpBuf.padEnd(6,'–'); - kpLampTop.setAttribute('fill',kpBuf?'var(--jewel-r)':'#3a0f0a');} -function kpPress(k){ - if(k==='✓'){setRd('R16',kpBuf?'OK · '+kpBuf:'empty');kpBuf='';kpRender();return;} - if(k==='✗'){kpBuf='';kpRender();setRd('R16','cleared'); - kpLampBot.setAttribute('fill','var(--jewel-r)'); - setTimeout(()=>kpLampBot.setAttribute('fill','#3a0f0a'),350);return;} - 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; @@ -2341,238 +2299,6 @@ function tickRcrt(){rcrtPh+=0.12;const amp=8+3*Math.sin(rcrtPh*0.35);let pts=''; tickRcrt(); if(!matchMedia('(prefers-reduced-motion: reduce)').matches)setInterval(tickRcrt,80); -/* R18 thumb-slide attenuator pair: lit numeral strip, side thumb tab */ -const THSL=[{name:'BLEND',v:74},{name:'MIX',v:92}]; -const thslParts=[]; -(function(){const s=$('thumbsl'),y0=22,y1=122; - const defs=svgEl(s,'defs',{}); - const rg=svgEl(defs,'linearGradient',{id:'thRail',x1:0,y1:0,x2:1,y2:0}); - svgEl(rg,'stop',{offset:'0','stop-color':'#3a3733'}); - svgEl(rg,'stop',{offset:'.5','stop-color':'#211f1c'}); - svgEl(rg,'stop',{offset:'1','stop-color':'#161412'}); - const tg=svgEl(defs,'linearGradient',{id:'thTab',x1:0,y1:0,x2:0,y2:1}); - svgEl(tg,'stop',{offset:'0','stop-color':'#f2efe6'}); - svgEl(tg,'stop',{offset:'1','stop-color':'#c6c1b3'}); - THSL.forEach((ch,i)=>{const x=40+i*50; - svgEl(s,'rect',{x:x-9,y:y0-10,width:18,height:y1-y0+20,rx:3,fill:'url(#thRail)',stroke:'#0a0908','stroke-width':1.2}); - for(const sy of [y0-6,y1+6]){svgEl(s,'circle',{cx:x,cy:sy,r:2.4,fill:'url(#sfScrew)',stroke:'#0a0908','stroke-width':.5}); - svgEl(s,'line',{x1:x-1.8,y1:sy-1,x2:x+1.8,y2:sy+1,stroke:'#14110e','stroke-width':.8});} - svgEl(s,'rect',{x:x-5,y:y0,width:10,height:y1-y0,fill:'#0d0a08',stroke:'#050404'}); - for(let n=0;n<=10;n++){const val=100-n*10,y=y0+6+n*(y1-y0-12)/10; - svgEl(s,'text',{x,y:y+2,'text-anchor':'middle','font-size':5.5,'font-family':'var(--mono)', - fill:'var(--gold)',opacity:.55}).textContent=val;} - const tab=svgEl(s,'g',{}); - svgEl(tab,'rect',{x:x+7,y:-6,width:8,height:12,rx:2,fill:'url(#thTab)',stroke:'#7a766a','stroke-width':.6}); - svgEl(tab,'rect',{x:x+8.2,y:-1,width:5.6,height:1.6,fill:'rgba(0,0,0,.25)'}); - svgEl(s,'text',{x,y:145,'text-anchor':'middle','font-size':6,'letter-spacing':'.14em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent=ch.name; - const hit=svgEl(s,'rect',{x:x-12,y:y0-10,width:30,height:y1-y0+20,fill:'transparent'}); - hit.style.cursor='ns-resize'; - thslParts.push({tab,nums:[...s.querySelectorAll('text')].filter(t=>t.getAttribute('x')==String(x)&&t.textContent!==ch.name)}); - dragY(hit,pct=>setThsl(i,pct));}); - })(); -function setThsl(i,v){v=Math.max(0,Math.min(100,Math.round(v)));THSL[i].v=v; - const p=thslParts[i]; - p.tab.setAttribute('transform',`translate(0,${28+(100-v)*0.88})`); - p.nums.forEach(t=>{const on=Math.abs(parseInt(t.textContent)-v)<=5; - t.setAttribute('fill',on?'var(--gold-hi)':'var(--gold)');t.setAttribute('opacity',on?'1':'.55');}); - setRd('R18',`${THSL[0].name} ${THSL[0].v} · ${THSL[1].name} ${THSL[1].v}`);} -setThsl(0,74);setThsl(1,92); - -/* R19 waveform region editor: monochrome LCD, draggable S/E flags */ -let wrS=22,wrE=76,wrBars=[],wrFlagS=null,wrFlagE=null; -(function(){const s=$('wregion'),x0=10,x1=180,yMid=48,N=85; - svgEl(s,'rect',{x:1,y:1,width:188,height:98,rx:6,fill:'var(--scr-bg1,#0b0c0b)',stroke:'var(--scr-brd,#2a2c2a)','stroke-width':2}); - svgEl(s,'text',{x:12,y:13,'font-size':7,'font-family':'var(--mono)',fill:'var(--scr-hi,#e8eae8)'}).textContent='C1:START'; - svgEl(s,'text',{x:78,y:13,'font-size':7,'font-family':'var(--mono)',fill:'var(--scr-hi,#e8eae8)'}).textContent='C2:OFF'; - svgEl(s,'text',{x:136,y:13,'font-size':7,'font-family':'var(--mono)',fill:'var(--scr-hi,#e8eae8)'}).textContent='C3:END'; - svgEl(s,'line',{x1:x0,y1:yMid,x2:x1,y2:yMid,stroke:'#3a3c3a','stroke-width':.6,'stroke-dasharray':'1.5 2'}); - for(let i=0;i<N;i++){const x=x0+(i/(N-1))*(x1-x0); - const env=Math.abs(Math.sin(i*0.19))*Math.abs(Math.sin(i*0.045))*(i%17<11?1:.25); - const h=Math.max(1.2,env*26); - wrBars.push(svgEl(s,'rect',{x:x-0.8,y:yMid-h,width:1.6,height:h*2,fill:'var(--scr-dim,#5a5c5a)'}));} - const flag=(lbl)=>{const g=svgEl(s,'g',{}); - svgEl(g,'line',{x1:0,y1:18,x2:0,y2:78,stroke:'var(--scr-hi,#f2f4f2)','stroke-width':1}); - svgEl(g,'rect',{x:lbl==='S'?0:-8,y:70,width:8,height:8,fill:'var(--scr-hi,#f2f4f2)'}); - svgEl(g,'text',{x:lbl==='S'?4:-4,y:76.5,'text-anchor':'middle','font-size':6.5,'font-weight':700, - 'font-family':'var(--mono)',fill:'var(--scr-bg1,#0b0c0b)'}).textContent=lbl;return g;}; - wrFlagS=flag('S');wrFlagE=flag('E'); - svgEl(s,'rect',{x:10,y:84,width:78,height:11,fill:'var(--scr-hi,#e8eae8)'}); - svgEl(s,'text',{x:14,y:92.5,'font-size':6.5,'font-family':'var(--mono)',fill:'var(--scr-bg1,#0b0c0b)'}).textContent='ENC:ZOOM(1x)'; - svgEl(s,'text',{x:96,y:92.5,'font-size':6.5,'font-family':'var(--mono)',fill:'var(--scr-hi,#e8eae8)'}).textContent='A-3 M:[S]'; - svgEl(s,'rect',{x:148,y:84,width:32,height:11,fill:'var(--scr-hi,#e8eae8)'}); - svgEl(s,'text',{x:164,y:92.5,'text-anchor':'middle','font-size':6.5,'font-weight':700, - 'font-family':'var(--mono)',fill:'var(--scr-bg1,#0b0c0b)'}).textContent='MENU'; - s.style.cursor='ew-resize'; - dragX(s,pct=>{ - // move whichever flag is nearer the pointer - if(Math.abs(pct-wrS)<=Math.abs(pct-wrE))setWregion(Math.min(pct,wrE-4),wrE); - else setWregion(wrS,Math.max(pct,wrS+4));});})(); -function setWregion(sv,ev){wrS=Math.max(0,Math.min(96,sv));wrE=Math.max(4,Math.min(100,ev)); - const x0=10,x1=180,xOf=p=>x0+p/100*(x1-x0); - wrFlagS.setAttribute('transform',`translate(${xOf(wrS)},0)`); - wrFlagE.setAttribute('transform',`translate(${xOf(wrE)},0)`); - wrBars.forEach((b,i)=>{const p=i/(wrBars.length-1)*100; - b.setAttribute('fill',(p>=wrS&&p<=wrE)?'var(--scr-hi,#f2f4f2)':'var(--scr-dim,#5a5c5a)');}); - setRd('R19',`S ${Math.round(wrS)}% · E ${Math.round(wrE)}%`);} -setWregion(22,76); - -/* R20 drum roller selector: numbered drum in a window, center chip reads it */ -const DRUMR=[{name:'HIGH',v:6},{name:'LOW',v:8}]; -const drumrGrps=[]; -(function(){const s=$('drumr'),cy=76,step=17; - const defs=svgEl(s,'defs',{}); - const paper=svgEl(defs,'linearGradient',{id:'drPaper',x1:0,y1:0,x2:1,y2:0}); - svgEl(paper,'stop',{offset:'0','stop-color':'#cfc6a8'}); - svgEl(paper,'stop',{offset:'.5','stop-color':'#ece4c8'}); - svgEl(paper,'stop',{offset:'1','stop-color':'#c6bd9e'}); - const curve=svgEl(defs,'linearGradient',{id:'drCurve',x1:0,y1:0,x2:0,y2:1}); - svgEl(curve,'stop',{offset:'0','stop-color':'rgba(0,0,0,.4)'}); - svgEl(curve,'stop',{offset:'.28','stop-color':'rgba(0,0,0,0)'}); - svgEl(curve,'stop',{offset:'.72','stop-color':'rgba(0,0,0,0)'}); - svgEl(curve,'stop',{offset:'1','stop-color':'rgba(0,0,0,.4)'}); - svgEl(s,'text',{x:65,y:12,'text-anchor':'middle','font-size':7,'letter-spacing':'.18em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent='EQUALIZER'; - DRUMR.forEach((ch,i)=>{const x=45+i*50; - svgEl(s,'text',{x:x+18,y:34,'text-anchor':'middle','font-size':8,fill:'var(--steel)'}).textContent='+'; - svgEl(s,'text',{x:x+18,y:124,'text-anchor':'middle','font-size':8,fill:'var(--steel)'}).textContent='−'; - svgEl(s,'rect',{x:x-12,y:24,width:24,height:104,rx:4,fill:'url(#thRail)',stroke:'#0a0908','stroke-width':1.2}); - const clip=svgEl(defs,'clipPath',{id:'drClip'+i}); - svgEl(clip,'rect',{x:x-9,y:28,width:18,height:96}); - svgEl(s,'rect',{x:x-9,y:28,width:18,height:96,fill:'url(#drPaper)'}); - const g=svgEl(s,'g',{'clip-path':`url(#drClip${i})`}); - const nums=svgEl(g,'g',{});nums.style.transition='transform .12s'; - for(let n=1;n<=10;n++) - svgEl(nums,'text',{x,y:cy+3+(ch.v-n)*step,'text-anchor':'middle','font-size':9,'font-weight':700, - 'font-family':'var(--mono)',fill:'#2b2418'}).textContent=n; - svgEl(g,'rect',{x:x-9,y:28,width:18,height:96,fill:'url(#drCurve)','pointer-events':'none'}); - svgEl(s,'rect',{x:x-8,y:cy-6.5,width:16,height:13,rx:1.5,fill:'#1a1613',opacity:.92}); - const chip=svgEl(s,'text',{x,y:cy+3,'text-anchor':'middle','font-size':9,'font-weight':700, - 'font-family':'var(--mono)',fill:'var(--cream)'}); - svgEl(s,'text',{x,y:136,'text-anchor':'middle','font-size':6,'letter-spacing':'.12em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent=ch.name; - const hit=svgEl(s,'rect',{x:x-14,y:24,width:28,height:104,fill:'transparent'}); - hit.style.cursor='ns-resize'; - drumrGrps.push({nums,chip,base:ch.v}); - dragDelta(hit,()=>DRUMR[i].v,v=>setDrumr(i,v),{min:1,max:10,sens:.08});}); - })(); -function setDrumr(i,v){v=Math.max(1,Math.min(10,v));DRUMR[i].v=v; - const p=drumrGrps[i]; - p.nums.style.transform=`translateY(${(v-p.base)*17}px)`; - p.chip.textContent=Math.round(v); - setRd('R20',`${DRUMR[0].name} ${Math.round(DRUMR[0].v)} · ${DRUMR[1].name} ${Math.round(DRUMR[1].v)}`);} -setDrumr(0,6);setDrumr(1,8); - -/* R21 LED program row: exclusive select, the LED carries the state */ -const LEDROW_PROGS=['Sm Hall B','VocPlate','Lg Hall B','Chamber','ParcPlate','Sm Hall A','Room A','Const Plate']; -let ledrowI=5,ledrowLeds=[]; -(function(){const s=$('ledrow'); - const defs=svgEl(s,'defs',{}); - const kb=svgEl(defs,'linearGradient',{id:'lrKey',x1:0,y1:0,x2:0,y2:1}); - svgEl(kb,'stop',{offset:'0','stop-color':'#2b2823'}); - svgEl(kb,'stop',{offset:'1','stop-color':'#171512'}); - LEDROW_PROGS.forEach((name,i)=>{const x=16+i*22.6; - svgEl(s,'text',{x,y:9,'text-anchor':'middle','font-size':6,'font-family':'var(--mono)', - fill:'var(--steel)'}).textContent=i+1; - ledrowLeds.push(svgEl(s,'circle',{cx:x,cy:17,r:2.4,fill:'#3a0f0a'})); - const g=svgEl(s,'g',{});g.style.cursor='pointer';g.style.transition='transform .07s'; - svgEl(g,'rect',{x:x-8.5,y:24,width:17,height:22,rx:2.5,fill:'url(#lrKey)',stroke:'#0a0908','stroke-width':1}); - svgEl(g,'rect',{x:x-6.5,y:26.5,width:13,height:3,rx:1.5,fill:'rgba(255,255,255,.06)'}); - g.addEventListener('click',()=>{g.style.transform='translateY(1.5px)'; - setTimeout(()=>g.style.transform='',80);setLedrow(i);});}); - svgEl(s,'text',{x:95,y:56,'text-anchor':'middle','font-size':6,'letter-spacing':'.16em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent='PROGRAM';})(); -function setLedrow(i){ledrowI=i; - ledrowLeds.forEach((l,k)=>{const on=k===i; - l.setAttribute('fill',on?'var(--jewel-r)':'#3a0f0a'); - l.setAttribute('style',on?'filter:drop-shadow(0 0 3px rgba(255,91,69,.8))':'');}); - setRd('R21',`${ledrowI+1} · ${LEDROW_PROGS[ledrowI]}`);} -setLedrow(5); - -/* R22 three-position slide: chrome pill, detents, honest LED pair */ -const VARSL_POS=['A','AB','B']; -let varslI=1,varslPill=null,varslLbls=[],varslLeds=[]; -(function(){const s=$('varslide');const detX=[34,55,76]; - svgEl(s,'text',{x:55,y:10,'text-anchor':'middle','font-size':5.5,'letter-spacing':'.16em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent='BASIC · VARIATION'; - svgEl(s,'rect',{x:20,y:16,width:70,height:14,rx:7,fill:'#0b0a09',stroke:'#000','stroke-width':1}); - svgEl(s,'rect',{x:21,y:17,width:68,height:5,rx:2.5,fill:'rgba(255,255,255,.04)'}); - varslPill=svgEl(s,'rect',{x:-13,y:18.5,width:26,height:9,rx:4.5,fill:'url(#sfChrome)',stroke:'#4e4a42','stroke-width':.6}); - varslPill.style.transition='transform .12s'; - VARSL_POS.forEach((lbl,i)=>{ - varslLbls.push(svgEl(s,'text',{x:detX[i],y:40,'text-anchor':'middle','font-size':6.5, - 'font-family':'var(--mono)',fill:'var(--dim)'})); - varslLbls[i].textContent=lbl;}); - svgEl(s,'rect',{x:32,y:45,width:46,height:11,rx:2,fill:'#141210',stroke:'#060505'}); - [44,66].forEach(x=>varslLeds.push(svgEl(s,'circle',{cx:x,cy:50.5,r:2.4,fill:'#3a0f0a'}))); - s.addEventListener('click',e=>{const r=s.getBoundingClientRect(); - const x=(e.clientX-r.left)/r.width*110; - setVarsl(x<45?0:x<66?1:2);});})(); -function setVarsl(i){varslI=i;const detX=[34,55,76]; - varslPill.setAttribute('transform',`translate(${detX[i]},0)`); - varslLbls.forEach((t,k)=>t.setAttribute('fill',k===i?'var(--gold-hi)':'var(--dim)')); - const lit=[i===0||i===1,i===2||i===1]; - varslLeds.forEach((l,k)=>l.setAttribute('fill',lit[k]?'var(--jewel-r)':'#3a0f0a')); - setRd('R22',VARSL_POS[i]);} -setVarsl(1); - -/* R23 spun-aluminum knob: machined rings in a knurled grip */ -let spunV=62,spunIdx=null; -(function(){const s=$('spunk'),cx=55,cy=52; - const defs=svgEl(s,'defs',{}); - const al=svgEl(defs,'radialGradient',{id:'spunFace',cx:'42%',cy:'34%',r:'85%'}); - svgEl(al,'stop',{offset:'0','stop-color':'#e8e6e0'}); - svgEl(al,'stop',{offset:'.7','stop-color':'#b3b0a8'}); - svgEl(al,'stop',{offset:'1','stop-color':'#8a877e'}); - for(let k=0;k<8;k++){const [x,y]=polar(cx,cy,45,-135+k*38.6); - svgEl(s,'circle',{cx:x,cy:y,r:1.3,fill:'var(--steel)'});} - for(let k=0;k<22;k++){const [x,y]=polar(cx,cy,36,k*16.36); - svgEl(s,'circle',{cx:x,cy:y,r:2.6,fill:'#14110e'});} - svgEl(s,'circle',{cx,cy,r:36,fill:'#1a1714',stroke:'#000','stroke-width':.8}); - svgEl(s,'circle',{cx,cy,r:30,fill:'url(#spunFace)',stroke:'#6e6b63','stroke-width':.8}); - for(const r of [24,18,12,6]) - svgEl(s,'circle',{cx,cy,r,fill:'none',stroke:r%12===0?'rgba(0,0,0,.12)':'rgba(255,255,255,.3)','stroke-width':.6}); - spunIdx=svgEl(s,'line',{x1:cx,y1:cy-28,x2:cx,y2:cy-10,stroke:'var(--fail)','stroke-width':2.6,'stroke-linecap':'round'}); - svgEl(s,'ellipse',{cx:cx-9,cy:cy-11,rx:9,ry:5,fill:'rgba(255,255,255,.28)',transform:`rotate(-32,${cx-9},${cy-11})`}); - svgEl(s,'text',{x:cx,y:103,'text-anchor':'middle','font-size':6,'letter-spacing':'.16em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent='SPEED';})(); -function setSpun(v){spunV=Math.max(0,Math.min(100,v)); - spunIdx.setAttribute('transform',`rotate(${-135+spunV/100*270},55,52)`); - setRd('R23',Math.round(spunV)+'%');} -dragDelta($('spunk'),()=>spunV,setSpun,{min:0,max:100});setSpun(62); - -/* R24 stomp switch + jewel: press to engage, the jewel reports */ -let stompOn=false,stompDome=null,stompJewel=null,stompGlow=null; -(function(){const s=$('stomp'),cx=55; - const defs=svgEl(s,'defs',{}); - const dg=svgEl(defs,'radialGradient',{id:'stompDome',cx:'40%',cy:'30%',r:'80%'}); - svgEl(dg,'stop',{offset:'0','stop-color':'#f4f2ec'}); - svgEl(dg,'stop',{offset:'.55','stop-color':'#b9b6ae'}); - svgEl(dg,'stop',{offset:'1','stop-color':'#6e6b63'}); - const jg=svgEl(defs,'radialGradient',{id:'stompJewel',cx:'38%',cy:'30%',r:'80%'}); - svgEl(jg,'stop',{offset:'0','stop-color':'#ffe9b0'}); - svgEl(jg,'stop',{offset:'.45','stop-color':'var(--jewel-a)'}); - svgEl(jg,'stop',{offset:'1','stop-color':'#5c3d0c'}); - stompGlow=svgEl(s,'circle',{cx,cy:22,r:14,fill:'rgba(255,180,58,.35)',filter:'url(#avGlow)',opacity:0}); - stompJewel=svgEl(s,'circle',{cx,cy:22,r:9,fill:'#241f1b',stroke:'#0a0908','stroke-width':1.5}); - for(let k=0;k<6;k++){const a1=k*60,a2=k*60+30; - const [x1,y1]=polar(cx,22,9,a1),[x2,y2]=polar(cx,22,9,a2); - svgEl(s,'path',{d:`M ${cx} 22 L ${x1} ${y1} A 9 9 0 0 1 ${x2} ${y2} Z`, - fill:k%2?'rgba(255,255,255,.09)':'rgba(0,0,0,.10)','pointer-events':'none'});} - for(let k=0;k<20;k++){const [x,y]=polar(cx,72,25,k*18); - svgEl(s,'circle',{cx:x,cy:y,r:2.4,fill:'#14110e'});} - svgEl(s,'circle',{cx,cy:72,r:25,fill:'#1a1714',stroke:'#000','stroke-width':.8}); - stompDome=svgEl(s,'g',{});stompDome.style.transition='transform .08s'; - svgEl(stompDome,'circle',{cx,cy:72,r:19,fill:'url(#stompDome)',stroke:'#55524a','stroke-width':.8}); - svgEl(stompDome,'ellipse',{cx:cx-6,cy:64,rx:8,ry:4.5,fill:'rgba(255,255,255,.5)',transform:`rotate(-24,${cx-6},64)`}); - $('stomp').onclick=()=>{stompDome.style.transform='translateY(1.5px)'; - setTimeout(()=>stompDome.style.transform='',90);setStomp(!stompOn);};})(); -function setStomp(on){stompOn=on; - stompJewel.setAttribute('fill',on?'url(#stompJewel)':'#241f1b'); - stompGlow.setAttribute('opacity',on?'1':'0'); - setRd('R24',on?'ENGAGED':'bypass');} -setStomp(false); - /* R27 winged gain selector: red T-bar over a dot ring, stepped detents */ const WINGK_STEPS=[-80,-70,-60,-50,-40,-30,-20,-10,-5,0,5,10]; let wingI=7,wingGrp=null; @@ -3813,7 +3539,7 @@ let dkPos=0,dkCarry=0; The nixie stays chipless on purpose: neon is only ever orange, so alternates would be historically false. */ screenChips('R10',$('dmx'),['amber','green','red','blue','vfd'],'amber'); screenChips('R17',$('rcrt'),['green','amber','red','blue','vfd'],'green'); -screenChips('R19',$('wregion'),['white','green','amber','blue','vfd'],'white'); +screenChips('R19',$('card-R19').gw.el,['white','green','amber','blue','vfd'],'white'); screenChips('R31',$('radar'),['amber','green','red','blue','vfd'],'amber'); screenChips('N11',$('scopep').closest('.scope'),['green','amber','red','blue','vfd'],'green'); BOOST.forEach(no=>{const rd=document.getElementById('rd-'+no); |
