@namespace DeepDrftPublic.Client.Controls @using DeepDrftPublic.Client.Services @inject WaveformVisualizerControlState ControlState @* The waveform visualizer controls. EIGHT continuous RadialKnobs — scroll speed, gradient rotation speed, lava gravity, lava heat, fluid amount, fluid viscosity, collision strength, waveform width — each its own dedicated control with a Material-icon caption. The single "bubbles" knob is split into fluid-amount + fluid-viscosity (Phase 10 §5). Visibility (Phase 10 §4): the host ALWAYS renders this component now and feeds the lava-lamp toggle into the @Visible parameter. THIS component decides knob visibility — it @if-gates the knobs but keeps the container's reserved size, so the content below the controls bar never pops when the lamp toggles. The gating is Blazor @if (matching the established "@if-gated knob band, no CSS hide/glass/animation" convention) — the knobs are simply not rendered when hidden, while a min-height container holds the layout. No collapse animation, no glass surface, no CSS visibility-hiding of populated knobs. It owns NO JS interop: it mutates the shared, session-scoped WaveformVisualizerControlState and raises its Changed event. The backdrop bridge (WaveformVisualizer) subscribes to that event and pushes the affected dial to the WebGL module. That keeps the JS module handle single-owned by the bridge and this component purely presentational. None of these is a seek surface (read-only contract §D). RadialKnob has no icon slot (its Label renders as SVG text) and no aria attribute-capture, so each control's Material icon rides beside its knob as an adjacent MudIcon caption and the accessible name rides on the wrapping group div (§7d). HoldValue stays false so the knobs are live — ValueChanged fires continuously during drag, preserving the Changed/NotifyChanged seam. *@
@code { ///