docs(product): fold Mix Visualizer lava reframe under Phase 10 (Waves R1-R4); inline knob-bar + icon redraw
This commit is contained in:
@@ -200,6 +200,23 @@ Full design, renderer architecture, the four effects, acceptance criteria, and p
|
||||
|
||||
**Wave 4 — detail-page polish + controls rework (presentation only; the final wave).** A UI/placement pass over the Mix detail page — **no renderer, state, bridge, or mapping change.** (1) The four controls move out of the always-visible row into a **popover** (`MudPopover`, `SharePopover`-idiom) opened by a new bespoke **lava-lamp icon button** anchored **top-right of the body, across from the `← Back` link** (recommend a new `TopRightAction` slot on `ReleaseDetailScaffold`, laid as a SpaceBetween row with the back link). (2) The lava-lamp SVG lives in `DeepDrftShared.Client/Common/DDIcons.cs` in the hand-rolled gas-lamp style (`currentColor`, 24×24 viewBox, raw-string const) — a recognizable lamp with two-three suspended blobs. (3) The four `MudSlider`s become four **`RadialKnob`s** (`DeepDrftShared.Client/Components/RadialKnob.razor`) **in a row in the popover**, each carrying its existing Material icon (`ZoomIn`/`BubbleChart`/`Air`/`Palette`) **as an adjacent `MudIcon` caption** — RadialKnob has **no icon slot** (its `Label` is SVG text), so icons sit beside each knob. Knobs bind `Value`/`ValueChanged` to the **unchanged** `MixVisualizerControlState` via the **same `OnXChanged` handlers + `NotifyChanged()` seam** the sliders use today (resolution via `MixZoomMapping` fraction; other three normalized [0,1]; `HoldValue=false` for live feel). (4) **Widen the Mix body** to match the Sessions detail page — `MudContainer MaxWidth="Large"` (~1280px, up from the scaffold's 760px), Mix-scoped so Track detail is unaffected. **Depends on Wave 3 merged** (the knobs drive the Wave 3 effects) and **supersedes the controls-row design** (`product-notes/mix-visualizer-webgl-renderer.md` §3 → §7). Read-only contract intact; no knob is a seek surface. Full design + acceptance: that spec's **§7**.
|
||||
|
||||
### Phase 10 — Reframe (Lava): Waves R1–R4
|
||||
|
||||
A **major reframe of the Mix visualizer's effects, controls, and color model**, folded **under this same Phase 10** as a reframe wave-set (**Waves R1–R4** — labelled to stay unambiguous against the landed Waves 1–4 above). It builds on the landed Phase 10 renderer infrastructure (pipeline, datum texture, playhead interp, bridge, widened body, lava-lamp trigger) but **replaces what it paints**. Daniel tested the Phase 10 effects end-to-end and rejected the visual result: the lava read as "giant disconnected circles," the colors drifted to cyan (an HSL saturation-boost artifact), and the waveform and lava read as two unrelated things sharing a canvas. The diagnosis (staff-engineer research pass) is that the rejected look is **structural to the effect approach, not a tuning miss**.
|
||||
|
||||
**This supersedes the original Phase 10 (Waves 1–4) effects/controls/color design** — `product-notes/mix-visualizer-webgl-renderer.md` §4 (effects) and §7 (popover-controls) are marked superseded with a pointer to the reframe spec. The renderer *infrastructure* carries forward unchanged.
|
||||
|
||||
**The three reframes:**
|
||||
- **Lava → CPU-physics wax blobs.** Keep the single-pass WebGL2 fragment renderer; add a small CPU-side per-frame physics step modeling ~16–32 Lagrangian "wax blobs" (position/velocity/temperature/radius) uploaded as uniforms and blended with `smin` SDF metaballs. The waveform and lava share **the same plane WITH real 2D elastic collision** (blob↔waveform-boundary + blob↔blob) — the waveform pushes the fluid out of its way (read-only authority preserved; the fluid never deforms the waveform). At heat 0 the wax rests at the bottom and only collision moves it (collision always on, independent of heat); at heat max many bubbles rise/morph per second. **Rejected: a full ping-pong FBO Navier-Stokes fluid sim** — a lava lamp is high-viscosity/low-turbulence, the opposite regime; large rewrite for unwanted realism. Deliberate later upgrade only.
|
||||
- **Color → three-color OKLab gradient with three motions.** One source of truth (`DeepDrftPalettes`), no hardcoded hexes. Always A→B linear from the center line outward. Three combined motions: (1) anchors A/B **rotate among three theme colors X/Y/Z** at the rotation-speed control's rate — **OKLab interpolation, never through the rainbow** (the cyan fix is structural, not a tuning dial); (2) per-bar sinusoidal variation **baked at segment entry and fixed as the segment scrolls** — realized by **keying the sinusoid to mix-time** so it travels with the segment by construction (decided 2026-06-16; the explicit ring-buffer alternative is rejected for maintainability); (3) per-bar gradient curve shifts with scroll height (mostly A at bottom → mostly B at top). The static noise/frost texture is **removed** (Daniel: makes the screen look dirty).
|
||||
- **Controls → six knobs in an inline collapse/expand knob-bar.** Replaces the four: (1) waveform scroll speed [replaces resolution/zoom as a standalone control], (2) gradient rotation speed, (3) lava gravity, (4) lava heat, (5) blob density/size, (6) collision strength (soft→hard). **NOT a popover or drawer — an inline collapse/expand knob-bar** (decided 2026-06-16): an `@if`-guarded **animated flex row of the six `RadialKnob`s** living inline in the controls area, expanding/collapsing **in place** (CSS width/opacity/transform transition) so it reads as the controls collapsing/expanding, not a floating surface. The lava-lamp icon button toggles a bound bool — no MudPopover/MudDrawer. Styled to **match the NowPlaying hero aesthetic** (the session-detail hero overlay — translucent dark glass, overlay-label typography, `Color.Secondary`). Also: overflow-clip the visualizer to the **dynamic footer height** (the player bar changes height minimized/expanded) so visuals stop cleanly above it; the clip line is also the lava rest line.
|
||||
|
||||
**Plus: redraw the lava-lamp glyph.** The current `DDIcons.LavaLamp` is rejected (Daniel: "form is shit, colors are shit"). Redraw to the classic 1970s silhouette — a wide truncated-cone metal **base**, a bulbous→roundedly-pointed teardrop **glass body**, a small cone **cap** ("offset cones") — with **navy fluid + moss blobs** (the theme's blue+green, faithful to the reference and on-theme) and a neutral/metallic base+cap. Authored in `DeepDrftShared.Client/Common/DDIcons.cs` as inner SVG markup (no `<svg>` wrapper; 24×24 viewBox); body silhouette `currentColor`, the two accent fills are commented literals traced to their `DeepDrftPalettes` source (SVG cannot resolve `var()`).
|
||||
|
||||
Heat→intensity and collision soft↔hard transfer functions are **staff-engineer tuning tasks** (endpoints fixed in the spec, formulas not). Full design, the wax-blob model, the collision model, the three-motion color model, the inline knob-bar, the icon redraw, observable acceptance criteria, and phasing: `product-notes/phase-10-mix-visualizer-lava-reframe.md`.
|
||||
|
||||
**Sequenced as four reframe waves.** `Wave R1 → Wave R2 → (Wave R3 ‖ Wave R4)`. Wave R1 (de-noise + dynamic footer clip + icon redraw) is a cheap unblock for a clean substrate. Wave R2 (wax-blob physics + 2D collision) is the load-bearing prerequisite — prove the lava before the color and the UI. Wave R3 (OKLab three-color gradient, the three motions) and Wave R4 (six controls + NowPlaying-styled inline knob-bar + widened state to six properties + extended bridge handle) both depend on Wave R2 but are independent of each other. **Both prior open Daniel calls are now decided:** controls-UI is an inline collapse/expand knob-bar (not popover/drawer); per-segment color is mix-time-keyed.
|
||||
|
||||
---
|
||||
|
||||
## Phase 11 — Public Site Enhancements
|
||||
@@ -234,23 +251,6 @@ Sequenced as **seven waves**; the critical path is `11.A → 11.B → 11.C`, wit
|
||||
|
||||
---
|
||||
|
||||
## Phase 12 — Mix Visualizer Lava Reframe
|
||||
|
||||
A **major reframe of the Mix visualizer's effects, controls, and color model**, building on the landed Phase 10 WebGL2 renderer infrastructure (pipeline, datum texture, playhead interp, bridge, widened body, lava-lamp trigger) but **replacing what it paints**. Daniel tested the Phase 10 effects end-to-end and rejected the visual result: the lava read as "giant disconnected circles," the colors drifted to cyan (an HSL saturation-boost artifact), and the waveform and lava read as two unrelated things sharing a canvas. The diagnosis (staff-engineer research pass) is that the rejected look is **structural to the effect approach, not a tuning miss**.
|
||||
|
||||
**This supersedes the Phase 10 effects/controls/color design** — `product-notes/mix-visualizer-webgl-renderer.md` §4 (effects) and §7 (popover-controls) are marked superseded with a pointer to the new spec. The renderer *infrastructure* carries forward unchanged.
|
||||
|
||||
**The three reframes:**
|
||||
- **Lava → CPU-physics wax blobs.** Keep the single-pass WebGL2 fragment renderer; add a small CPU-side per-frame physics step modeling ~16–32 Lagrangian "wax blobs" (position/velocity/temperature/radius) uploaded as uniforms and blended with `smin` SDF metaballs. The waveform and lava share **the same plane WITH real 2D elastic collision** (blob↔waveform-boundary + blob↔blob) — the waveform pushes the fluid out of its way (read-only authority preserved; the fluid never deforms the waveform). At heat 0 the wax rests at the bottom and only collision moves it (collision always on, independent of heat); at heat max many bubbles rise/morph per second. **Rejected: a full ping-pong FBO Navier-Stokes fluid sim** — a lava lamp is high-viscosity/low-turbulence, the opposite regime; large rewrite for unwanted realism. Deliberate later upgrade only.
|
||||
- **Color → three-color OKLab gradient with three motions.** One source of truth (`DeepDrftPalettes`), no hardcoded hexes. Always A→B linear from the center line outward. Three combined motions: (1) anchors A/B **rotate among three theme colors X/Y/Z** at the rotation-speed control's rate — **OKLab interpolation, never through the rainbow** (the cyan fix is structural, not a tuning dial); (2) per-bar sinusoidal variation **baked at segment entry and fixed as the segment scrolls** (implies per-segment color state — cleanest realization: key the sinusoid to mix-time so it travels by construction); (3) per-bar gradient curve shifts with scroll height (mostly A at bottom → mostly B at top). The static noise/frost texture is **removed** (Daniel: makes the screen look dirty).
|
||||
- **Controls → six knobs in a flyout.** Replaces the four: (1) waveform scroll speed [replaces resolution/zoom as a standalone control], (2) gradient rotation speed, (3) lava gravity, (4) lava heat, (5) blob density/size, (6) collision strength (soft→hard). **NOT a popover — an extended flyout menu bar** (MudBlazor survey: recommend a horizontal `MudPopover` styled as a knob bar, or `MudDrawer Anchor="Bottom"` if Daniel wants the edge-slide motion — the one Daniel call worth making up front). The six `RadialKnob`s live in the flyout, styled to **match the NowPlaying hero aesthetic** (the session-detail hero overlay — translucent dark glass, overlay-label typography, `Color.Secondary`). Also: overflow-clip the visualizer to the **dynamic footer height** (the player bar changes height minimized/expanded) so visuals stop cleanly above it; the clip line is also the lava rest line.
|
||||
|
||||
Heat→intensity and collision soft↔hard transfer functions are **staff-engineer tuning tasks** (endpoints fixed in the spec, formulas not). Full design, the wax-blob model, the collision model, the three-motion color model, the flyout survey, observable acceptance criteria, and phasing: `product-notes/phase-12-mix-visualizer-lava-reframe.md`.
|
||||
|
||||
**Sequenced as four waves.** `Wave 1 → Wave 2 → (Wave 3 ‖ Wave 4)`. Wave 1 (de-noise + dynamic footer clip) is a cheap unblock for a clean substrate. Wave 2 (wax-blob physics + 2D collision) is the load-bearing prerequisite — prove the lava before the color and the UI. Wave 3 (OKLab three-color gradient, the three motions) and Wave 4 (six controls + NowPlaying-styled flyout + widened state to six properties + extended bridge handle) both depend on Wave 2 but are independent of each other. **Open Daniel call:** flyout primitive (popover-flyout vs. bottom drawer — spec §7b/§10).
|
||||
|
||||
---
|
||||
|
||||
## Working with this file
|
||||
|
||||
- **Add items by extending an existing phase first**; only create a new phase when the addition genuinely doesn't fit any of 1–5. Phase numbers are organisational, not sequencing.
|
||||
|
||||
@@ -214,7 +214,8 @@ contract on both sides).
|
||||
|
||||
## 4. The four visual effects
|
||||
|
||||
> **SUPERSEDED (2026-06-16) by `product-notes/phase-12-mix-visualizer-lava-reframe.md`.** Daniel tested
|
||||
> **SUPERSEDED (2026-06-16) by `product-notes/phase-10-mix-visualizer-lava-reframe.md` (the Phase 10
|
||||
> reframe, Waves R1–R4).** Daniel tested
|
||||
> the landed effects end-to-end and rejected the visual result — the lava read as "giant disconnected
|
||||
> circles," the color drifted to cyan (an HSL saturation-boost artifact), and the waveform and lava read
|
||||
> as two unrelated things. The reframe replaces this entire effects layer: the per-bar bulge + detach
|
||||
@@ -222,7 +223,7 @@ contract on both sides).
|
||||
> of its way), the HSL navy↔moss treatment becomes a **three-color OKLab gradient with three combined
|
||||
> motions**, the separate "glass" effect folds into the blob shading, and the static noise/frost layer is
|
||||
> **removed**. The renderer *infrastructure* (pipeline, datum texture, playhead interp, bridge) is reused;
|
||||
> the *art* below is replaced. See the new spec §3–§6. The four-effect text below is retained as the
|
||||
> the *art* below is replaced. See the reframe spec §3–§6. The four-effect text below is retained as the
|
||||
> record of what the rejected Wave 3 shipped.
|
||||
|
||||
Described as **intended look + shader-side approach in conceptual terms**. The exact GLSL is
|
||||
@@ -433,14 +434,18 @@ hand).
|
||||
|
||||
## 7. Wave 4 — Detail-page polish + controls rework (presentation only)
|
||||
|
||||
> **PARTIALLY SUPERSEDED (2026-06-16) by `product-notes/phase-12-mix-visualizer-lava-reframe.md`.**
|
||||
> **PARTIALLY SUPERSEDED (2026-06-16) by `product-notes/phase-10-mix-visualizer-lava-reframe.md` (the
|
||||
> Phase 10 reframe, Waves R1–R4).**
|
||||
> **Kept:** the lava-lamp icon-button trigger top-right of the body across from the back link (§7c, §7f
|
||||
> — `DDIcons.LavaLamp`, landed) and the widened Mix body (`MudContainer MaxWidth="Large"`, §7g, landed).
|
||||
> **Superseded:** the four-knob **popover** becomes a six-knob **flyout** (the reframe adds two controls —
|
||||
> — `DDIcons.LavaLamp`, landed; the **glyph itself is redrawn** by the reframe §7f).
|
||||
> **Kept:** the widened Mix body (`MudContainer MaxWidth="Large"`, §7g, landed).
|
||||
> **Superseded:** the four-knob **popover** becomes a six-knob **inline collapse/expand knob-bar** — NOT a
|
||||
> popover or drawer (the reframe adds two controls —
|
||||
> lava gravity, blob density/size, collision strength — and drops/recasts others: resolution/zoom is
|
||||
> removed in favor of scroll speed; bubblyness/detach are replaced by the physical lava model), and the
|
||||
> popover primitive is reconsidered (`MudDrawer` vs. popover-as-flyout — see the new spec §7b). See the
|
||||
> new spec §7 for the six controls, the flyout survey, and the NowPlaying-hero aesthetic target. The §7
|
||||
> removed in favor of scroll speed; bubblyness/detach are replaced by the physical lava model). The
|
||||
> controls become an `@if`-guarded animated flex row of six RadialKnobs inline in the controls area,
|
||||
> toggled by the lava-lamp icon — see the reframe spec §7b. See the reframe spec §7 for the six controls,
|
||||
> the inline knob-bar, and the NowPlaying-hero aesthetic target. The §7
|
||||
> text below is retained as the record of what the four-knob popover shipped.
|
||||
|
||||
Status: **design-complete, implementation-ready.** Added 2026-06-15. **Depends on Wave 3 being merged**
|
||||
|
||||
+190
-103
@@ -1,14 +1,21 @@
|
||||
# Mix Visualizer — Lava Reframe (Design Spec)
|
||||
# Mix Visualizer — Phase 10 Reframe (Lava) — Design Spec
|
||||
|
||||
Status: **design-complete, implementation-ready.** Author: product-designer. Date: 2026-06-16.
|
||||
**No code has been written by this doc.**
|
||||
|
||||
This is a **major reframe of the Mix visualizer's effects layer, controls, and color model**. It
|
||||
builds on the landed Phase 10 WebGL2 renderer (Waves 1–4: the single-pass fragment-shader pipeline, the
|
||||
loudness datum texture, the wall-clock playhead interpolation, the controls UI, the widened Mix body)
|
||||
and **replaces what that pipeline paints** — the per-bar bulge, the analytic-metaball "lava," the glass
|
||||
treatment, and the navy↔moss color treatment. The renderer *infrastructure* is reused; the *art and the
|
||||
controls* are rebuilt.
|
||||
This is a **major reframe of the Mix visualizer's effects layer, controls, and color model**, folded
|
||||
**under the still-open Phase 10** (the WebGL2 renderer) as a **reframe wave-set (Waves R1–R4)** —
|
||||
distinct from Phase 10's original Waves 1–4 (renderer swap, controls row, the four effects, the
|
||||
popover/knob polish) which are **already merged**. It builds on that landed Phase 10 infrastructure (the
|
||||
single-pass fragment-shader pipeline, the loudness datum texture, the wall-clock playhead interpolation,
|
||||
the controls UI, the widened Mix body) and **replaces what that pipeline paints** — the per-bar bulge,
|
||||
the analytic-metaball "lava," the glass treatment, and the navy↔moss color treatment. The renderer
|
||||
*infrastructure* is reused; the *art and the controls* are rebuilt.
|
||||
|
||||
> **Numbering note.** This reframe lives **under Phase 10**, not as a separate phase. Its waves are
|
||||
> labelled **R1–R4** to stay unambiguous against Phase 10's landed Waves 1–4. The filename
|
||||
> `phase-10-mix-visualizer-lava-reframe.md` reflects that; an earlier draft of this doc was numbered
|
||||
> "Phase 12" — that numbering is retired.
|
||||
|
||||
**Why a reframe, not an iteration.** Daniel tested the landed Phase 10 effects end-to-end and rejected
|
||||
the visual result: the lava reads as "giant disconnected circles," the colors drifted to cyan (an HSL
|
||||
@@ -19,15 +26,15 @@ scripted blobs with no physics produce disconnected circles, and HSL interpolati
|
||||
low-saturation theme tokens passes through hue regions that read as cyan. Both are fixed by changing the
|
||||
*model*, not the dials.
|
||||
|
||||
This spec **supersedes** the Phase 10 effects/controls/color design:
|
||||
This spec **supersedes** the original Phase 10 effects/controls/color design:
|
||||
|
||||
- `product-notes/mix-visualizer-webgl-renderer.md` **§4 (the four visual effects)** — superseded by
|
||||
§3–§6 here.
|
||||
- `product-notes/mix-visualizer-webgl-renderer.md` **§7 (Wave 4 popover-controls rework)** — superseded
|
||||
by §7 here (the trigger and the widened body are kept; the four-knob popover becomes a six-knob
|
||||
flyout, and the popover primitive is reconsidered in §7b).
|
||||
inline collapse/expand knob-bar — see §7).
|
||||
|
||||
What carries forward unchanged from Phase 10 (do **not** re-derive — reference it):
|
||||
What carries forward unchanged from Phase 10's landed waves (do **not** re-derive — reference it):
|
||||
|
||||
- The single-pass WebGL2 fragment renderer, the full-window quad, the trivial pass-through vertex
|
||||
shader (`mix-visualizer-webgl-renderer.md` §2a).
|
||||
@@ -42,29 +49,32 @@ What carries forward unchanged from Phase 10 (do **not** re-derive — reference
|
||||
`MixZoomMapping` log-space fraction↔seconds mapping.
|
||||
- The read-only contract (8.K §D): one-way playback input, no seek, no scrub, no write-back.
|
||||
- The widened Mix body (`MudContainer MaxWidth="Large"`) and the lava-lamp `DDIcons.LavaLamp`
|
||||
icon-button trigger top-right of the body, across from the back link (Phase 10 §7c, §7g — **kept**).
|
||||
icon-button trigger top-right of the body, across from the back link (Phase 10 §7c, §7g — **kept**;
|
||||
the icon glyph itself is **redrawn** by this reframe, see §7f).
|
||||
|
||||
Cross-references (read these before implementing):
|
||||
|
||||
- `product-notes/mix-visualizer-webgl-renderer.md` — the Phase 10 spec this reframes. §1/§2 (scope,
|
||||
renderer architecture, bridge) carry forward; §4/§7 are superseded.
|
||||
- `product-notes/mix-visualizer-webgl-renderer.md` — the Phase 10 renderer spec this reframes. §1/§2
|
||||
(scope, renderer architecture, bridge) carry forward; §4/§7 are superseded.
|
||||
- `DeepDrftPublic/Interop/visualizer/MixVisualizer.ts` — the landed renderer. The Wave 1 scroll/zoom
|
||||
geometry, the datum texture, and the playhead machinery are reused; the §4-effect GLSL (the bubble
|
||||
SDF, the detach blobs, the HSL `mixHsl`/`vivify` color, the glass) is the part being replaced.
|
||||
- `DeepDrftPublic.Client/Controls/MixVisualizerControls.razor[.cs]` — the four-knob control component;
|
||||
becomes six knobs (§7).
|
||||
becomes six knobs in an inline collapse/expand bar (§7).
|
||||
- `DeepDrftPublic.Client/Services/MixVisualizerControlState.cs` — the scoped four-property state holder;
|
||||
widens to six properties (§7c).
|
||||
- `DeepDrftPublic.Client/Controls/MixZoomMapping.cs` — reused unchanged for the scroll-speed control.
|
||||
- `DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor[.cs/.css]` — the bridge. Extend the handle
|
||||
with the new control setters; the `.css` gains the overflow-clip work (§2).
|
||||
- `DeepDrftPublic.Client/Pages/MixDetail.razor[.css]` — the page; the popover becomes the flyout (§7).
|
||||
- `DeepDrftPublic.Client/Pages/MixDetail.razor[.css]` — the page; the controls area gains the inline
|
||||
collapse/expand knob-bar (§7).
|
||||
- `DeepDrftPublic.Client/Pages/SessionDetail.razor[.css]` — the **NowPlaying / hero aesthetic** the
|
||||
flyout must match (§7e).
|
||||
knob-bar must match (§7e).
|
||||
- `DeepDrftPublic.Client/Controls/AudioPlayerBar/AudioPlayerBar.razor[.css]` — the footer/player bar
|
||||
whose **dynamic height** the clip line must follow (§2c).
|
||||
- `DeepDrftShared.Client/Common/DeepDrftPalettes.cs` — the **single source of truth** for theme colors
|
||||
(§6a). `DeepDrftShared.Client/Components/RadialKnob.razor` — the knob, consumed unchanged (§7d).
|
||||
- `DeepDrftShared.Client/Common/DDIcons.cs` — the lava-lamp glyph, **redrawn** by this reframe (§7f).
|
||||
|
||||
---
|
||||
|
||||
@@ -75,8 +85,9 @@ Cross-references (read these before implementing):
|
||||
metaballs in the existing fragment shader, sharing the *same plane* as the waveform **with real 2D
|
||||
collision** — the waveform pushes the fluid out of its way. Replace the navy↔moss treatment with a
|
||||
**three-color, OKLab-interpolated, per-segment-baked gradient** that animates along three combined
|
||||
motions. Replace the four-knob popover with a **six-knob flyout** styled to match the hero NowPlaying
|
||||
aesthetic. Remove the static noise texture that makes the screen look dirty.
|
||||
motions. Replace the four-knob popover with a **six-knob inline collapse/expand knob-bar** styled to
|
||||
match the hero NowPlaying aesthetic. Remove the static noise texture that makes the screen look dirty.
|
||||
Redraw the lava-lamp trigger glyph to the classic 1970s silhouette (§7f).
|
||||
|
||||
**In scope.**
|
||||
|
||||
@@ -89,7 +100,9 @@ aesthetic. Remove the static noise texture that makes the screen look dirty.
|
||||
height (§6).
|
||||
- **Six controls** replacing the four: scroll speed, gradient rotation speed, lava gravity, lava heat,
|
||||
blob density/size, collision strength (§7).
|
||||
- The **flyout** (replacing the popover) styled to the NowPlaying hero aesthetic (§7).
|
||||
- The **inline collapse/expand knob-bar** (replacing the popover) styled to the NowPlaying hero
|
||||
aesthetic (§7).
|
||||
- A **redrawn `DDIcons.LavaLamp`** glyph — classic 1970s lava-lamp silhouette (§7f).
|
||||
- **Overflow clipping** to the dynamic footer height (§2).
|
||||
- **Removing the static noise texture** (§3).
|
||||
|
||||
@@ -108,8 +121,8 @@ aesthetic. Remove the static noise texture that makes the screen look dirty.
|
||||
|
||||
**Reused vs. replaced — at a glance.**
|
||||
|
||||
| Layer | Reused from Phase 10 | Replaced by this reframe |
|
||||
|-------|----------------------|--------------------------|
|
||||
| Layer | Reused from Phase 10 (Waves 1–4) | Replaced by this reframe (R1–R4) |
|
||||
|-------|----------------------------------|----------------------------------|
|
||||
| WebGL2 pipeline / quad / vertex shader | ✅ as-is | — |
|
||||
| Datum texture + sampling | ✅ as-is | — |
|
||||
| Playhead interp + smoothing | ✅ as-is | — |
|
||||
@@ -120,7 +133,8 @@ aesthetic. Remove the static noise texture that makes the screen look dirty.
|
||||
| Color model (HSL navy↔moss) | — | OKLab three-color gradient, 3 motions (§6) |
|
||||
| Glass treatment | — | folded into the blob shading (§4f); no separate glass dials |
|
||||
| Static noise/frost texture | — | **removed** (§3) |
|
||||
| Controls (4 knobs, popover) | — | 6 knobs in a flyout (§7) |
|
||||
| Controls (4 knobs, popover) | — | 6 knobs in an inline collapse/expand bar (§7) |
|
||||
| Lava-lamp trigger glyph | trigger placement kept | glyph **redrawn** (§7f) |
|
||||
|
||||
---
|
||||
|
||||
@@ -383,19 +397,21 @@ Three theme colors X, Y, Z are in play. Over time, the gradient's two anchors **
|
||||
rainbow** — interpolate in **OKLab** (§6c) so the blend stays faithful to the three theme colors with no
|
||||
hue drift and no cyan excursion.
|
||||
|
||||
**Motion 2 — per-bar sinusoidal variation, baked at segment entry.**
|
||||
**Motion 2 — per-bar sinusoidal variation, baked at segment entry (chosen realization: mix-time-keyed).**
|
||||
Each bar's A and B vary slightly by a sinusoidal transfer, so the colors change in **"waves" across the
|
||||
waveform** rather than one uniform gradient. **Critical implementation requirement:** a segment's colors
|
||||
are **chosen when it enters (incoming, at the bottom) and stay FIXED for that segment as the waveform
|
||||
scrolls up, until it scrolls out of view.** Colors are **baked per-segment at entry, not recomputed per
|
||||
frame.** This implies **per-segment color state tied to scroll position** — the renderer must track, for
|
||||
each visible segment, the A/B colors assigned when it entered, and carry them with the segment as it
|
||||
scrolls. (Flagged as a notable implementation requirement: this is per-segment state, not a stateless
|
||||
per-fragment function. Staff-engineer designs the storage — likely a ring buffer keyed to scroll
|
||||
position, or baking the per-segment phase into the datum-time coordinate so the sinusoid is a pure
|
||||
function of mix-time and therefore *automatically* travels with the segment. The mix-time approach is the
|
||||
cleaner realization: if the per-bar sinusoid is keyed to the segment's mix-time rather than its current
|
||||
screen-Y, it is fixed-per-segment *by construction* and scrolls correctly with no explicit buffer.)
|
||||
frame.**
|
||||
|
||||
**Decided realization (Daniel, 2026-06-16): key the per-bar sinusoid to the segment's mix-time, not its
|
||||
screen-Y.** Daniel approved this approach explicitly ("whatever works and isn't a clusterfuck to
|
||||
maintain"). Because mix-time is fixed for a given segment, the sinusoid becomes a **pure function of
|
||||
mix-time** and is therefore **fixed-per-segment by construction** — it travels with the segment as it
|
||||
scrolls, with **no explicit per-segment ring buffer to maintain.** This is the chosen approach.
|
||||
**Rejected for maintainability:** an explicit ring buffer keyed to scroll position that tracks each
|
||||
visible segment's baked A/B colors — it is more moving parts and more state to keep coherent for the
|
||||
same visual result. Do not build it; use the mix-time-keyed sinusoid.
|
||||
|
||||
**Motion 3 — per-bar gradient curve shifts with scroll height.**
|
||||
Each bar's gradient *curve* (the A→B mix profile along its own height) shifts as it scrolls up. At the
|
||||
@@ -405,8 +421,8 @@ scroll height (its screen-Y / scroll position), composed on top of the A/B color
|
||||
for that segment.
|
||||
|
||||
The three motions compose: Motion 1 sets *which* two theme colors A and B are right now (rotating among
|
||||
X/Y/Z), Motion 2 perturbs A and B slightly per-segment in fixed-at-entry waves, and Motion 3 shifts the
|
||||
A→B blend curve along each bar as it climbs.
|
||||
X/Y/Z), Motion 2 perturbs A and B slightly per-segment in fixed-at-entry waves (keyed to mix-time), and
|
||||
Motion 3 shifts the A→B blend curve along each bar as it climbs.
|
||||
|
||||
### 6c. OKLab, not HSL — and why
|
||||
|
||||
@@ -426,7 +442,7 @@ OKLab. Drop the `mixHsl` / `vivify` / `VIVID_*` machinery entirely.
|
||||
|
||||
---
|
||||
|
||||
## 7. The six controls + the flyout
|
||||
## 7. The six controls + the inline collapse/expand knob-bar
|
||||
|
||||
### 7a. The six controls (replacing the four)
|
||||
|
||||
@@ -449,32 +465,40 @@ Defaults are Daniel's to tune on screen (his standing preference — he tunes ra
|
||||
live). Recommended starting points: scroll speed ~mid, rotation ~0.3, gravity ~0.5, heat ~0.3, density
|
||||
~0.4, collision ~0.5. These are feel-anchors, not commitments.
|
||||
|
||||
### 7b. Flyout, not popover — survey of MudBlazor options
|
||||
### 7b. The inline collapse/expand knob-bar (decided — NOT a popover or drawer)
|
||||
|
||||
**Reframe from Phase 10 §7:** the controls live in an **extended flyout menu bar**, not a popover.
|
||||
Clicking the lava-lamp icon makes the **RadialKnobs fly out** for editing.
|
||||
**Decision (Daniel, 2026-06-16): the controls are an inline collapse/expand knob-bar, NOT a floating
|
||||
popover or a drawer.** The six RadialKnobs live **inline in the controls area** (where the controls sit
|
||||
today) as an **`@if`-guarded flex row** that **animates open and closed in place**. It must read as
|
||||
**part of the controls collapsing/expanding** — the knob row expanding out from its predecessor — **not**
|
||||
a separate surface hanging off the icon.
|
||||
|
||||
MudBlazor options surveyed for "click an icon, knobs fly out into an editing strip":
|
||||
**The mechanism (no MudPopover, no MudDrawer):**
|
||||
|
||||
| Option | Fit | Verdict |
|
||||
|--------|-----|---------|
|
||||
| **`MudDrawer`** (`Anchor="Right"`/`Bottom"`, `Variant="Temporary"` or `"Mini"`) | A real drawer that slides in from an edge; `Open`-bound, overlay-dismissable, themeable. The "Mini" variant expands/collapses in place — close to a flyout bar. | **Recommended for an edge-anchored flyout strip.** A right or bottom temporary drawer reads as "the lava-lamp panel slid in," matches the "extended menu bar" language, and gives the six knobs room in a row/column. |
|
||||
| **`MudPopover` as a flyout** (the Phase 10 idiom, widened) | Anchored floating panel of arbitrary content; already in the codebase (`SharePopover`). Can be styled as a horizontal bar dropping from the icon. | **Acceptable, lighter-weight.** Closest to what Phase 10 shipped; if the flyout should *hang off the icon* rather than slide from a screen edge, a wide horizontal `MudPopover` styled as a knob bar is the smallest change. |
|
||||
| **`MudMenu`** | Built for actionable item lists, not a custom drag-interaction knob row. | **Rejected** — fights the knob drag/click model (same reasoning as Phase 10 §7d). |
|
||||
| **A bespoke CSS expanding panel** (no MudBlazor primitive) | Full control of the "menu bar extends" animation; an absolutely-positioned strip that animates width/opacity from the icon. | **Fallback** if neither drawer nor popover gives the exact "menu bar flies out" motion Daniel wants. More CSS to own. |
|
||||
- A **bound `bool`** (e.g. `_controlsExpanded`) gates the knob row. The **lava-lamp icon button toggles
|
||||
it** — the same `DDIcons.LavaLamp` trigger kept from Phase 10 §7c, now redrawn (§7f), now a
|
||||
collapse/expand toggle instead of a popover anchor.
|
||||
- When toggled open, the flex row of six knobs **animates open** via **CSS transition** — width / opacity
|
||||
/ transform — **expanding out from the icon / its predecessor element**, so it reads as the controls
|
||||
growing in place. When toggled closed it collapses back the same way.
|
||||
- **Animation intent:** a smooth in-place expansion (expand-from-icon / slide-open flex row), reading as
|
||||
one continuous collapse/expand of the controls area — not a panel popping into existence over the page.
|
||||
Use the codebase's existing transition vocabulary (the existing controls/transition CSS) so the motion
|
||||
feels native, not bolted on.
|
||||
- **No floating surface.** There is no overlay, no anchored popover panel, no edge drawer. The knob row is
|
||||
a real inline child of the controls area that occupies layout when open and collapses to nothing
|
||||
(or to just the icon) when closed.
|
||||
|
||||
**Recommendation:** start with a **horizontal `MudPopover` styled as a flyout knob bar** anchored to the
|
||||
lava-lamp icon (smallest delta from the landed §7 popover, keeps the icon-button trigger and the
|
||||
outside-click/overlay idiom already wired in `MixDetail.razor`), **unless** Daniel wants the controls to
|
||||
slide from a screen edge — in which case use a **`MudDrawer`** (`Anchor="Bottom"` reads most like an
|
||||
"extended menu bar"). This is a genuine fork on the desired *motion*; both are cheap. Surfaced as the one
|
||||
open question worth a Daniel call (§9).
|
||||
**Why this over the Phase 10 popover.** The popover read as a detached panel hanging off the icon; Daniel
|
||||
wants the controls to *be* the controls — collapsing and expanding in place. The inline animated flex row
|
||||
keeps the six knobs in the page's flow, makes the open/close a property of the controls themselves, and
|
||||
avoids the popover/drawer overlay machinery entirely. (Prior-art touchstone: an inline "expand for
|
||||
advanced settings" disclosure row — e.g. a toolbar that grows a secondary row of controls in place —
|
||||
rather than a flyout/menu.)
|
||||
|
||||
Either way: the six RadialKnobs live in the flyout, the lava-lamp icon button is the trigger (kept from
|
||||
§7c — `DDIcons.LavaLamp`, top-right of the body across from the back link), the flyout stays open while
|
||||
dragging a knob (the knob's global mouse-capture overlay must not be read as an outside-click — verify;
|
||||
gate dismiss-on-outside-click off mid-drag if needed, as Phase 10 §7d already noted), and no flyout
|
||||
element is a seek surface.
|
||||
**Layout note.** Six knobs in a flex row may wrap on narrow viewports (2×3 / 3×2) — a layout call, but
|
||||
all six must remain reachable, and the wrap must still read as part of the inline collapse/expand (the
|
||||
whole block grows/shrinks), not as a separate surface.
|
||||
|
||||
### 7c. State — widen to six properties
|
||||
|
||||
@@ -485,7 +509,7 @@ that maps to it — staff-engineer's call), `GradientRotationSpeed` (rename of `
|
||||
`const` default mirrored to the TS tuning anchors (keep the C#↔TS default-sync discipline the existing
|
||||
`Default*` consts have). Same scoped-DI persistence model: survives SPA nav within a session, resets on
|
||||
fresh load. Same `Changed` event seam — the bridge subscribes and pushes the affected uniform; the
|
||||
flyout component only mutates state and raises `Changed`. **This is the same architecture as today, just
|
||||
knob-bar component only mutates state and raises `Changed`. **This is the same architecture as today, just
|
||||
six properties instead of four.**
|
||||
|
||||
The bridge handle gains setters for the new controls (`setScrollSpeed`, `setGradientRotationSpeed`,
|
||||
@@ -496,7 +520,7 @@ mirroring how Phase 10 §2d extended the handle.
|
||||
|
||||
`RadialKnob` (`DeepDrftShared.Client/Components/RadialKnob.razor`) is consumed as-is (its API is fixed —
|
||||
`Value`/`ValueChanged`/`Min`/`Max`/`Step`/`Label`/`Size`/`Color`/`HoldValue`; no icon slot; `Label` is
|
||||
SVG text). Six knobs in the flyout, each with an adjacent `MudIcon` caption (the no-icon-slot
|
||||
SVG text). Six knobs in the inline bar, each with an adjacent `MudIcon` caption (the no-icon-slot
|
||||
constraint from Phase 10 §7e still holds). `HoldValue=false` so they are live. `Step="0.001"` for
|
||||
continuous feel. Suggested Material icons per control (staff-engineer picks final glyphs):
|
||||
|
||||
@@ -514,25 +538,78 @@ reachable.
|
||||
|
||||
### 7e. Aesthetic target — match the NowPlaying hero
|
||||
|
||||
**The flyout's color and structure must match the "NowPlaying" section in the hero.** The closest
|
||||
**The knob-bar's color and structure must match the "NowPlaying" section in the hero.** The closest
|
||||
existing component to that aesthetic in the codebase is the **Session detail hero**
|
||||
(`DeepDrftPublic.Client/Pages/SessionDetail.razor` + `.css`) — the hero-dominant overlay composition: a
|
||||
large background image with a darkening gradient shim (`.session-hero-shim`), and overlay rows
|
||||
(`.session-hero-top` / `.session-hero-bottom`) carrying title/artist, genre/date chips, and the play
|
||||
affordance with translucent surfaces over the image. The structural cues to borrow:
|
||||
|
||||
- A **translucent dark surface** (the shim aesthetic) so the flyout reads as floating glass over the
|
||||
- A **translucent dark surface** (the shim aesthetic) so the knob-bar reads as floating glass over the
|
||||
visualizer, not an opaque panel.
|
||||
- The **overlay-chip / overlay-label typography** (`.session-overlay-label` / `.session-overlay-value`)
|
||||
for the knob captions, so the flyout's labels match the hero's.
|
||||
for the knob captions, so the bar's labels match the hero's.
|
||||
- `Color.Secondary` accents (the play affordance and the lava-lamp trigger both use `Color.Secondary`) —
|
||||
keep the knobs/captions on the same accent so the flyout feels of-a-piece with the hero.
|
||||
keep the knobs/captions on the same accent so the bar feels of-a-piece with the hero.
|
||||
|
||||
Staff-engineer studies `SessionDetail.razor[.css]` and matches its surface color + structural rhythm.
|
||||
The intent: open the flyout and it looks like it belongs to the same design family as the session hero's
|
||||
now-playing overlay, not a generic MudBlazor panel. (If Daniel has a *specific* NowPlaying component in
|
||||
mind other than the session hero overlay, confirm — but the session hero is the strongest match in the
|
||||
current tree.)
|
||||
The intent: expand the knob-bar and it looks like it belongs to the same design family as the session
|
||||
hero's now-playing overlay, not a generic MudBlazor panel — even though it is an inline collapse/expand
|
||||
element, not a floating one (§7b). (If Daniel has a *specific* NowPlaying component in mind other than
|
||||
the session hero overlay, confirm — but the session hero is the strongest match in the current tree.)
|
||||
|
||||
### 7f. Redraw the lava-lamp glyph — classic 1970s silhouette
|
||||
|
||||
**Decision (Daniel, 2026-06-16): the current `DDIcons.LavaLamp` is rejected ("form is shit, colors are
|
||||
shit") and must be redrawn** to the classic 1970s "Lava" lamp silhouette (Daniel supplied a reference
|
||||
image). The trigger placement (top-right, across from the back link) is unchanged; only the glyph art
|
||||
changes.
|
||||
|
||||
**Home & authoring convention.** Authored in `DeepDrftShared.Client/Common/DDIcons.cs` as **inner SVG
|
||||
markup only — no outer `<svg>` wrapper** (MudBlazor supplies the wrapper). A **24×24 viewBox** coordinate
|
||||
space (matches the MudBlazor `viewBox="0 0 24 24"` wrapper and the existing `DDIcons` convention). A
|
||||
`public const string` raw-string literal, same as the other icons in the file.
|
||||
|
||||
**Silhouette (bottom → top) — "offset cones":**
|
||||
|
||||
1. A **WIDE truncated-cone metal BASE** — widest at the very bottom, tapering *up* to a narrow waist.
|
||||
2. A tall tapered **GLASS VESSEL** sitting on the base — **bulbous/rounded at the bottom**, tapering
|
||||
**upward** to a **roundedly-POINTED top** (an elongated teardrop / bullet shape — pointy-ish but
|
||||
**NOT sharp**).
|
||||
3. A small **truncated-cone metal CAP** on top, **mirroring the base**.
|
||||
|
||||
The read is: cone base + tapered teardrop body + small cone cap. This is the iconic 1970s Lava lamp
|
||||
profile — distinct from the current narrow straight-sided vessel, which is rejected.
|
||||
|
||||
**Colors (on-theme AND faithful to the reference).** The reference shows a silver metal base/cap, blue
|
||||
fluid, and green blobs. Map to the app theme:
|
||||
|
||||
- **Fluid: navy. Blobs: moss.** Navy and moss **are** the theme's blue + green, so this is both faithful
|
||||
to the reference and on-theme by construction.
|
||||
- **Base + cap: neutral / metallic** (the silver of the reference).
|
||||
- The **body silhouette (glass vessel outline) can be `currentColor`** so it tints with context
|
||||
(`Color.Secondary`, light/dark) exactly as the existing icons do. The **fluid and blobs carry the
|
||||
navy/moss accents** as the icon's color identity.
|
||||
|
||||
**Keeping the icon theme-aligned (the one source-of-truth wrinkle).** The single source of truth for
|
||||
theme colors is `DeepDrftPalettes` (§6a), but an inline SVG `const string` in `DDIcons.cs` **cannot
|
||||
resolve `var(--mud-palette-*)`** — a fill on an SVG path inside a raw-string literal must be a literal
|
||||
value (or `currentColor`). So the navy/moss fluid/blob stops will need to be **literal hex stops** in the
|
||||
SVG. To minimize the duplication-of-truth this creates:
|
||||
|
||||
- Prefer **`currentColor` for everything that can be** (the body silhouette, ideally the metal base/cap
|
||||
via a neutral-tinted variant) so the bulk of the icon themes for free.
|
||||
- For the two accent fills that genuinely must be literal (navy fluid, moss blobs), **use the exact
|
||||
`DeepDrftPalettes` navy/moss hexes** (e.g. navy `#17283f`, moss `#3D7A68`) and **add a code comment in
|
||||
`DDIcons.cs` naming the `DeepDrftPalettes` member each literal mirrors**, so the two literals are
|
||||
explicitly traceable to the source and a future palette change has a documented sync point. This is the
|
||||
same `currentColor`-where-possible + commented-literal-where-not discipline the existing gas-lamp flame
|
||||
icon already uses (its `#FF9800`/`#FFCA28` flame stops are literals on an otherwise-`currentColor`
|
||||
lamp). The hard requirement: **no silent second copy of the palette** — `currentColor` first, commented
|
||||
literal only where SVG forces it.
|
||||
|
||||
(The precise path data is staff-engineer's; this fixes the silhouette, the color mapping, the authoring
|
||||
convention, and the theme-alignment discipline — not the exact coordinates.)
|
||||
|
||||
---
|
||||
|
||||
@@ -572,86 +649,96 @@ current tree.)
|
||||
blend stays faithful to the theme colors at all rotation phases.
|
||||
13. **Anchor rotation.** A and B rotate among X/Y/Z over time at the gradient-rotation-speed rate;
|
||||
dragging the control visibly changes the rotation rate, never frozen at the slow end.
|
||||
14. **Per-segment bake.** A segment's colors are fixed when it enters at the bottom and travel with it
|
||||
unchanged as it scrolls up and out — colors do not recompute under a stationary segment.
|
||||
14. **Per-segment bake (mix-time-keyed).** A segment's colors are fixed when it enters at the bottom and
|
||||
travel with it unchanged as it scrolls up and out — colors do not recompute under a stationary
|
||||
segment. (Realized via the mix-time-keyed sinusoid, §6b motion 2.)
|
||||
15. **Per-bar curve shift.** A bar is mostly A at the bottom and mostly B by the top — color appears to
|
||||
move outward as the bar climbs.
|
||||
16. **One source of truth.** No hardcoded theme hexes in the visualizer; a `DeepDrftPalettes` edit or a
|
||||
dark-mode toggle re-themes the field live with no duplicate to maintain.
|
||||
dark-mode toggle re-themes the field live with no duplicate to maintain. (The icon's two accent
|
||||
literals are the documented, commented exception — §7f.)
|
||||
|
||||
**Controls / flyout**
|
||||
**Controls / knob-bar**
|
||||
|
||||
17. **Six controls.** Exactly six RadialKnobs — scroll speed, gradient rotation speed, gravity, heat,
|
||||
density/size, collision strength — each captioned with an icon; resolution/zoom as a standalone
|
||||
control is gone.
|
||||
18. **Flyout.** Clicking the lava-lamp icon flies the knobs out (drawer or popover-flyout per the §7b
|
||||
decision); clicking outside closes; dragging a knob does not close it.
|
||||
19. **NowPlaying aesthetic.** The flyout's surface color + structure match the session hero now-playing
|
||||
18. **Inline collapse/expand.** Clicking the lava-lamp icon expands the six-knob flex row **in place**
|
||||
(animated open/closed via CSS transition), reading as the controls collapsing/expanding — **not** a
|
||||
floating popover or drawer. Clicking again collapses it; dragging a knob does not collapse it.
|
||||
19. **NowPlaying aesthetic.** The knob-bar's surface color + structure match the session hero now-playing
|
||||
overlay (translucent dark glass, overlay-label typography, `Color.Secondary` accents).
|
||||
20. **Persistence + read-only.** All six positions survive SPA nav within a session, reset on fresh
|
||||
load; no control and no flyout element is a seek/playback surface; the bridge and read-only contract
|
||||
load; no control and no knob-bar element is a seek/playback surface; the bridge and read-only contract
|
||||
are intact.
|
||||
|
||||
**Icon**
|
||||
|
||||
21. **Redrawn lava-lamp glyph.** The trigger shows the classic 1970s silhouette — wide truncated-cone
|
||||
base, bulbous→roundedly-pointed teardrop glass body, small cone cap — with navy fluid + moss blobs
|
||||
and a neutral/metallic base+cap; body tints via `currentColor`; renders cleanly at ~24px.
|
||||
|
||||
**Performance**
|
||||
|
||||
21. **60 FPS** on a mid-range desktop with heat, density, and collision at non-trivial values
|
||||
22. **60 FPS** on a mid-range desktop with heat, density, and collision at non-trivial values
|
||||
simultaneously; graceful degrade (drop internal resolution before frames) on weaker/mobile devices.
|
||||
|
||||
---
|
||||
|
||||
## 9. Suggested phasing / waves
|
||||
## 9. Suggested phasing / waves (R1–R4)
|
||||
|
||||
A **physics-and-collision first, color second, flyout third** sequence — the lava is the real work and
|
||||
the riskiest, so prove it before the gradient and the UI rework.
|
||||
A **physics-and-collision first, color second, knob-bar third** sequence — the lava is the real work and
|
||||
the riskiest, so prove it before the gradient and the UI rework. **These are reframe waves R1–R4, folded
|
||||
under the open Phase 10 and distinct from its landed Waves 1–4.**
|
||||
|
||||
### Wave 1 — De-noise + footer clip (cheap, unblocks a clean canvas)
|
||||
Remove the static noise/frost layer (§3) and implement the dynamic footer-height clip + lava-rest line
|
||||
(§2c). Small, independent, and gives a clean substrate to build the lava on. **Acceptance:** §8 #3, #4.
|
||||
### Wave R1 — De-noise + footer clip + icon redraw (cheap, unblocks a clean canvas)
|
||||
Remove the static noise/frost layer (§3), implement the dynamic footer-height clip + lava-rest line
|
||||
(§2c), and **redraw the `DDIcons.LavaLamp` glyph** (§7f — independent, can land anytime, grouped here as
|
||||
cheap polish). Small, independent, and gives a clean substrate to build the lava on. **Acceptance:** §8
|
||||
#3, #4, #21.
|
||||
|
||||
### Wave 2 — The wax-blob physics + collision (the load-bearing step)
|
||||
### Wave R2 — The wax-blob physics + collision (the load-bearing step)
|
||||
Stand up the CPU physics step (16–32 blobs: position/velocity/temperature/radius), the per-frame uniform
|
||||
upload, the `smin` metaball render, the heat/gravity/density mapping, and the 2D collision model (both
|
||||
pairs, the soft↔hard blend). This is where the architecture is proven; it replaces the §4-effect GLSL.
|
||||
**Acceptance:** §8 #1, #5–#11, #21 (at this wave's workload). Controls can be temporary sliders/debug
|
||||
knobs here — the real flyout is Wave 4.
|
||||
**Acceptance:** §8 #1, #5–#11, #22 (at this wave's workload). Controls can be temporary sliders/debug
|
||||
knobs here — the real inline knob-bar is Wave R4.
|
||||
|
||||
### Wave 3 — The OKLab three-color gradient (the three motions)
|
||||
### Wave R3 — The OKLab three-color gradient (the three motions)
|
||||
Replace the HSL `mixHsl`/`vivify` color with OKLab interpolation; implement the three motions (anchor
|
||||
rotation among X/Y/Z, per-segment baked sinusoidal variation, per-bar curve shift), sourced from
|
||||
`DeepDrftPalettes` with no hardcoded duplicates. **Acceptance:** §8 #12–#16. The per-segment-bake
|
||||
requirement (§6b motion 2) is the subtle part — prefer the mix-time-keyed realization so it travels with
|
||||
the segment by construction.
|
||||
rotation among X/Y/Z, per-segment baked sinusoidal variation **keyed to mix-time**, per-bar curve shift),
|
||||
sourced from `DeepDrftPalettes` with no hardcoded duplicates. **Acceptance:** §8 #12–#16. The
|
||||
per-segment-bake requirement (§6b motion 2) uses the mix-time-keyed realization so it travels with the
|
||||
segment by construction (decided — §6b).
|
||||
|
||||
### Wave 4 — Six controls + the NowPlaying-styled flyout
|
||||
### Wave R4 — Six controls + the NowPlaying-styled inline knob-bar
|
||||
Widen `MixVisualizerControlState` to six properties; replace the four-knob popover with the six-knob
|
||||
flyout (drawer or popover-flyout per §7b); style it to the session-hero aesthetic; extend the bridge
|
||||
handle with the new setters. **Acceptance:** §8 #17–#20.
|
||||
**inline collapse/expand knob-bar** (§7b — `@if`-guarded animated flex row, lava-lamp icon toggles it, no
|
||||
popover/drawer); style it to the session-hero aesthetic; extend the bridge handle with the new setters.
|
||||
**Acceptance:** §8 #17–#20.
|
||||
|
||||
**Dependency shape:** `Wave 1 → Wave 2 → (Wave 3 ‖ Wave 4)`. Wave 1 is a quick unblock. Wave 2 is the
|
||||
prerequisite for everything visual. Waves 3 (color) and 4 (controls/flyout) both depend on Wave 2 but are
|
||||
independent of each other — the gradient can land before the flyout, or vice versa, and each control's
|
||||
effect is independently tunable. Daniel tunes ranges/transfer-functions by hand once on screen
|
||||
throughout (his standing preference).
|
||||
**Dependency shape:** `Wave R1 → Wave R2 → (Wave R3 ‖ Wave R4)`. Wave R1 is a quick unblock (and folds in
|
||||
the independent icon redraw). Wave R2 is the prerequisite for everything visual. Waves R3 (color) and R4
|
||||
(controls/knob-bar) both depend on Wave R2 but are independent of each other — the gradient can land
|
||||
before the knob-bar, or vice versa, and each control's effect is independently tunable. Daniel tunes
|
||||
ranges/transfer-functions by hand once on screen throughout (his standing preference).
|
||||
|
||||
---
|
||||
|
||||
## 10. Open items
|
||||
|
||||
Tuning knobs and one genuine fork. None block starting Wave 1.
|
||||
Tuning knobs only — the controls-UI fork and the per-segment-storage fork are both now **decided** (§7b
|
||||
inline knob-bar; §6b mix-time-keyed). None block starting Wave R1.
|
||||
|
||||
- **§7b — flyout primitive (the one Daniel call worth making up front):** horizontal `MudPopover`
|
||||
styled as a knob bar (smallest delta, hangs off the icon) **vs.** `MudDrawer Anchor="Bottom"` (slides
|
||||
from a screen edge, reads most like an "extended menu bar"). Both cheap; the choice is about the
|
||||
*motion* Daniel wants. Recommend popover-flyout unless he wants the edge-slide.
|
||||
- **§4c, §5d — transfer functions:** heat 0..1 → rise/morph intensity; collision 0..1 → soft↔hard blend
|
||||
shape; restitution coefficients; penetration-penalty curve. All staff-engineer tuning tasks with the
|
||||
endpoints fixed here.
|
||||
- **§4g — blob count band** within 16–32 and the density-control mapping to count vs. radius.
|
||||
- **§6a — exact X/Y/Z theme-var bindings** per light/dark for the richest spread (the palette is the
|
||||
source either way).
|
||||
- **§6b motion 2 — per-segment color storage** (ring buffer vs. mix-time-keyed sinusoid — recommend
|
||||
mix-time-keyed so it travels by construction).
|
||||
- **§7a — scroll-speed mapping:** reuse `MixZoomMapping` as a scroll-rate map vs. a fresh linear map.
|
||||
- **§7e — NowPlaying source:** confirm the session hero overlay is the intended "NowPlaying" aesthetic
|
||||
(strongest match in the tree) or point to a different component.
|
||||
- **§7f — icon accent literals:** the two literal navy/moss stops the SVG forces (commented to their
|
||||
`DeepDrftPalettes` source) — exact hexes are staff-engineer's to pull from the palette.
|
||||
- **Defaults** for all six controls — Daniel tunes on screen.
|
||||
Reference in New Issue
Block a user