diff --git a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.css b/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.css index 78a7d01..91583b2 100644 --- a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.css +++ b/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.css @@ -1,8 +1,19 @@ /* Full-viewport fixed backdrop. Sits behind the detail content (.mix-detail-foreground is z-index:1) - and never intercepts pointer events — except the zoom slider, which re-enables them on itself. */ + and never intercepts pointer events — except the zoom slider, which re-enables them on itself. + + Footer clip (Phase 10 W1, spec §2c): the backdrop must stop cleanly ABOVE the audio player bar so + no lava/waveform pixel paints over or under it. `overflow: hidden` clips the canvas to this box, and + `bottom` is inset by the player bar's LIVE height — `--player-height`, the custom property the player + already publishes on :root via its ResizeObserver (AudioPlayerBar + Interop/layout/spacer.ts). That + var tracks the expanded bar's border-box height across breakpoints/error-banner reflow, and resets to + 0 when the bar is minimized — so the clip line follows the bar's actual current height with no extra + coupling: when minimized the var is 0 and the backdrop reaches the viewport bottom (the floating FAB, + z-index 1300, simply sits over it — there is no full-width bar to clip to), matching spec §2c. The + 0px fallback keeps the backdrop full-height on any page that doesn't host the player. */ .mix-waveform-bg { position: fixed; inset: 0; + bottom: var(--player-height, 0px); z-index: 0; pointer-events: none; overflow: hidden; diff --git a/DeepDrftPublic/Interop/visualizer/MixVisualizer.ts b/DeepDrftPublic/Interop/visualizer/MixVisualizer.ts index e6d2a08..e2952dc 100644 --- a/DeepDrftPublic/Interop/visualizer/MixVisualizer.ts +++ b/DeepDrftPublic/Interop/visualizer/MixVisualizer.ts @@ -855,9 +855,13 @@ void main() { // most effective "this is glass" cue (spec §4f.4). float fresnel = pow(1.0 - max(dot(N, V), 0.0), GLASS_FRESNEL_POWER); - // Frosted translucency: a subtle noise modulation of alpha so edges read soft/lit - // rather than hard — the "frosted glass" cue done in-shader (no CSS blur, §4f.3). - float frost = 0.85 + 0.15 * valueNoise(vec2(screenX * 0.05, screenYTop * 0.05)); + // REMOVED (Phase 10 W1 de-noise, spec §3): the screen-space "frost" alpha noise — + // frost = 0.85 + 0.15 * valueNoise(vec2(screenX*0.05, screenYTop*0.05)). It was a + // static value-noise keyed to SCREEN coordinates (not the moving fluid), so it sat as + // a fixed grainy/dirty film over the whole ribbon — exactly the "static-looking texture + // that makes the screen look dirty" Daniel rejected. Alpha is now the clean backdrop + // opacity with no grain. (Fluid-tied noise — the bubble swell and the colour-field drift, + // both keyed to mix-time — is retained: it moves with the audio and does not read as dirt.) // Compose the lit glass colour: field base + warped refraction, lifted by sheen and // a Fresnel rim toward the VIVID moss accent, plus a white-hot specular dot. Using the @@ -867,9 +871,10 @@ void main() { lit = mix(lit, vividAccent * 1.3, fresnel * 0.7); // rim glows vivid moss lit += spec * vec3(1.0); // specular is white light - // Alpha: the backdrop opacity, lifted at the rim (Fresnel) so edges catch light, and - // softened by the frost. Pre-multiplied output for the ONE/ONE_MINUS_SRC_ALPHA blend. - float alpha = inside * RIBBON_OPACITY * frost; + // Alpha: the backdrop opacity, lifted at the rim (Fresnel) so edges catch light. + // (Frost removed — see the de-noise note above.) Pre-multiplied output for the + // ONE/ONE_MINUS_SRC_ALPHA blend. + float alpha = inside * RIBBON_OPACITY; alpha = clamp(alpha + inside * fresnel * RIBBON_OPACITY * 0.8, 0.0, 1.0); fragColor = vec4(lit * alpha, alpha); diff --git a/DeepDrftShared.Client/Common/DDIcons.cs b/DeepDrftShared.Client/Common/DDIcons.cs index 271a28f..ab6f6d0 100644 --- a/DeepDrftShared.Client/Common/DDIcons.cs +++ b/DeepDrftShared.Client/Common/DDIcons.cs @@ -24,17 +24,24 @@ public static class DDIcons """; /// - /// Lava lamp - the Mix visualizer settings glyph. Inner path/shape markup for MudBlazor's Icon= slot - /// (no outer <svg> wrapper — MudBlazor supplies that). Tapered base, tall rounded glass vessel, - /// a cap, and three suspended blobs at varied heights. The silhouette is currentColor so it themes - /// with its context (Color.Secondary tint, light/dark). The blobs carry a warm two-tone accent à la - /// the gas-lamp flame so the lamp reads as "lit" at icon size; coordinates are in the 24×24 space - /// that matches MudBlazor's viewBox="0 0 24 24" wrapper. + /// Lava lamp - the Mix visualizer settings glyph. Classic 1970s "Lava" silhouette, redrawn (Phase 10 + /// W1). Inner path/shape markup for MudBlazor's Icon= slot (no outer <svg> wrapper — MudBlazor + /// supplies that); coordinates in the 24×24 space matching viewBox="0 0 24 24". + /// + /// Bottom→top: a WIDE truncated-cone metal BASE (widest at the very bottom, tapering up to a narrow + /// waist); a tall tapered GLASS VESSEL on the base — bulbous/rounded at the bottom, tapering up to a + /// roundedly-pointed (teardrop/bullet) top; a small truncated-cone metal CAP on top mirroring the base. + /// The metal base + cap are currentColor so the silhouette stays tintable with its context + /// (Color.Secondary, light/dark). The fluid + blobs are hard navy/moss so the lamp reads as "lit" at + /// icon size: navy (#17283F) vessel fluid with 3 varied moss (#429D6A) lava blobs suspended in it. + /// NOTE: these hexes mirror the app theme tokens (navy ~#17283F/#0D1B2A, moss ~#3D7A68/#429D6A). /// public const string LavaLamp = """ - - - - + + + + + + """; }