From 651ba1e2138bb2643b12d6a3bb7f693f1785c134 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 12 Jul 2026 22:52:27 -0500 Subject: refactor(gallery): move widget CSS into GW_CSS in widgets.js Widget-internal rules and the pulse/flipdrop keyframes now inject via ensureCss, so widgets.js consumers get styling without the gallery stylesheet. The page-side reelspin injector became a plain GW_CSS rule. The gallery keeps page furniture, option-chip capsules, tokens, and the reduced-motion guard. --- docs/prototypes/panel-widget-gallery.html | 501 ----------------------------- docs/prototypes/widgets.js | 504 +++++++++++++++++++++++++++++- 2 files changed, 503 insertions(+), 502 deletions(-) (limited to 'docs') diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index 2eae646..2f703e8 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -136,321 +136,6 @@ h2::after{content:"";height:1px;background:var(--wash);flex:1} .card a.xref:hover{color:var(--gold-hi);border-color:var(--gold-hi)} .card:target{border-color:var(--gold);box-shadow:inset 0 1px 0 rgba(255,255,255,.04),0 0 0 1px var(--gold),0 6px 14px rgba(0,0,0,.4)} -/* ---- shared primitives ---- */ -.lamp{width:9px;height:9px;border-radius:50%;background:var(--pass);box-shadow:0 0 6px 1px rgba(116,147,47,.55)} -.lamp.gold{background:var(--gold);box-shadow:0 0 6px 1px rgba(var(--glow-lo),.6)} -.lamp.red{background:var(--fail);box-shadow:0 0 6px 1px rgba(203,107,77,.55)} -.lamp.off{background:var(--wash);box-shadow:none} -.lamp.busy{background:var(--gold);animation:pulse var(--pulse-rate) ease-in-out infinite} -/* standard pulse: 1s ease-in-out — the norm for every pulsing / flashing element */ -@keyframes pulse{50%{opacity:.25}} - -/* slide toggle — after the iPod-hold-switch pill: dome thumb, revealed state engraving. - Flex layout with fixed px only: absolute insets and stretched widths misrender under stage zoom. */ -.switch{display:inline-flex;vertical-align:middle;align-items:center;justify-content:space-between; - width:52px;height:23px;border-radius:12px;padding:2px 7px 2px 2px;cursor:pointer; - background:var(--sw-off-bg,linear-gradient(180deg,#15130f,#242019)); - border:1px solid var(--sw-off-brd,var(--slate)); - box-shadow:inset 0 1.5px 3px rgba(0,0,0,.55)} -.switch::before{content:"OFF";order:2;font-size:7px;letter-spacing:.06em;font-weight:700; - font-family:var(--mono);color:var(--sw-off-ink,var(--cream))} -.switch::after{content:"";order:1;width:17px;height:17px;border-radius:50%; - background:var(--sw-thumb,radial-gradient(circle at 35% 28%,#f6f2e8,#b0aa9a)); - box-shadow:0 1px 2.5px rgba(0,0,0,.65),inset 0 1px 0 rgba(255,255,255,.25)} -.switch.on{background:var(--sw-on-bg,linear-gradient(180deg,var(--amber-grad-top),var(--gold))); - border-color:var(--sw-on-brd,var(--gold-hi)); - padding:2px 2px 2px 7px;box-shadow:inset 0 1.5px 3px rgba(0,0,0,.3)} -.switch.on::before{content:"ON";order:1;color:var(--sw-on-ink,var(--panel))} -.switch.on::after{order:2} -.switch.red{background:linear-gradient(180deg,#d98a6f,var(--fail));border-color:var(--fail);padding:2px 2px 2px 7px} -.switch.red::before{content:"OFF";order:1;color:var(--cream)} -.switch.red::after{order:2} - -.key{font:inherit;font-size:11.5px;letter-spacing:.06em;color:var(--silver);cursor:pointer; - background:linear-gradient(180deg,#23211e,#191715);border:1px solid #33302b;border-bottom-color:#0c0b0a; - border-radius:8px;padding:8px 12px;box-shadow:inset 0 1px 0 rgba(255,255,255,.04),0 2px 3px rgba(0,0,0,.4)} -.key:hover{color:var(--gold);border-color:var(--gold)} -.key:active{transform:translateY(1px)} -.key.on{color:var(--panel);background:linear-gradient(180deg,var(--amber-grad-top),var(--gold));border-color:var(--gold-hi);font-weight:700} -.key.red{color:var(--cream);background:linear-gradient(180deg,#d98a6f,var(--fail));border-color:var(--fail)} -.key.off{opacity:.4} - -.chip{color:var(--dim);cursor:pointer;border-bottom:1px dotted var(--wash);font-size:12px} -.chip.on{color:var(--gold);border-color:var(--gold)} - -.badge{font-size:.62rem;letter-spacing:.18em;color:var(--panel);background:var(--gold);border-radius:4px;padding:1px 6px} -.badge.red{background:var(--fail);color:var(--cream)} -.badge.ghost{background:transparent;border:1px solid var(--slate);color:var(--silver)} - -/* fader */ -.fader{width:150px;height:16px;position:relative;cursor:pointer;touch-action:none} -.fader .slot{position:absolute;top:6px;left:0;right:0;height:4px;border-radius:2px;background:#0d0f10;border:1px solid #231f18;overflow:hidden} -.fader .fill{position:absolute;top:0;left:0;bottom:0;background:linear-gradient(90deg,var(--amber-grad-bot),var(--gold))} -.fader .cap{position:absolute;top:1px;width:7px;height:14px;border-radius:2px;margin-left:-3.5px; - background:linear-gradient(180deg,var(--amber-grad-top),var(--amber-grad-mid));border:1px solid var(--amber-edge);box-shadow:0 1px 2px rgba(0,0,0,.5)} -/* vertical fader */ -.vfader{width:16px;height:64px;position:relative;cursor:pointer;touch-action:none} -.vfader .slot{position:absolute;left:6px;top:0;bottom:0;width:4px;border-radius:2px;background:#0d0f10;border:1px solid #231f18;overflow:hidden} -.vfader .fill{position:absolute;left:0;right:0;bottom:0;background:linear-gradient(0deg,var(--amber-grad-bot),var(--gold))} -.vfader .cap{position:absolute;left:1px;height:7px;width:14px;border-radius:2px;margin-top:-3.5px; - background:linear-gradient(90deg,var(--amber-grad-mid),var(--amber-grad-top));border:1px solid var(--amber-edge)} - -/* rotary knob */ -.knob{width:52px;height:52px;border-radius:50%;position:relative;cursor:ns-resize;touch-action:none; - background:radial-gradient(circle at 40% 35%,#2a2622,#141210);border:1px solid #3a352c; - box-shadow:inset 0 2px 3px rgba(255,255,255,.05),0 3px 6px rgba(0,0,0,.5)} -.knob .ind{position:absolute;left:50%;top:5px;width:2px;height:16px;background:var(--gold-hi); - margin-left:-1px;transform-origin:50% 21px;border-radius:1px;box-shadow:0 0 5px rgba(var(--glow-hi),.6)} - -/* needle gauge */ -.gauge{width:96px;cursor:ns-resize;touch-action:none} -.gauge .dial{position:relative;height:48px;overflow:hidden} -.gauge .arc{position:absolute;inset:0 0 -48px 0;border:2px solid var(--wash);border-radius:50%} -.gauge .tk{position:absolute;left:50%;top:1px;width:1.5px;height:8px;margin-left:-.75px;background:var(--steel);transform-origin:50% 47px} -.gauge .ndl{position:absolute;left:50%;bottom:0;width:2px;height:40px;background:var(--gold-hi); - transform-origin:50% 100%;transform:rotate(0deg);border-radius:2px;box-shadow:0 0 6px rgba(var(--glow-hi),.5); - transition:transform .12s cubic-bezier(.3,1.3,.5,1)} -.gauge .hub{position:absolute;left:50%;bottom:-4px;width:8px;height:8px;margin-left:-4px;border-radius:50%;background:var(--gold)} -.gauge .gv{color:var(--cream);text-align:center;font-size:12px;font-weight:700;margin-top:5px;font-variant-numeric:tabular-nums} - -/* segmented VU / LED bar */ -.vu{width:170px;display:flex;flex-direction:column;gap:5px} -.vurow{display:flex;align-items:center;gap:7px} -.vurow .ch{color:var(--steel);font-size:.6rem;width:8px} -.vubar{flex:1;display:flex;gap:2px;height:9px} -.vubar i{flex:1;background:var(--wash);border-radius:1px;opacity:.3} -.vubar i.on{opacity:1;background:var(--pass)}.vubar i.hot{opacity:1;background:var(--gold)} -.vubar i.clip{opacity:1;background:var(--fail)}.vubar i.peak{outline:1px solid var(--gold-hi);outline-offset:-1px} - -/* mini 4-bar signal */ -.sig{display:flex;align-items:flex-end;gap:2px;height:18px} -.sig i{width:4px;background:var(--wash);border-radius:1px} -.sig i:nth-child(1){height:5px}.sig i:nth-child(2){height:9px}.sig i:nth-child(3){height:13px}.sig i:nth-child(4){height:17px} -.sig i.on{background:var(--pass)}.sig i.hot{background:var(--gold)}.sig i.clip{background:var(--fail)} - -/* signal ladder (wifi bars) */ -.ladder{display:inline-flex;gap:3px;align-items:flex-end;height:18px;cursor:pointer} -.ladder i{width:5px;background:var(--wash);border-radius:1px} -.ladder i:nth-child(1){height:6px}.ladder i:nth-child(2){height:10px} -.ladder i:nth-child(3){height:14px}.ladder i:nth-child(4){height:18px} - -/* linear progress / fuel bar */ -.bar{width:160px;height:12px;background:#0d0f10;border:1px solid #231f18;border-radius:6px;overflow:hidden;position:relative;cursor:pointer;touch-action:none} -.bar>span{position:absolute;left:0;top:0;bottom:0;background:linear-gradient(90deg,var(--amber-grad-bot),var(--gold));border-radius:6px} -.bar.warn>span{background:linear-gradient(90deg,#a35a3f,var(--fail))} - -/* radial ring */ -.ring{width:60px;height:60px;border-radius:50%;cursor:ns-resize;touch-action:none; - background:conic-gradient(var(--gold) calc(var(--p)*1%),var(--wash) 0); - display:grid;place-items:center;position:relative} -.ring::before{content:"";position:absolute;inset:6px;border-radius:50%;background:var(--well)} -.ring b{position:relative;color:var(--cream);font-size:12px;font-weight:700;font-variant-numeric:tabular-nums} - -/* tabular readout */ -.readout{color:var(--cream);font-size:24px;font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:.04em;cursor:pointer} -.readout small{color:var(--dim);font-size:12px;font-weight:400} -.readout .u{color:var(--steel);font-size:.6rem;letter-spacing:.2em;display:block;text-align:center;margin-top:2px} - -/* sparkline */ -.spark{width:170px;height:44px} -.spark svg{display:block;width:100%;height:100%} - -/* lamp row (list item) */ -.lrow{width:190px;display:flex;align-items:center;gap:9px;padding:6px 8px;border-radius:7px;background:#141210;cursor:pointer;font-size:12.5px} -.lrow:hover{background:var(--wash)} -.lrow .who{color:var(--silver)}.lrow .who b{color:var(--cream)} -.lrow .what{margin-left:auto;color:var(--dim);font-size:11px} - -/* arm-to-fire */ -.arm{font:inherit;font-size:11.5px;color:var(--silver);cursor:pointer;background:#191715;border:1px solid #33302b; - border-radius:8px;padding:7px 12px} -.arm.armed{background:rgba(203,107,77,.12);border-color:var(--fail);color:var(--fail)} - -/* stepper / segmented selector */ -.seg{display:flex;border:1px solid #33302b;border-radius:8px;overflow:hidden} -.seg button{font:inherit;font-size:11px;color:var(--silver);background:#191715;border:0;border-right:1px solid #33302b;padding:7px 11px;cursor:pointer} -.seg button:last-child{border-right:0} -.seg button.on{background:linear-gradient(180deg,var(--amber-grad-top),var(--gold));color:var(--panel);font-weight:700} - -/* engraved section label */ -.engrave{width:180px;color:var(--steel);font-size:.62rem;letter-spacing:.3em;text-transform:uppercase;cursor:pointer; - display:flex;align-items:center;gap:9px} -.engrave::before,.engrave::after{content:"";height:1px;background:var(--wash);flex:1} -.engrave::before{max-width:10px} -.engrave .cnt{color:var(--dim);letter-spacing:.1em;text-transform:none} - -/* waveform strip */ -.wave{width:170px;height:38px} -.wave svg{width:100%;height:100%;display:block} - -/* toast */ -.toastw{font-size:11px;color:var(--cream);background:var(--slate);border-radius:7px;padding:5px 10px;cursor:pointer} - -/* output well (log step) */ -.owell{width:200px;background:var(--well);border:1px solid var(--wash);border-radius:8px;padding:7px 9px;font-size:11px;cursor:pointer} -.ostep{display:flex;gap:7px;align-items:flex-start;padding:2px 0} -.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} - -/* rotary selector */ -.rotsel{position:relative;width:118px;height:74px} -.rotsel>.knob{position:absolute;left:50%;top:20px;margin-left:-26px;cursor:pointer} -.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(var(--glow-hi),.55)} - -/* slide-rule tuner dial */ -.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(var(--glow-lo),.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(var(--glow-hi),.6)} -.tuner:focus-visible{outline:2px solid var(--gold);outline-offset:2px} -.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 tube */ -.nixie{display:inline-flex;gap:5px;cursor:pointer} -.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%)} - -/* ===== candidate-unique CSS ===== */ -/* rocker */ -.rocker{width:66px;height:40px;border-radius:7px;cursor:pointer;position:relative; - background:linear-gradient(180deg,#25211c,#141210);border:1px solid #34302a; - box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 3px 6px rgba(0,0,0,.5);overflow:hidden} -.rocker .half{position:absolute;left:0;right:0;height:50%;display:flex;align-items:center;justify-content:center; - font-size:12px;letter-spacing:.06em;color:var(--dim)} -.rocker .top{top:0;border-bottom:1px solid #0c0b0a;background:linear-gradient(180deg,#211d19,#181513)} -.rocker .bot{bottom:0;background:linear-gradient(180deg,#141210,#100e0c);box-shadow:inset 0 3px 5px rgba(0,0,0,.55)} -.rocker.on .top{background:linear-gradient(180deg,var(--amber-grad-top),var(--gold));color:var(--panel);font-weight:700;box-shadow:0 0 10px rgba(var(--glow-hi),.35)} -.rocker.on .bot{color:var(--steel)} -.rocker:not(.on) .top{color:var(--steel)} -.rocker:not(.on) .bot{background:linear-gradient(180deg,#2a1512,#1c0f0d);color:var(--fail);box-shadow:inset 0 3px 5px rgba(0,0,0,.55),0 0 8px rgba(203,107,77,.25)} - -/* transport */ -.reels{display:flex;gap:16px;align-items:center;justify-content:center;margin-bottom:2px} -.reel{width:26px;height:26px;border-radius:50%;border:2px solid #34302a;position:relative; - background:radial-gradient(circle at 45% 40%,#211d18,#0d0b09)} -.reel::before{content:"";position:absolute;inset:9px;border-radius:50%;border:1px solid #4a443a;background:#161310} -.reel i{position:absolute;left:50%;top:50%;width:2px;height:11px;background:var(--steel);margin:-5.5px 0 0 -1px;transform-origin:50% 5.5px} -.reel i:nth-child(1){background:var(--gold-hi);box-shadow:0 0 4px rgba(var(--glow-hi),.55)} -.reel i:nth-child(2){transform:rotate(120deg)}.reel i:nth-child(3){transform:rotate(240deg)} -.transport{display:flex;gap:5px} -.tbtn{font:inherit;font-size:12px;color:var(--silver);cursor:pointer;width:30px;height:26px;display:grid;place-items:center; - background:linear-gradient(180deg,#23211e,#191715);border:1px solid #33302b;border-bottom-color:#0c0b0a;border-radius:6px} -.tbtn:hover{color:var(--gold);border-color:var(--gold)} -.tbtn.on{color:var(--panel);background:linear-gradient(180deg,var(--amber-grad-top),var(--gold));border-color:var(--gold-hi)} -.tbtn.rec.on{color:var(--cream);background:linear-gradient(180deg,#d98a6f,var(--fail));border-color:var(--fail)} - -/* radio bank */ -.radiobank{display:flex;gap:0;border:1px solid #0c0b0a;border-radius:7px;overflow:hidden; - background:#0c0b0a;padding:3px;box-shadow:inset 0 2px 4px rgba(0,0,0,.5)} -.preset{font:inherit;font-size:11px;color:var(--dim);cursor:pointer;padding:8px 9px;border:0;border-radius:4px; - background:linear-gradient(180deg,#211d19,#161310);box-shadow:inset 0 1px 0 rgba(255,255,255,.04)} -.preset+.preset{margin-left:3px} -.preset:hover{color:var(--silver)} -.preset.on{color:var(--panel);background:linear-gradient(180deg,var(--amber-grad-top),var(--gold));font-weight:700; - box-shadow:inset 0 2px 4px rgba(0,0,0,.4)} - -/* concentric dual knob */ -.dualknob{width:64px;height:64px;position:relative} -.dualknob .outer{width:64px;height:64px;border-radius:50%;position:absolute;inset:0;cursor:ns-resize;touch-action:none; - background:radial-gradient(circle at 40% 35%,#2a2622,#100e0c);border:1px solid #3a352c; - box-shadow:inset 0 2px 3px rgba(255,255,255,.05),0 3px 6px rgba(0,0,0,.5)} -.dualknob .outer .tick{position:absolute;left:50%;top:3px;width:2px;height:9px;background:var(--steel);margin-left:-1px;transform-origin:50% 29px} -.dualknob .inner{width:34px;height:34px;border-radius:50%;position:absolute;left:15px;top:15px;cursor:ns-resize;touch-action:none; - background:radial-gradient(circle at 40% 35%,#37322a,#1a1713);border:1px solid #4a443a;box-shadow:0 2px 4px rgba(0,0,0,.5)} -.dualknob .inner .ind{position:absolute;left:50%;top:3px;width:2px;height:11px;background:var(--gold-hi);margin-left:-1px; - transform-origin:50% 14px;border-radius:1px;box-shadow:0 0 5px rgba(var(--glow-hi),.6)} - -/* rotary encoder + LED ring */ -.encoder{position:relative;width:66px;height:66px;display:grid;place-items:center;cursor:ns-resize;touch-action:none} -.encoder .led{position:absolute;width:5px;height:5px;border-radius:50%;background:var(--wash); - left:50%;top:50%;margin:-2.5px} -.encoder .led.on{background:var(--gold);box-shadow:0 0 5px 1px rgba(var(--glow-lo),.7)} -.encoder .knob{width:40px;height:40px;cursor:ns-resize} -.encoder .knob .ind{transform-origin:50% 15px;top:4px;height:12px} - -/* keyed mode switch */ -.keylock{position:relative;width:110px;height:70px} -.keylock .body{position:absolute;left:50%;top:30px;margin-left:-21px;width:42px;height:42px;border-radius:50%; - background:radial-gradient(circle at 42% 36%,#2a2622,#0f0d0b);border:1px solid #3a352c;cursor:pointer; - box-shadow:inset 0 2px 3px rgba(255,255,255,.05),0 3px 6px rgba(0,0,0,.5)} -.keylock .barrel{position:absolute;left:50%;top:50%;width:5px;height:5px;margin:-2.5px;border-radius:1px;background:#0a0908; - box-shadow:0 0 2px rgba(0,0,0,.8)} -.keylock .bit{position:absolute;left:50%;top:50%;width:3px;height:15px;margin:-15px 0 0 -1.5px;background:var(--gold-hi); - border-radius:1px;transform-origin:50% 100%;box-shadow:0 0 5px rgba(var(--glow-hi),.55);transition:transform .2s} -.keylock .kpos{position:absolute;font-size:9px;color:var(--dim);letter-spacing:.05em;transform:translate(-50%,-50%)} -.keylock .kpos.on{color:var(--gold-hi);text-shadow:0 0 6px rgba(var(--glow-hi),.55)} - -/* crossfader */ -.xfader{width:160px;height:22px;position:relative;cursor:pointer;touch-action:none} -.xfader .slot{position:absolute;top:9px;left:0;right:0;height:4px;border-radius:2px;background:#0d0f10;border:1px solid #231f18} -.xfader .detent{position:absolute;top:2px;left:50%;width:1px;height:18px;background:var(--steel);margin-left:-.5px;opacity:.7} -.xfader .end{position:absolute;top:11px;font-size:9px;color:var(--steel);transform:translateY(-50%)} -.xfader .cap{position:absolute;top:3px;width:9px;height:16px;border-radius:2px;margin-left:-4.5px;transition:left .05s; - background:linear-gradient(180deg,var(--amber-grad-top),var(--amber-grad-mid));border:1px solid var(--amber-edge);box-shadow:0 1px 2px rgba(0,0,0,.5)} - -/* thumbwheel */ -.thumbw{display:flex;align-items:center;gap:10px} -.thumbwheel{width:34px;height:52px;border-radius:6px;cursor:ns-resize;touch-action:none;position:relative;overflow:hidden; - border:1px solid #34302a;box-shadow:inset 0 0 8px rgba(0,0,0,.6); - background:repeating-linear-gradient(0deg,#0e0c0a 0 2px,#221e19 2px 3px,#2f2a23 3px 5px,#221e19 5px 6px)} -.thumbwheel::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(0,0,0,.55),transparent 30%,transparent 70%,rgba(0,0,0,.55))} -.thumbw .win{color:var(--cream);font-size:15px;font-weight:700;font-variant-numeric:tabular-nums; - background:var(--well);border:1px solid #231f18;border-radius:4px;padding:3px 8px} - -/* DIP bank */ -.dip{display:flex;gap:3px;padding:6px 7px;background:#0f1a2a;border:1px solid #24344a;border-radius:5px; - box-shadow:inset 0 1px 3px rgba(0,0,0,.5)} -.dipsw{width:12px;height:26px;background:#0a1220;border-radius:2px;position:relative;cursor:pointer;border:1px solid #1c2c42} -.dipsw i{position:absolute;left:1px;right:1px;height:11px;border-radius:1px;background:linear-gradient(180deg,#eae4d2,#b4ad98); - bottom:1px;transition:bottom .12s,top .12s} -.dipsw.on i{bottom:auto;top:1px;background:linear-gradient(180deg,var(--amber-grad-top),var(--gold))} - -/* jog / shuttle */ -.jog{position:relative;width:74px;height:74px;cursor:ns-resize;touch-action:none} -.jog .shuttle{position:absolute;inset:0;border-radius:50%;border:6px solid #1a1713; - background:conic-gradient(from -90deg,#3a352c 0 var(--sh,40deg),#141210 0 360deg); - box-shadow:inset 0 0 8px rgba(0,0,0,.6)} -.jog .inner{position:absolute;inset:12px;border-radius:50%;transition:transform .05s linear; - background:radial-gradient(circle at 42% 36%,#2c2822,#100e0c);border:1px solid #3a352c;box-shadow:0 2px 5px rgba(0,0,0,.6)} -.jog .dimple{position:absolute;left:50%;top:7px;width:8px;height:8px;margin-left:-4px;border-radius:50%; - background:radial-gradient(circle at 40% 35%,#151210,#000);box-shadow:inset 0 1px 2px rgba(0,0,0,.9)} - -/* oscilloscope — screen-family vars with the original green as fallback */ -.scope{width:176px;height:78px;border-radius:6px;position:relative;overflow:hidden; - background:radial-gradient(circle at 50% 45%,var(--scr-bgc,#04140a),var(--scr-bge,#020a05)); - border:1px solid var(--scr-brd,#123018); - box-shadow:inset 0 0 16px rgba(0,0,0,.7)} -.scope .grat{position:absolute;inset:0;opacity:.5; - background-image:linear-gradient(var(--scr-grat,rgba(111,206,51,.18)) 1px,transparent 1px),linear-gradient(90deg,var(--scr-grat,rgba(111,206,51,.18)) 1px,transparent 1px); - background-size:22px 19.5px} -.scope .grat::after{content:"";position:absolute;left:0;right:0;top:50%;height:1px;background:var(--scr-gratc,rgba(111,206,51,.35))} -.scope svg{position:absolute;inset:0;width:100%;height:100%} -.scope polyline{fill:none;stroke:var(--scr-hi,var(--phos));stroke-width:1.6;filter:drop-shadow(0 0 3px var(--scr-glow,rgba(127,224,160,.8)))} - -/* voice-loop keyset */ -.vloop{display:grid;grid-template-columns:repeat(4,52px);gap:4px} -.vk{display:flex;flex-direction:column;align-items:stretch;gap:4px;font-size:7px;letter-spacing:.05em; - text-align:center;padding:6px 4px 4px;cursor:pointer; - color:var(--dim);background:linear-gradient(180deg,#23211e,#191715);border:1px solid #33302b;border-radius:4px; - font-family:var(--mono)} -.vk .bar{height:3px;width:40px;align-self:center;border-radius:2px;background:#16240f} -.vk.mon{color:var(--silver)} -.vk.mon .bar{background:var(--pass);box-shadow:0 0 4px rgba(116,147,47,.6)} -.vk.mon.act .bar{background:#a8d84a;box-shadow:0 0 7px rgba(150,200,60,.9)} -.vk.tlk{color:var(--panel);background:linear-gradient(180deg,var(--amber-grad-top),var(--gold)); - border-color:var(--gold-hi);font-weight:700} -.vk.tlk .bar{background:var(--pass);box-shadow:0 0 4px rgba(116,147,47,.6)} - /* option chips: each group is an encircled capsule (label + choices); groups flow with spacing */ .famchips{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:1px} .fgroup{display:inline-flex;align-items:center;gap:6px;padding:3px 9px 3px 8px; @@ -460,188 +145,6 @@ h2::after{content:"";height:1px;background:var(--wash);flex:1} border:1px solid rgba(255,255,255,.22);box-shadow:0 1px 3px rgba(0,0,0,.5)} .famchips .fc.on{outline:2px solid var(--silver);outline-offset:1px} -/* spectrum / EQ */ -.eq{display:flex;align-items:flex-end;gap:3px;height:60px} -.eq .band{width:9px;display:flex;flex-direction:column-reverse;gap:2px;height:100%} -.eq .band i{height:5px;border-radius:1px;background:var(--wash);opacity:.3} -.eq .band i.on{opacity:1;background:var(--pass)} -.eq .band i.hot{opacity:1;background:var(--gold)} -.eq .band i.clip{opacity:1;background:var(--fail)} - -/* crossed-needle */ -.crossm{width:120px} -.crossm .face{position:relative;height:56px;overflow:hidden;cursor:ns-resize;touch-action:none} -.crossm .arc{position:absolute;inset:2px 4px -56px;border:2px solid var(--wash);border-radius:50%} -.crossm .nA{position:absolute;left:14px;bottom:2px;width:2px;height:52px;background:var(--gold-hi);transform-origin:50% 100%; - border-radius:2px;box-shadow:0 0 5px rgba(var(--glow-hi),.5);transition:transform .12s cubic-bezier(.3,1.2,.5,1)} -.crossm .nB{position:absolute;right:14px;bottom:2px;width:2px;height:52px;background:var(--fail);transform-origin:50% 100%; - border-radius:2px;box-shadow:0 0 5px rgba(203,107,77,.5);transition:transform .12s cubic-bezier(.3,1.2,.5,1)} -.crossm .lbl{display:flex;justify-content:space-between;color:var(--steel);font-size:9px;margin-top:2px} - -/* thermometer */ -.thermo{display:flex;align-items:flex-end;gap:6px;height:74px;cursor:ns-resize;touch-action:none} -.thermo .tube{width:12px;height:64px;border-radius:6px 6px 0 0;position:relative;background:#0d0f10;border:1px solid #231f18;overflow:hidden} -.thermo .fill{position:absolute;left:0;right:0;bottom:0;background:linear-gradient(0deg,#a35a3f,var(--fail))} -.thermo .bulb{width:20px;height:20px;border-radius:50%;background:var(--fail);position:absolute;left:-4px;bottom:-9px; - box-shadow:0 0 6px rgba(203,107,77,.5)} -.thermo .scale{display:flex;flex-direction:column;justify-content:space-between;height:64px;font-size:9px;color:var(--steel)} -.thermo .wrapcol{position:relative;padding-bottom:9px} - -/* bourdon */ -.bourdon{width:82px;height:82px;border-radius:50%;position:relative;cursor:ns-resize;touch-action:none; - background:radial-gradient(circle at 48% 42%,#1d1a16,#0c0b09);border:2px solid #2c261d; - box-shadow:inset 0 2px 5px rgba(0,0,0,.6)} -.bourdon svg{position:absolute;inset:0} -.bourdon .ndl{position:absolute;left:50%;top:50%;width:2px;height:32px;margin:-32px 0 0 -1px;background:var(--gold-hi); - transform-origin:50% 100%;border-radius:2px;box-shadow:0 0 5px rgba(var(--glow-hi),.55);transition:transform .12s cubic-bezier(.3,1.2,.5,1)} -.bourdon .hub{position:absolute;left:50%;top:50%;width:8px;height:8px;margin:-4px;border-radius:50%;background:var(--gold)} -.bourdon .cap{position:absolute;left:0;right:0;bottom:12px;text-align:center;font-size:8px;letter-spacing:.16em;color:var(--steel)} - -/* strip-chart */ -.strip{width:176px;height:62px;border-radius:5px;position:relative;overflow:hidden; - background:#0c0e0f;border:1px solid #231f18} -.strip .rule{position:absolute;inset:0;opacity:.4; - background-image:linear-gradient(90deg,rgba(150,147,133,.14) 1px,transparent 1px);background-size:16px 100%} -.strip svg{position:absolute;inset:0;width:100%;height:100%} -.strip polyline{fill:none;stroke:var(--gold);stroke-width:1.4} -.strip .pen{position:absolute;right:2px;width:6px;height:6px;margin:-3px;border-radius:50%;background:var(--gold-hi); - box-shadow:0 0 6px rgba(var(--glow-hi),.8);transition:top .08s linear} - -/* correlation */ -.corr{width:150px;cursor:pointer;touch-action:none} -.corr .face{position:relative;height:44px;overflow:hidden} -.corr .arc{position:absolute;inset:0 0 -44px;border:2px solid var(--wash);border-radius:50%} -.corr .zero{position:absolute;left:50%;top:2px;width:1px;height:10px;background:var(--gold);margin-left:-.5px} -.corr .ndl{position:absolute;left:50%;bottom:0;width:2px;height:38px;background:var(--gold-hi);transform-origin:50% 100%; - border-radius:2px;box-shadow:0 0 5px rgba(var(--glow-hi),.5);transition:transform .1s ease-out} -.corr .lbl{display:flex;justify-content:space-between;color:var(--steel);font-size:9px;margin-top:2px} - -/* battery */ -.batt{display:flex;align-items:center;cursor:pointer;touch-action:none} -.batt .cells{display:flex;gap:2px;padding:3px;border:1px solid #34302a;border-radius:4px;background:#0d0f10} -.batt .cell{width:12px;height:26px;border-radius:1px;background:var(--wash);opacity:.35} -.batt .cell.on{opacity:1;background:linear-gradient(180deg,var(--pass),#5c7526)} -.batt .cell.warn.on{background:linear-gradient(180deg,var(--fail),#a04a34)} -.batt .nub{width:4px;height:12px;background:#34302a;border-radius:0 2px 2px 0} - -/* split-flap */ -.flap{display:inline-flex;gap:4px;cursor:pointer} -.flapd{width:30px;height:42px;border-radius:5px;position:relative;overflow:hidden; - background:linear-gradient(180deg,#211d18,#141210);border:1px solid #34302a;box-shadow:0 2px 4px rgba(0,0,0,.5)} -.flapd b{position:absolute;inset:0;display:grid;place-items:center;font-size:24px;color:var(--cream); - text-shadow:0 1px 2px rgba(0,0,0,.7)} -.flapd::after{content:"";position:absolute;left:0;right:0;top:50%;height:1px;background:rgba(0,0,0,.65);box-shadow:0 1px 0 rgba(255,255,255,.03)} -.flapd.flip b{animation:flipdrop .3s ease-in} -@keyframes flipdrop{0%{transform:translateY(-42%) scaleY(.4);opacity:.3}100%{transform:none;opacity:1}} - -/* seven-segment */ -.seven{display:inline-flex;gap:6px;padding:6px 9px;border-radius:6px;background:#0a0806;border:1px solid #231f18;cursor:pointer; - box-shadow:inset 0 0 10px rgba(0,0,0,.6)} -.seg7{width:22px;height:40px;filter:drop-shadow(0 0 3px rgba(87,211,87,.55))} -.seg7.red{filter:drop-shadow(0 0 3px rgba(226,84,63,.55))} -.seven .colon{align-self:center;display:flex;flex-direction:column;gap:9px} -.seven .colon i{width:4px;height:4px;border-radius:50%;background:var(--sevgrn);box-shadow:0 0 4px rgba(87,211,87,.7)} - -/* DSKY verb/noun panel */ -.dsky{display:flex;gap:9px;align-items:stretch;background:#1c1916;border:1px solid #060505;border-radius:8px;padding:8px} -.dsky .lampcol{display:grid;grid-template-rows:repeat(6,1fr);gap:3px;width:52px} -.dsky .sl{font-size:6.5px;letter-spacing:.04em;display:flex;align-items:center;justify-content:center;text-align:center; - background:#141210;color:#5c574c;border-radius:2px;border:1px solid #26221c} -.dsky .sl.on{background:linear-gradient(180deg,var(--amber-warn),var(--gold));color:var(--panel);font-weight:700; - box-shadow:0 0 6px rgba(var(--glow-lo),.5)} -.dsky .right{display:flex;flex-direction:column;gap:6px} -.dsky .wins{display:flex;gap:8px} -.dsky .win{display:flex;flex-direction:column;align-items:center;gap:2px} -.dsky .win .wl{font-size:6px;letter-spacing:.14em;color:var(--steel)} -.dsky .win .wd{display:flex;gap:2px;background:#0a0806;border:1px solid #231f18;border-radius:4px;padding:3px 4px} -.dsky .win .wd .seg7{width:13px;height:24px} -.dsky .win.hot .wd{border-color:var(--gold);box-shadow:0 0 5px rgba(var(--glow-lo),.4)} -.dsky .pad{display:grid;grid-template-columns:repeat(5,1fr);gap:4px} -.dsky .pad .key{padding:4px 0;font-size:8.5px;border-radius:5px;text-align:center;letter-spacing:.03em} - -/* VFD marquee */ -.vfdm{width:176px;height:34px;border-radius:5px;overflow:hidden;position:relative;cursor:pointer; - background:linear-gradient(180deg,#04100e,#020807);border:1px solid #123028;box-shadow:inset 0 0 12px rgba(0,0,0,.6)} -.vfdm .txt{position:absolute;top:50%;transform:translateY(-50%);white-space:nowrap;font-size:15px;letter-spacing:.22em; - color:var(--vfd);text-shadow:0 0 6px rgba(99,230,200,.65)} -.vfdm .mesh{position:absolute;inset:0;pointer-events:none;opacity:.35; - background-image:radial-gradient(rgba(0,0,0,.6) 40%,transparent 41%);background-size:3px 3px} - -/* annunciator */ -.annwrap{display:flex;flex-direction:column;gap:6px} -.annbar{display:flex;gap:5px;align-items:center} -.mc{font-size:7px;letter-spacing:.08em;padding:4px 8px;border-radius:3px;background:#141210;color:#5c574c; - border:1px solid #26221c;text-align:center} -.mc.on{background:linear-gradient(180deg,#d98a6f,var(--fail));color:var(--cream);font-weight:700; - box-shadow:0 0 8px rgba(203,107,77,.5)} -.mc.on.fl{animation:pulse var(--pulse-rate) ease-in-out infinite} -.annbar .key{padding:3px 7px;font-size:7.5px;border-radius:4px} -.annun{display:grid;grid-template-columns:repeat(3,1fr);gap:3px} -.acell{font-size:8.5px;letter-spacing:.08em;text-align:center;color:var(--dim);padding:6px 4px;border-radius:3px;cursor:pointer; - background:#141210;border:1px solid #262320;line-height:1.2} -.acell.warn{color:var(--panel);background:linear-gradient(180deg,var(--amber-warn),var(--gold));font-weight:700;box-shadow:0 0 8px rgba(var(--glow-lo),.4)} -.acell.fault{color:var(--cream);background:linear-gradient(180deg,#d98a6f,var(--fail));font-weight:700;box-shadow:0 0 8px rgba(203,107,77,.4);animation:pulse var(--pulse-rate) ease-in-out infinite} - -/* jewel */ -.jewel{width:24px;height:24px;border-radius:50%;position:relative;cursor:pointer; - background:radial-gradient(circle at 36% 30%,rgba(255,255,255,.75),var(--jc) 42%,#3a0d08 100%); - box-shadow:0 0 10px 1px var(--jc),inset 0 -2px 3px rgba(0,0,0,.5)} -.jewel::after{content:"";position:absolute;inset:0;border-radius:50%; - background:conic-gradient(from 0deg,rgba(255,255,255,.12) 0 22deg,transparent 22deg 45deg,rgba(0,0,0,.18) 45deg 67deg,transparent 67deg 90deg); - background-repeat:repeat} -.jewel.dim{background:radial-gradient(circle at 36% 30%,rgba(120,120,120,.3),#241f1b 55%,#0e0c0a);box-shadow:inset 0 -2px 3px rgba(0,0,0,.5)} - -/* tape counter */ -.counter{display:inline-flex;gap:2px;padding:4px;background:#0c0b0a;border:1px solid #2c261d;border-radius:4px; - box-shadow:inset 0 1px 3px rgba(0,0,0,.6)} -.cwheel{width:18px;height:34px;border-radius:2px;position:relative;overflow:hidden; - background:linear-gradient(180deg,#efe9d6,#c7c0ac);box-shadow:inset 0 0 3px rgba(0,0,0,.3)} -.cwheel .col{position:absolute;left:0;right:0;text-align:center;color:#1a1613;font-size:18px;font-weight:700;line-height:34px; - transition:top .35s cubic-bezier(.4,1.4,.5,1)} -.cwheel .col span{display:block;height:34px} -.cwheel::before,.cwheel::after{content:"";position:absolute;left:0;right:0;height:9px;z-index:2;pointer-events:none} -.cwheel::before{top:0;background:linear-gradient(180deg,rgba(0,0,0,.4),transparent)} -.cwheel::after{bottom:0;background:linear-gradient(0deg,rgba(0,0,0,.4),transparent)} -.counter .redw{background:linear-gradient(180deg,#e7b46a,#cf9440)} - -/* analog clock */ -.clock{width:78px;height:78px;border-radius:50%;position:relative; - background:radial-gradient(circle at 46% 40%,#1c1915,#0c0b09);border:2px solid #2c261d;box-shadow:inset 0 2px 5px rgba(0,0,0,.6)} -.clock .tk{position:absolute;left:50%;top:4px;width:1.5px;height:6px;background:var(--steel);margin-left:-.75px;transform-origin:50% 35px} -.clock .hh{position:absolute;left:50%;top:50%;width:3px;height:20px;margin:-20px 0 0 -1.5px;background:var(--cream); - transform-origin:50% 100%;border-radius:2px} -.clock .mh{position:absolute;left:50%;top:50%;width:2px;height:28px;margin:-28px 0 0 -1px;background:var(--silver); - transform-origin:50% 100%;border-radius:2px} -.clock .sh{position:absolute;left:50%;top:50%;width:1px;height:30px;margin:-30px 0 0 -.5px;background:var(--gold-hi); - transform-origin:50% 100%;box-shadow:0 0 4px rgba(var(--glow-hi),.5)} -.clock .pin{position:absolute;left:50%;top:50%;width:6px;height:6px;margin:-3px;border-radius:50%;background:var(--gold)} - -/* frequency-dial scale */ -.freqscale{width:184px;height:44px;position:relative;border-radius:5px;overflow:hidden;cursor:pointer;touch-action:none; - background:linear-gradient(180deg,#191510,#0b0908);border:1px solid #2a251c; - box-shadow:inset 0 0 16px rgba(var(--glow-lo),.1)} -.freqscale .tick{position:absolute;top:5px;width:1px;background:var(--steel);transform:translateX(-50%)} -.freqscale .mk{position:absolute;bottom:6px;transform:translateX(-50%);color:var(--steel);font-size:9px} -.freqscale .band{position:absolute;bottom:2px;left:6px;color:var(--gold);font-size:8px;letter-spacing:.18em} -.freqscale .fptr{position:absolute;top:3px;bottom:14px;width:2px;margin-left:-1px;border-radius:1px; - background:var(--fail);box-shadow:0 0 7px rgba(203,107,77,.85)} - -/* patch-bay */ -.patch{padding:7px 9px;background:#141210;border:1px solid #2c261d;border-radius:5px;position:relative} -.patch .row{display:flex;gap:9px} -.patch .row+.row{margin-top:9px} -.patch .jack{width:13px;height:13px;border-radius:50%;cursor:pointer;background:radial-gradient(circle at 40% 35%,#3a352c,#0a0908 70%); - border:1px solid #4a443a;box-shadow:inset 0 1px 2px rgba(0,0,0,.8)} -.patch .jack.hot{background:radial-gradient(circle at 40% 35%,var(--amber-edge),#1a1408 70%)} -.patch .jack.sel{border-color:var(--gold-hi);box-shadow:0 0 6px 1px rgba(var(--glow-hi),.7)} -.patch svg{position:absolute;inset:0;pointer-events:none;width:100%;height:100%} -.patch svg path{fill:none;stroke:var(--gold);stroke-width:2.4;opacity:.85;stroke-linecap:round} - -/* ===== reference-batch (R) widgets — SVG-first, after period hardware ===== */ -.rsvg{display:block} -.rsvg.drag{cursor:ns-resize;touch-action:none} -.rsvg.press{cursor:pointer} - @media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}} @@ -1962,10 +1465,6 @@ function tickT(){$('card-20').gw.tick();} function tickVfd(){IH.vfd.tick();} function tickCounter(){IH.counter.set(IH.counter.get()+137);} -/* reels spin keyframe */ -(function(){const st=document.createElement('style');st.textContent='@keyframes reelspin{to{transform:rotate(360deg)}}';document.head.appendChild(st);})(); -document.querySelectorAll('.reel.spin').forEach(r=>{r.style.animation='reelspin 2.6s linear infinite';}); - /* static paint for reduced motion */ function paintStatic(){ MH.vu.set(0.55,0.5);MH.mini.set(0.55); diff --git a/docs/prototypes/widgets.js b/docs/prototypes/widgets.js index 2c57935..72bb107 100644 --- a/docs/prototypes/widgets.js +++ b/docs/prototypes/widgets.js @@ -3782,7 +3782,509 @@ GW.blinkenlights = function (host, opts = {}) { }; /* ---- widget CSS: injected once, grows as builders move in ---- */ -const GW_CSS = ``; +/* widget-internal CSS (moved from the gallery