aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-12 01:02:03 -0500
committerCraig Jennings <c@cjennings.net>2026-07-12 01:02:03 -0500
commit8fa5fa4f2a7a1cc43cbcb5abdc623e4aac66346e (patch)
treedc77b872ed942d12027bf6dff43b0e3adb3ab0f9 /docs
parenta00b777d2b939d057a4ed43786c6c0072c2552d9 (diff)
downloadarchsetup-8fa5fa4f2a7a1cc43cbcb5abdc623e4aac66346e.tar.gz
archsetup-8fa5fa4f2a7a1cc43cbcb5abdc623e4aac66346e.zip
feat(gallery): add R23-R25 spun knob, stomp pair, fourteen-segment display
Three widgets closing the reference batch (pedal references filed in the catalogue's working directory): - R23 spun-aluminum knob: bright machined face with concentric tooling rings inside a knurled grip ring, red index over dot ticks. Promoted from the banked queue after a second independent reference confirmed it. - R24 stomp switch + jewel: the pedal engage pair — a chrome dome stomp and the faceted jewel that reports the state, translated to the kit's amber. - R25 fourteen-segment display: the starburst alphanumeric that spells words, with a per-letter segment map and glow. Click cycles ZOOM/ECHO/TAPE/MOOD/HALL/COMP. I verified all three in headless Chrome: the knob tracks drags, the stomp toggles the jewel both ways, the display respells on click with the exact segment count the letter map predicts, no console exceptions.
Diffstat (limited to 'docs')
-rw-r--r--docs/prototypes/panel-widget-gallery.html106
1 files changed, 106 insertions, 0 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html
index 70b92d2..ac2af6a 100644
--- a/docs/prototypes/panel-widget-gallery.html
+++ b/docs/prototypes/panel-widget-gallery.html
@@ -730,6 +730,12 @@ card(C,'R21','LED program row',
card(C,'R22','Three-position slide',
`<svg id="varslide" class="rsvg press" viewBox="0 0 110 64" width="110" height="64"></svg>`,
'<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>`,
+ '<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>`,
+ '<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.');
/* ============ METERS & GAUGES ============ */
const M=$('meters');
@@ -870,6 +876,9 @@ card(I,'R10','Data matrix readout',
card(I,'R11','Warning flag window',
`<svg id="wflag" class="rsvg press" viewBox="0 0 120 64" width="120" height="64"></svg>`,
'<b>the mechanical alarm flag.</b> 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.');
+card(I,'R25','Fourteen-segment display',
+ `<svg id="seg14" class="rsvg press" viewBox="0 0 130 54" width="130" height="54"></svg>`,
+ '<b>segments that spell.</b> The starburst alphanumeric — diagonals and split bars let it write words, not just digits. Click to cycle the word. After a pedal preset display.');
/* ============ CONTROL WIRING ============ */
/* 01 toggle */
@@ -1821,6 +1830,103 @@ function setVarsl(i){varslI=i;const detX=[34,55,76];
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);
+
+/* R25 fourteen-segment display: the starburst that spells */
+const SEG14_WORDS=['ZOOM','ECHO','TAPE','MOOD','HALL','COMP'];
+const SEG14_MAP={A:['a','b','c','e','f','g1','g2'],C:['a','d','e','f'],
+ D:['a','b','c','d','i','l'],E:['a','d','e','f','g1','g2'],H:['b','c','e','f','g1','g2'],
+ L:['d','e','f'],M:['b','c','e','f','h','j'],O:['a','b','c','d','e','f'],
+ P:['a','b','e','f','g1','g2'],T:['a','i','l'],Z:['a','d','j','k']};
+let seg14I=0,seg14Cells=[];
+(function(){const s=$('seg14');
+ svgEl(s,'rect',{x:1,y:1,width:128,height:52,rx:5,fill:'#0a0f08',stroke:'#1c2a16','stroke-width':2});
+ // segment shapes in a 22x36 local box (x0,y0 top-left)
+ const TH=2.6,W=22,H=36,mid=H/2;
+ const segs={
+ a:[[2,0],[W-2,0],[W-4,TH],[4,TH]],
+ d:[[2,H],[W-2,H],[W-4,H-TH],[4,H-TH]],
+ f:[[0,2],[TH,4],[TH,mid-2],[0,mid-1]],
+ e:[[0,H-2],[TH,H-4],[TH,mid+2],[0,mid+1]],
+ b:[[W,2],[W-TH,4],[W-TH,mid-2],[W,mid-1]],
+ c:[[W,H-2],[W-TH,H-4],[W-TH,mid+2],[W,mid+1]],
+ g1:[[2,mid],[4,mid-TH/2],[W/2-1,mid-TH/2],[W/2-1,mid+TH/2],[4,mid+TH/2]],
+ g2:[[W-2,mid],[W-4,mid-TH/2],[W/2+1,mid-TH/2],[W/2+1,mid+TH/2],[W-4,mid+TH/2]],
+ i:[[W/2-TH/2,3],[W/2+TH/2,3],[W/2+TH/2,mid-2],[W/2-TH/2,mid-2]],
+ l:[[W/2-TH/2,H-3],[W/2+TH/2,H-3],[W/2+TH/2,mid+2],[W/2-TH/2,mid+2]],
+ h:[[3,3],[5.5,3],[W/2-2,mid-3],[W/2-4.5,mid-3]],
+ j:[[W-3,3],[W-5.5,3],[W/2+2,mid-3],[W/2+4.5,mid-3]],
+ k:[[3,H-3],[5.5,H-3],[W/2-2,mid+3],[W/2-4.5,mid+3]],
+ m:[[W-3,H-3],[W-5.5,H-3],[W/2+2,mid+3],[W/2+4.5,mid+3]]};
+ for(let d=0;d<4;d++){const x0=13+d*28,y0=9,cell={};
+ for(const k in segs){
+ cell[k]=svgEl(s,'polygon',{points:segs[k].map(p=>`${x0+p[0]},${y0+p[1]}`).join(' '),
+ fill:'var(--sevoff)'});}
+ seg14Cells.push(cell);}
+ $('seg14').onclick=()=>setSeg14((seg14I+1)%SEG14_WORDS.length);})();
+function setSeg14(i){seg14I=i;const word=SEG14_WORDS[i].padEnd(4,' ');
+ seg14Cells.forEach((cell,d)=>{const lit=SEG14_MAP[word[d]]||[];
+ for(const k in cell){const on=lit.includes(k);
+ cell[k].setAttribute('fill',on?'var(--sevgrn)':'var(--sevoff)');
+ cell[k].setAttribute('style',on?'filter:drop-shadow(0 0 2.5px rgba(87,211,87,.6))':'');}});
+ setRd('R25',SEG14_WORDS[i]);}
+setSeg14(0);
+
/* ============ LIVE SIGNAL LOOPS ============ */
buildBars($('vuL'),16);buildBars($('vuR'),16);$('mini').innerHTML='<i></i><i></i><i></i><i></i>';
(function(){const eq=$('eq');for(let b=0;b<11;b++){const band=document.createElement('span');band.className='band';