From 03a8cc01cb8c33fd0667585362dcc5121f66801e Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 12 Jul 2026 00:44:36 -0500 Subject: 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. --- docs/prototypes/panel-widget-gallery.html | 41 +++++++++++++++++++++ .../2026-07-12-thumb-slide-attenuators.png | Bin 0 -> 76160 bytes 2 files changed, 41 insertions(+) create mode 100644 working/retro-stereo-widgets/references/2026-07-12-thumb-slide-attenuators.png 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', ``, 'a composed entry instrument. 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', + ``, + 'a lit column of numbers, a thumb tab. 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=''; (function(){const eq=$('eq');for(let b=0;b<11;b++){const band=document.createElement('span');band.className='band'; diff --git a/working/retro-stereo-widgets/references/2026-07-12-thumb-slide-attenuators.png b/working/retro-stereo-widgets/references/2026-07-12-thumb-slide-attenuators.png new file mode 100644 index 0000000..8cf2ea3 Binary files /dev/null and b/working/retro-stereo-widgets/references/2026-07-12-thumb-slide-attenuators.png differ -- cgit v1.2.3