aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html64
1 files changed, 64 insertions, 0 deletions
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}}
</style>
</head>
@@ -249,6 +287,19 @@ card(C,'08','Arm-to-fire',
card(C,'09','Lamp row',
`<div class="lrow"><span class="lamp gold"></span><span class="who"><b>WH-1000XM4</b></span><span class="what">tap to connect</span></div>`,
'<b>actionable list item.</b> The net/bt/sound row: lamp + name + status, click acts. The workhorse.');
+card(C,'24','Rotary selector',
+ `<span class="rotsel">
+ <span class="pos" style="left:14%;top:53%">4</span><span class="pos" style="left:28%;top:18%">6</span><span class="pos on" style="left:50%;top:7%">8</span><span class="pos" style="left:72%;top:18%">10</span><span class="pos" style="left:86%;top:53%">12</span>
+ <span class="knob" onclick="rotSel(this)"><span class="ind"></span></span>
+ </span>`,
+ '<b>pick one of N by position.</b> 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',
+ `<span class="tuner" id="tuner" onclick="tuneNext()">
+ <span class="tick" style="left:12px"></span><span class="tick" style="left:51px"></span><span class="tick" style="left:90px"></span><span class="tick" style="left:129px"></span><span class="tick" style="left:168px"></span>
+ <span class="mk" style="left:12px">4</span><span class="mk" style="left:51px">6</span><span class="mk on" style="left:90px">8</span><span class="mk" style="left:129px">10</span><span class="mk" style="left:168px">12</span>
+ <span class="ndl" id="tundl" style="left:90px"></span>
+ </span>`,
+ '<b>value on a printed scale.</b> 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',
`<span class="toastw">joined @Hyatt_WiFi — saved</span>`,
'<b>transient confirmation.</b> The one-line result after an action. Auto-dismiss; red variant for errors.');
+card(I,'26','Nixie tube',
+ `<span class="nixie"><span class="tube off"><b>0</b></span><span class="tube"><b>8</b></span></span>`,
+ '<b>a single warm-glowing numeral.</b> 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',
+ `<span class="magiceye"><span class="fan"></span></span>`,
+ '<b>the glowing tuning eye.</b> 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='<i></i><i></i><i></i><i></i>';
$('kind').style.transform=`rotate(${kang-150}deg)`;