diff --git a/DeepDrftPublic/wwwroot/styles/deepdrft-styles.css b/DeepDrftPublic/wwwroot/styles/deepdrft-styles.css index 6c53392..1aed379 100644 --- a/DeepDrftPublic/wwwroot/styles/deepdrft-styles.css +++ b/DeepDrftPublic/wwwroot/styles/deepdrft-styles.css @@ -399,8 +399,9 @@ h2, h3, h4, h5, h6, section labels are LIGHT (static). The slider track/thumb and the lamp toggles are green. ============================================================================= */ .waveform-visualizer-control-panel.mix-visualizer-controls-bar { - /* Lighter-navy elevated panel ground (§5: navy-mid). */ - background: var(--deepdrft-navy-mid); + /* Greyed panel ground — desaturated charcoal so the blue slider reads against it (defect #1). + Token is tunable in deepdrft-tokens.css without touching this rule. */ + background: var(--deepdrft-panel-ground); /* Square corners + thin light border — NowPlayingCard chrome (§5). */ border: 1px solid var(--deepdrft-border-light); border-radius: 0; @@ -424,11 +425,12 @@ h2, h3, h4, h5, h6, /* ── Row layout (§3). Each row is a horizontal band. Row 1 (MODE) and row 3 (WAVE) use space-between so the right-pinned control (color / width) hugs the far edge. Row 2 (LAVA) uses - flex-start so its label + four knobs group left rather than spreading edge-to-edge. ── */ + flex-start so its label + four knobs group left rather than spreading edge-to-edge. + align-items: center so the WAVE slider and section label vertically center with each other (defect #4). ── */ .waveform-visualizer-control-panel .wvc-row { display: flex; flex-direction: row; - align-items: flex-start; + align-items: center; gap: 0.85rem 1rem; } @@ -454,7 +456,7 @@ h2, h3, h4, h5, h6, .waveform-visualizer-control-panel .wvc-row-left { display: flex; flex-direction: row; - align-items: flex-start; + align-items: center; gap: 0.85rem 1rem; } @@ -496,29 +498,52 @@ h2, h3, h4, h5, h6, width: 100%; } -/* Caption icons + section labels render LIGHT (§5/§9 colour principle: static/decorative = light). MudIcon - is portaled here too, so this is a plain global descendant selector — no ::deep, no scope attribute (CSS - isolation does not reach inside the overlay). The knob arcs/pointers + slider stay green (interactive). */ +/* Caption icons render LIGHT (§5/§9: static/decorative = light). !important beats the scoped + .mix-visualizer-control ::deep .mix-visualizer-control-icon rule (which sets green for the legacy + inline mount) when the icon also carries mix-visualizer-control-icon. Lamp toggles are MudIconButton + not MudIcon so they are unaffected — they stay green (interactive, Color.Primary). (defect #3) */ .waveform-visualizer-control-panel .waveform-visualizer-control-icon { - color: var(--deepdrft-white); + color: var(--deepdrft-white) !important; opacity: 0.85; } /* ── The modal overlay (Phase 15 §4). MudOverlay is already a full-viewport flex scrim that centers its content (.mud-overlay { display:flex; align-items:center; justify-content:center }), which gives the - screen-centered panel on every host for free — we do NOT fight that positioning. We only (a) set the - mild modal tint from the SINGLE --deepdrft-modal-scrim-alpha token (§10.5, one point of change) and - (b) cap the centered content's height so a tall both-on deck scrolls inside the modal rather than - overflowing the viewport. The overlay portals to the body, so these are plain global rules (no scope - attribute). The doubled .mud-overlay-scrim.mud-overlay-dark selector (0,2,0) outranks MudBlazor's own - .mud-overlay-dark (0,1,0), so the tint wins regardless of stylesheet load order. ── */ + screen-centered panel on every host for free — we do NOT fight that positioning. We: + (a) Raise the overlay z-index above the header (100) and the player-dock footer (1200/1300) so the + scrim tints the ENTIRE viewport uniformly — header and footer included (defect #7). The panel + content needs z-index: auto (inherits from stacking context) so it sits above the scrim naturally; + the RadialKnob capture div at 9999 remains above everything. + (b) Set the mild tint from the SINGLE --deepdrft-modal-scrim-alpha token (§10.5, defect #6). + (c) Remove overflow-y:auto on the content wrapper — it was the source of the drag scrollbar (defect #2). + The panel's max-width/flex-column already contain its size; the outer overlay clips at 100vh. + (d) Suppress body scroll while the overlay is present so no page-scroll occurs during a drag (defect #2). + The overlay portals to the body, so these are plain global rules (no scope attribute). The doubled + .mud-overlay-scrim.mud-overlay-dark selector (0,2,0) outranks MudBlazor's own .mud-overlay-dark (0,1,0), + so the tint wins regardless of stylesheet load order. ── */ + +/* Raise the overlay itself above the sticky header (z-index:100) and the fixed player dock (z-index:1200). + Use 1400 so it sits above the minimized-dock FAB (1300) too. The panel content inherits this context + and stacks above the scrim; the RadialKnob capture div (z-index:9999) stays highest. */ +.waveform-visualizer-control-overlay { + z-index: 1400 !important; +} + .waveform-visualizer-control-overlay .mud-overlay-scrim.mud-overlay-dark { background-color: rgba(var(--deepdrft-scrim-rgb), var(--deepdrft-modal-scrim-alpha)); } +/* No overflow-y:auto — removing it eliminates the spurious scrollbar that appeared while dragging a + knob (defect #2). The panel's flex-column layout is self-contained and never overflows the overlay. */ .waveform-visualizer-control-overlay .mud-overlay-content { max-height: 90vh; - overflow-y: auto; + overflow: visible; +} + +/* Lock body scroll while the controls overlay is open so the page cannot be scrolled during a + knob drag (defect #2). :has() degrades gracefully in older browsers (no lock, no crash). */ +body:has(.waveform-visualizer-control-overlay) { + overflow: hidden; } @media (max-width: 419.98px) { diff --git a/DeepDrftShared.Client/Components/RadialKnob.razor b/DeepDrftShared.Client/Components/RadialKnob.razor index 809878a..3beb2ed 100644 --- a/DeepDrftShared.Client/Components/RadialKnob.razor +++ b/DeepDrftShared.Client/Components/RadialKnob.razor @@ -1,10 +1,16 @@ @using System.Globalization - + @if (_isDragging) {
+ @onpointermove="@OnGlobalPointerMove" + @onpointerup="@OnGlobalPointerUp" + @onpointercancel="@OnGlobalPointerCancel">
} @@ -156,19 +162,19 @@ _lastMouseY = e.ClientY; _dragValue = Value; // Initialize drag value with current value - // Add global mouse event handlers using Blazor's event handling + // The full-viewport capture div renders; pointer events on it will handle the rest. StateHasChanged(); } - private async Task OnGlobalMouseMove(MouseEventArgs e) + private async Task OnGlobalPointerMove(PointerEventArgs e) { if (_isDragging) { - await UpdateValueFromMouse(e); + await UpdateValueFromPointer(e); } } - private async Task OnGlobalMouseUp(MouseEventArgs e) + private async Task OnGlobalPointerUp(PointerEventArgs e) { if (_isDragging && HoldValue) { @@ -183,9 +189,16 @@ StateHasChanged(); } - private async Task UpdateValueFromMouse(MouseEventArgs e) + // Pointer capture cancelled by OS (e.g. Alt+Tab, system gesture) — end drag cleanly. + private async Task OnGlobalPointerCancel(PointerEventArgs e) { - // Calculate vertical delta from last mouse position + _isDragging = false; + StateHasChanged(); + } + + private async Task UpdateValueFromPointer(PointerEventArgs e) + { + // Calculate vertical delta from last pointer position double deltaY = _lastMouseY - e.ClientY; // Inverted: up = positive, down = negative _lastMouseY = e.ClientY; diff --git a/DeepDrftShared.Client/wwwroot/styles/deepdrft-tokens.css b/DeepDrftShared.Client/wwwroot/styles/deepdrft-tokens.css index a4ee762..e6c453f 100644 --- a/DeepDrftShared.Client/wwwroot/styles/deepdrft-tokens.css +++ b/DeepDrftShared.Client/wwwroot/styles/deepdrft-tokens.css @@ -26,7 +26,10 @@ --deepdrft-scrim-rgb: 13, 27, 42; /* Modal scrim opacity — the SINGLE point of truth for the visualizer-controls overlay tint (Phase 15 §4/§10.5). Mild so the panel reads as modal without a blackout. Change here once. */ - --deepdrft-modal-scrim-alpha: 0.3; + --deepdrft-modal-scrim-alpha: 0.15; + /* Panel ground — desaturated from navy-mid toward charcoal so the blue slider stands out. + Tunable: increase blue channel (e.g. #1e2235) to recover warmth, lower (e.g. #1a1d22) to go darker. */ + --deepdrft-panel-ground: #1e2028; /* Wireframe font stack */ --deepdrft-font-display: "Cormorant Garamond", Georgia, serif;