aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-12 00:44:36 -0500
committerCraig Jennings <c@cjennings.net>2026-07-12 00:44:36 -0500
commit03a8cc01cb8c33fd0667585362dcc5121f66801e (patch)
tree68719366131fa310744d47d46939e17eacfa0b0d /docs
parent8aedc95043c69955f2e23e51a555ff2fb177a514 (diff)
downloadarchsetup-03a8cc01cb8c33fd0667585362dcc5121f66801e.tar.gz
archsetup-03a8cc01cb8c33fd0667585362dcc5121f66801e.zip
feat(gallery): add R18 thumb-slide attenuator pair
Two narrow rail channels after a compressor's blend/mix pair (reference filed in the catalogue's working directory): a lit amber numeral column (100 down to 0) inside each screwed rail, a cream thumb tab riding the rail's edge, and the numeral nearest the value lighting bright. The channels drag independently and the readout carries both. This differs from the R12 slot fader on both counts that matter: the scale is a lit column inside the channel rather than engraved beside it, and the control is a side tab rather than a T-handle. I verified both channels in headless Chrome: independent drags move each tab and relight the nearest figure, no console exceptions.
Diffstat (limited to 'docs')
-rw-r--r--docs/prototypes/panel-widget-gallery.html41
1 files changed, 41 insertions, 0 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html
index be79a0a..252a368 100644
--- a/docs/prototypes/panel-widget-gallery.html
+++ b/docs/prototypes/panel-widget-gallery.html
@@ -715,6 +715,9 @@ card(C,'R15','Multi-band dial',
card(C,'R16','Entry keypad',
`<svg id="keypad" class="rsvg" viewBox="0 0 150 190" width="150" height="190"></svg>`,
'<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>`,
+ '<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.');
/* ============ METERS & GAUGES ============ */
const M=$('meters');
@@ -1631,6 +1634,44 @@ 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);
+
/* ============ 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';