From d12f9b3041ae962411ddd84f6fad87090aa13faf Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 11 Jul 2026 13:40:10 -0500 Subject: feat(gallery): add rotary selector, slide-rule dial, and tube readouts Bring the hi-fi selector and vacuum-tube idioms from the Takuzu design pass into the panel widget kit: a rotary selector, a slide-rule tuner dial, a nixie tube, and a magic-eye tube. --- .../2026-07-03-panel-widget-gallery-prototype.html | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html') diff --git a/docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html b/docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html index 8e642f4..19323bf 100644 --- a/docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html +++ b/docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html @@ -182,6 +182,44 @@ h2::after{content:"";height:1px;background:var(--wash);flex:1} .ostep .lamp{margin-top:3px;width:7px;height:7px} .ostep b{color:var(--cream);font-weight:700}.ostep .ev{color:var(--steel);display:block;font-size:10.5px} +/* ---- hi-fi selectors & tubes (added from the takuzu design pass) ---- */ +/* rotary selector: knob + printed detent positions, pointer names the value */ +.rotsel{position:relative;width:118px;height:74px} +.rotsel>.knob{position:absolute;left:50%;top:20px;margin-left:-26px} +.rotsel .pos{position:absolute;font-size:9px;color:var(--dim);transform:translate(-50%,-50%);letter-spacing:.02em} +.rotsel .pos.on{color:var(--gold-hi);text-shadow:0 0 6px rgba(255,215,95,.55)} + +/* slide-rule tuner dial: printed scale + lit pointer over a warm backlight */ +.tuner{width:180px;height:46px;position:relative;border-radius:6px;overflow:hidden;cursor:pointer; + background:linear-gradient(180deg,#191510,#0b0908);border:1px solid #2a251c; + box-shadow:inset 0 0 20px rgba(218,181,61,.12),inset 0 1px 0 rgba(255,255,255,.03)} +.tuner .tick{position:absolute;top:6px;width:1px;height:11px;background:var(--steel);transform:translateX(-50%)} +.tuner .mk{position:absolute;bottom:8px;transform:translateX(-50%);color:var(--steel);font-size:10px} +.tuner .mk.on{color:var(--gold-hi);text-shadow:0 0 6px rgba(255,215,95,.6)} +.tuner .ndl{position:absolute;top:3px;bottom:3px;width:2px;margin-left:-1px;border-radius:1px; + background:var(--fail);box-shadow:0 0 7px rgba(203,107,77,.85);transition:left .25s} + +/* nixie / VFD tube numeral: one warm-glowing digit per tube, no matrix */ +.nixie{display:inline-flex;gap:5px} +.nixie .tube{width:30px;height:44px;border-radius:5px;position:relative;overflow:hidden; + background:radial-gradient(circle at 50% 38%,#241a12,#0b0807);border:1px solid #2c261d; + display:grid;place-items:center;box-shadow:inset 0 0 12px rgba(0,0,0,.6)} +.nixie .tube b{font-size:26px;font-weight:400;color:#ff9a3c; + text-shadow:0 0 6px rgba(255,140,50,.85),0 0 15px rgba(255,120,40,.45)} +.nixie .tube.off b{color:#3a2a1c;text-shadow:none} +.nixie .tube::after{content:"";position:absolute;inset:0;pointer-events:none; + background:linear-gradient(180deg,rgba(255,255,255,.06),transparent 32%)} + +/* magic-eye tuning tube: green phosphor with a closing shadow wedge */ +.magiceye{width:52px;height:52px;border-radius:50%;position:relative;overflow:hidden; + background:radial-gradient(circle,#08160a 55%,#040c05);border:1px solid #1b2c1b; + box-shadow:inset 0 0 14px rgba(0,0,0,.7)} +.magiceye .fan{position:absolute;inset:5px;border-radius:50%; + background:conic-gradient(from 140deg,#0c1e0c 0 var(--gap,64deg),#6fce33 0 360deg); + box-shadow:0 0 12px rgba(111,206,51,.4)} +.magiceye::after{content:"";position:absolute;left:50%;top:50%;width:9px;height:9px;margin:-4.5px; + border-radius:50%;background:#08160a;box-shadow:0 0 3px rgba(0,0,0,.6)} + @media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}} @@ -249,6 +287,19 @@ card(C,'08','Arm-to-fire', card(C,'09','Lamp row', `
WH-1000XM4tap to connect
`, 'actionable list item. The net/bt/sound row: lamp + name + status, click acts. The workhorse.'); +card(C,'24','Rotary selector', + ` + 4681012 + + `, + 'pick one of N by position. The source/speaker selector — printed detents, the pointer names the value. Read from where it points, not from a lit cell. Ideal for board size or grade. Click to turn.'); +card(C,'25','Slide-rule dial', + ` + + 4681012 + + `, + 'value on a printed scale. The illuminated tuner face — a lit pointer glides a warm-backlit strip of marks. Unmistakably hi-fi; great for board size. Click to step.'); /* ============ METERS & GAUGES ============ */ const M=$('meters'); @@ -302,12 +353,25 @@ card(I,'22','Output well', card(I,'23','Toast / status line', `joined @Hyatt_WiFi — saved`, 'transient confirmation. The one-line result after an action. Auto-dismiss; red variant for errors.'); +card(I,'26','Nixie tube', + `08`, + 'a single warm-glowing numeral. The nixie/VFD readout — one lit digit per tube, leading zeros dark, no matrix of cells. For a count that should feel analog: board size, a channel number.'); +card(I,'27','Magic-eye tube', + ``, + 'the glowing tuning eye. A phosphor-green tube whose dark wedge narrows as a value peaks — signal lock, level, how close to solved. Pure nostalgia; a soft alternative to the ring.'); /* ---- live animation ---- */ let ph=0, kang=140; function bumpKnob(){ kang=(kang+35)%300-0; $('kind').style.transform=`rotate(${kang-150}deg)`; } function armFire(){ const a=$('arm'); if(a.classList.contains('armed')){a.classList.remove('armed');a.textContent='forget';} else{a.classList.add('armed');a.textContent='forget? again';} } +let rotIdx=2; const rotAng=[-70,-35,0,35,70]; +function rotSel(knob){ const poss=knob.parentElement.querySelectorAll('.pos'); + rotIdx=(rotIdx+1)%5; knob.querySelector('.ind').style.transform=`rotate(${rotAng[rotIdx]}deg)`; + poss.forEach((p,i)=>p.classList.toggle('on',i===rotIdx)); } +let tunIdx=2; const tunX=[12,51,90,129,168]; +function tuneNext(){ const mks=$('tuner').querySelectorAll('.mk'); tunIdx=(tunIdx+1)%5; + $('tundl').style.left=tunX[tunIdx]+'px'; mks.forEach((m,i)=>m.classList.toggle('on',i===tunIdx)); } buildBars($('vuL'),16); buildBars($('vuR'),16); buildBars($('mini'),0); $('mini').innerHTML=''; $('kind').style.transform=`rotate(${kang-150}deg)`; -- cgit v1.2.3