Merge Examples/RL tabs into single unified toolbar across all four UIs. Users can now freely mix supervised learning (Add Example + Train) with RL feedback (thumbs up/down) without switching modes. Param bar dragging is always enabled. Add Web MIDI input module (js/synth/midi-input.js) for external MIDI controllers — routes note on/off to C15 synth, CC 1/2 to joystick. Add gamepad module (js/ui/gamepad.js) with auto-detection, deadzone, and axis normalization across all UIs. Fix synth parameter sync: routeOutputs() now called after trainModel() in onThumbsUp and loadState to prevent stale params on first joystick move. Add separate Clear Examples button (dataset only, keeps weights).
857 lines
16 KiB
CSS
857 lines
16 KiB
CSS
/* NISPS Immersive — Design A */
|
|
/* Full-viewport canvas with floating translucent overlays */
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
:root {
|
|
--glass-bg: rgba(13, 13, 13, 0.65);
|
|
--glass-border: rgba(255, 255, 255, 0.08);
|
|
--glass-blur: 16px;
|
|
--accent: #ff6a00;
|
|
--accent-dim: rgba(255, 106, 0, 0.25);
|
|
--danger: #ff4466;
|
|
--text: #e0e0e0;
|
|
--text-dim: #888;
|
|
--radius: 12px;
|
|
--radius-sm: 8px;
|
|
--safe-bottom: env(safe-area-inset-bottom, 0px);
|
|
}
|
|
|
|
html, body {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
background: #0d0d0d;
|
|
color: var(--text);
|
|
font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
|
|
font-size: 13px;
|
|
touch-action: none;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
}
|
|
|
|
/* ---- Back button ---- */
|
|
.back-btn {
|
|
position: fixed;
|
|
top: 30px;
|
|
left: 8px;
|
|
z-index: 30;
|
|
width: 36px;
|
|
height: 36px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0;
|
|
border-radius: 6px;
|
|
background: rgba(13, 13, 13, 0.65);
|
|
backdrop-filter: blur(16px);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
color: var(--text);
|
|
text-decoration: none;
|
|
line-height: 1;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.back-btn:hover, .back-btn:active {
|
|
border-color: var(--accent);
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* ---- Output mode toggle (floating) ---- */
|
|
.output-toggle-float {
|
|
position: fixed;
|
|
top: 30px;
|
|
right: 12px;
|
|
z-index: 30;
|
|
display: flex;
|
|
border-radius: 6px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--glass-border);
|
|
background: var(--glass-bg);
|
|
backdrop-filter: blur(var(--glass-blur));
|
|
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
}
|
|
|
|
.otf-opt {
|
|
padding: 6px 14px;
|
|
font-size: 12px;
|
|
font-family: inherit;
|
|
color: var(--text-dim);
|
|
background: transparent;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.otf-opt.active {
|
|
background: var(--accent-dim);
|
|
color: var(--accent);
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* ---- Fullscreen canvas ---- */
|
|
#vis-canvas,
|
|
#synth-vis-canvas {
|
|
position: fixed;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
z-index: 0;
|
|
}
|
|
|
|
#synth-vis-canvas {
|
|
display: none;
|
|
}
|
|
|
|
#synth-vis-canvas.active {
|
|
display: block;
|
|
}
|
|
|
|
#vis-canvas.hidden-canvas {
|
|
display: none;
|
|
}
|
|
|
|
/* ---- Glass mixin ---- */
|
|
.glass {
|
|
background: var(--glass-bg);
|
|
backdrop-filter: blur(var(--glass-blur));
|
|
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
border: 1px solid var(--glass-border);
|
|
}
|
|
|
|
/* ---- Heatmap strip (top) ---- */
|
|
.heatmap-strip {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 22px;
|
|
z-index: 20;
|
|
background: rgba(13, 13, 13, 0.5);
|
|
backdrop-filter: blur(8px);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
display: flex;
|
|
align-items: flex-end;
|
|
padding: 2px 4px;
|
|
}
|
|
|
|
.heatmap-cells {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex: 1;
|
|
height: 16px;
|
|
gap: 1px;
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.heatmap-cell {
|
|
flex: 1;
|
|
min-width: 0;
|
|
position: relative;
|
|
cursor: pointer;
|
|
height: 16px;
|
|
background: rgba(255, 255, 255, 0.04);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.heatmap-cell-bar {
|
|
height: 100%;
|
|
border-radius: 0 1px 1px 0;
|
|
transition: width 0.15s;
|
|
}
|
|
|
|
.heatmap-cell:hover .heatmap-cell-bar {
|
|
filter: brightness(1.3);
|
|
}
|
|
|
|
.heatmap-tooltip {
|
|
position: fixed;
|
|
top: 32px;
|
|
padding: 4px 10px;
|
|
background: rgba(0, 0, 0, 0.85);
|
|
border: 1px solid var(--glass-border);
|
|
border-radius: 6px;
|
|
font-size: 12px;
|
|
color: var(--text);
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transition: opacity 0.15s;
|
|
z-index: 25;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.heatmap-tooltip.visible {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* ---- Floating joystick with integrated map ---- */
|
|
.joystick-container {
|
|
position: fixed;
|
|
bottom: 136px;
|
|
left: 24px;
|
|
width: 160px;
|
|
height: 160px;
|
|
z-index: 30;
|
|
touch-action: none;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
#joy-map {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
cursor: grab;
|
|
touch-action: none;
|
|
}
|
|
|
|
#joy-map:active {
|
|
cursor: grabbing;
|
|
}
|
|
|
|
.joystick-glow {
|
|
position: absolute;
|
|
inset: -8px;
|
|
border-radius: 50%;
|
|
pointer-events: none;
|
|
background: radial-gradient(circle, rgba(255,106,0,0.06) 0%, transparent 70%);
|
|
z-index: -1;
|
|
}
|
|
|
|
/* Noise ring (RL exploration indicator) */
|
|
.noise-ring {
|
|
position: absolute;
|
|
inset: -4px;
|
|
border-radius: 50%;
|
|
border: 0px solid rgba(255, 100, 50, 0.0);
|
|
pointer-events: none;
|
|
transition: border-width 0.3s, border-color 0.3s;
|
|
}
|
|
|
|
.noise-ring.active {
|
|
border-width: 3px;
|
|
border-color: rgba(255, 100, 50, 0.5);
|
|
}
|
|
|
|
.noise-ring.high {
|
|
border-width: 6px;
|
|
border-color: rgba(255, 60, 40, 0.6);
|
|
}
|
|
|
|
/* Follow badge near joystick */
|
|
.follow-badge {
|
|
position: absolute;
|
|
top: -24px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
padding: 2px 10px;
|
|
border-radius: 10px;
|
|
background: rgba(255, 106, 0, 0.15);
|
|
border: 1px solid rgba(255, 106, 0, 0.4);
|
|
color: var(--accent);
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 1px;
|
|
pointer-events: none;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.follow-badge.hidden {
|
|
display: none;
|
|
}
|
|
|
|
/* Joystick follow-mode pulsing border on canvas */
|
|
.joystick-container.follow-active #joy-map {
|
|
box-shadow: 0 0 0 2px rgba(255, 106, 0, 0.5);
|
|
animation: follow-pulse 1.5s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes follow-pulse {
|
|
0%, 100% { box-shadow: 0 0 0 2px rgba(255, 106, 0, 0.3); }
|
|
50% { box-shadow: 0 0 12px 3px rgba(255, 106, 0, 0.5); }
|
|
}
|
|
|
|
/* ---- RL floating buttons ---- */
|
|
.rl-buttons {
|
|
position: fixed;
|
|
bottom: 92px; /* just above 88px collapsed sheet */
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
display: flex;
|
|
gap: 32px;
|
|
z-index: 45;
|
|
transition: opacity 0.3s;
|
|
}
|
|
|
|
.rl-buttons.hidden {
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.rl-btn {
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 50%;
|
|
border: 2px solid var(--glass-border);
|
|
background: var(--glass-bg);
|
|
backdrop-filter: blur(var(--glass-blur));
|
|
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding-top: 2px;
|
|
gap: 0;
|
|
}
|
|
|
|
.rl-icon {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
}
|
|
|
|
.key-num {
|
|
font-size: 12px;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
font-family: inherit;
|
|
line-height: 1;
|
|
margin-top: -1px;
|
|
}
|
|
|
|
.rl-btn:active {
|
|
transform: scale(0.9);
|
|
}
|
|
|
|
.rl-up {
|
|
border-color: rgba(0, 200, 160, 0.4);
|
|
color: #00c8a0;
|
|
background: rgba(0, 200, 160, 0.08);
|
|
}
|
|
|
|
.rl-up:active {
|
|
background: rgba(0, 200, 160, 0.2);
|
|
box-shadow: 0 0 20px rgba(0, 200, 160, 0.3);
|
|
}
|
|
|
|
.rl-down {
|
|
border-color: rgba(220, 60, 20, 0.4);
|
|
color: #dc3c14;
|
|
background: rgba(220, 60, 20, 0.08);
|
|
}
|
|
|
|
.rl-down:active {
|
|
background: rgba(220, 60, 20, 0.2);
|
|
box-shadow: 0 0 20px rgba(220, 60, 20, 0.3);
|
|
}
|
|
|
|
.rl-btn.flash {
|
|
animation: rl-flash 0.25s ease-out;
|
|
}
|
|
|
|
@keyframes rl-flash {
|
|
0% { transform: scale(1.15); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
|
|
/* ---- Floating mode bar (sticky inside sheet) ---- */
|
|
.floating-bar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 45;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
padding: 6px 12px;
|
|
background: rgba(13, 13, 13, 0.85);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border-bottom: 1px solid var(--glass-border);
|
|
}
|
|
|
|
/* Float button (randomize in floating bar) */
|
|
.float-btn {
|
|
padding: 4px 12px;
|
|
border-radius: 6px;
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
background: rgba(255, 255, 255, 0.04);
|
|
color: var(--text-dim);
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.float-btn:active {
|
|
background: rgba(255, 106, 0, 0.15);
|
|
color: var(--accent);
|
|
}
|
|
|
|
.float-btn.accent {
|
|
border-color: rgba(255, 106, 0, 0.3);
|
|
color: var(--accent);
|
|
}
|
|
|
|
.follow-pill {
|
|
padding: 4px 12px;
|
|
border-radius: 6px;
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
background: rgba(255, 255, 255, 0.04);
|
|
color: var(--text-dim);
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.follow-pill.active {
|
|
background: rgba(255, 106, 0, 0.15);
|
|
border-color: rgba(255, 106, 0, 0.4);
|
|
color: var(--accent);
|
|
}
|
|
|
|
.chevron-btn {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
border: 1px solid var(--glass-border);
|
|
background: rgba(255, 255, 255, 0.06);
|
|
color: var(--text-dim);
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.chevron-btn:active {
|
|
background: rgba(255, 255, 255, 0.12);
|
|
}
|
|
|
|
.chevron-btn.open {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
/* ---- Bottom sheet ---- */
|
|
.bottom-sheet {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 40;
|
|
background: rgba(13, 13, 13, 0.75);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border-top: 1px solid var(--glass-border);
|
|
border-radius: 0;
|
|
transition: height 0.35s cubic-bezier(0.22, 1, 0.36, 1);
|
|
height: 88px;
|
|
overflow: hidden;
|
|
padding-bottom: var(--safe-bottom);
|
|
will-change: height;
|
|
}
|
|
|
|
.bottom-sheet.expanded {
|
|
height: 55vh;
|
|
overflow-y: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
/* Sheet status line */
|
|
.sheet-status {
|
|
padding: 8px 16px;
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
text-align: center;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
height: 44px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* Sheet content */
|
|
.sheet-content {
|
|
padding: 0 16px 16px;
|
|
}
|
|
|
|
/* Mode row */
|
|
.mode-row {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
/* Pill toggle */
|
|
.pill-toggle {
|
|
display: inline-flex;
|
|
border-radius: 6px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--glass-border);
|
|
background: rgba(255, 255, 255, 0.04);
|
|
}
|
|
|
|
.pill-opt {
|
|
padding: 6px 18px;
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-dim);
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.pill-opt.active {
|
|
background: var(--accent-dim);
|
|
color: var(--accent);
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Action buttons row */
|
|
.action-row {
|
|
display: flex;
|
|
gap: 8px;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.action-btn {
|
|
padding: 8px 16px;
|
|
border-radius: 6px;
|
|
border: 1px solid var(--glass-border);
|
|
background: rgba(255, 255, 255, 0.06);
|
|
color: var(--text);
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
touch-action: manipulation;
|
|
}
|
|
|
|
.action-btn:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.action-btn.accent {
|
|
border-color: rgba(255, 106, 0, 0.3);
|
|
color: var(--accent);
|
|
background: rgba(255, 106, 0, 0.08);
|
|
}
|
|
|
|
.action-btn.accent:active {
|
|
background: rgba(255, 106, 0, 0.2);
|
|
}
|
|
|
|
.action-btn.dim {
|
|
color: var(--text-dim);
|
|
border-color: rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
.action-btn.flash {
|
|
animation: btn-flash 0.2s ease-out;
|
|
}
|
|
|
|
@keyframes btn-flash {
|
|
0% { background: rgba(255, 106, 0, 0.3); }
|
|
100% { background: rgba(255, 255, 255, 0.06); }
|
|
}
|
|
|
|
/* Preset row */
|
|
.preset-row {
|
|
display: flex;
|
|
gap: 6px;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.preset-label {
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
margin-right: 4px;
|
|
}
|
|
|
|
.preset-chip {
|
|
padding: 4px 12px;
|
|
border-radius: 6px;
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
background: rgba(255, 255, 255, 0.04);
|
|
color: var(--text-dim);
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
touch-action: manipulation;
|
|
}
|
|
|
|
.preset-chip:active {
|
|
background: rgba(255, 106, 0, 0.15);
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* Synth panel */
|
|
.synth-panel {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.synth-panel.hidden {
|
|
display: none;
|
|
}
|
|
|
|
.synth-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.synth-row label {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
min-width: 80px;
|
|
}
|
|
|
|
.synth-row input[type="range"] {
|
|
flex: 1;
|
|
accent-color: var(--accent);
|
|
height: 4px;
|
|
}
|
|
|
|
.synth-row select {
|
|
flex: 1;
|
|
background: rgba(255, 255, 255, 0.06);
|
|
border: 1px solid var(--glass-border);
|
|
border-radius: 6px;
|
|
color: var(--text);
|
|
padding: 4px 8px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.synth-status {
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
/* Loss section */
|
|
.loss-section {
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.loss-section label {
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
#loss-canvas {
|
|
width: 100%;
|
|
height: 80px;
|
|
border-radius: var(--radius-sm);
|
|
background: rgba(0, 0, 0, 0.3);
|
|
border: 1px solid var(--glass-border);
|
|
}
|
|
|
|
/* Advanced section */
|
|
.advanced-section {
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.advanced-section summary {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
cursor: pointer;
|
|
padding: 6px 0;
|
|
}
|
|
|
|
.raw-params {
|
|
display: grid;
|
|
grid-template-columns: 1fr;
|
|
gap: 4px;
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
padding: 8px 0;
|
|
}
|
|
|
|
.raw-param {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 11px;
|
|
}
|
|
|
|
.raw-param-label {
|
|
width: 70px;
|
|
color: var(--text-dim);
|
|
text-align: right;
|
|
flex-shrink: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.raw-param input[type="range"] {
|
|
flex: 1;
|
|
accent-color: var(--accent);
|
|
height: 3px;
|
|
}
|
|
|
|
.raw-param-val {
|
|
width: 36px;
|
|
color: var(--text-dim);
|
|
text-align: left;
|
|
flex-shrink: 0;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* ---- Synth quick controls (play button next to back) ---- */
|
|
.synth-quick-controls {
|
|
position: fixed;
|
|
top: 30px;
|
|
left: 52px;
|
|
z-index: 30;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: 0;
|
|
}
|
|
|
|
.play-btn {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 18px;
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
background: rgba(13, 13, 13, 0.65);
|
|
backdrop-filter: blur(16px);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: background 0.15s, border-color 0.15s;
|
|
padding: 0;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.play-btn:active {
|
|
background: rgba(255, 255, 255, 0.12);
|
|
}
|
|
|
|
.play-btn.playing {
|
|
border-color: rgba(255, 106, 0, 0.4);
|
|
color: var(--accent);
|
|
background: rgba(255, 106, 0, 0.12);
|
|
}
|
|
|
|
.play-drawer {
|
|
display: none;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
padding: 8px 12px;
|
|
border-radius: 18px;
|
|
background: rgba(13, 13, 13, 0.65);
|
|
backdrop-filter: blur(16px);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
margin-left: 6px;
|
|
height: auto;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.play-drawer label {
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.play-drawer input[type="range"] {
|
|
width: 80px;
|
|
accent-color: var(--accent);
|
|
height: 3px;
|
|
}
|
|
|
|
.play-drawer span {
|
|
font-size: 10px;
|
|
font-variant-numeric: tabular-nums;
|
|
min-width: 24px;
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
.synth-quick-controls:hover .play-drawer,
|
|
.play-drawer.show {
|
|
display: flex;
|
|
}
|
|
|
|
/* ---- Utility ---- */
|
|
.hidden {
|
|
display: none !important;
|
|
}
|
|
|
|
/* ---- Scrollbar styling ---- */
|
|
.bottom-sheet::-webkit-scrollbar {
|
|
width: 4px;
|
|
}
|
|
|
|
.bottom-sheet::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.bottom-sheet::-webkit-scrollbar-thumb {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* ---- Media queries ---- */
|
|
@media (min-width: 768px) {
|
|
.joystick-container {
|
|
width: 180px;
|
|
height: 180px;
|
|
bottom: 156px;
|
|
left: 32px;
|
|
}
|
|
|
|
#joy-map {
|
|
width: 180px;
|
|
height: 180px;
|
|
}
|
|
|
|
.rl-buttons {
|
|
bottom: 92px;
|
|
gap: 32px;
|
|
}
|
|
|
|
.rl-btn {
|
|
width: 72px;
|
|
height: 72px;
|
|
font-size: 32px;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
.bottom-sheet {
|
|
max-width: 600px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
}
|
|
}
|