Adds a docs overlay that lives inside the rack chrome, opened from a new
MANUAL hw-btn in the top bar (ESC also closes). Styled as a screen recess
matching the editor — amber section headers, engraved labels, recessed code
blocks — so it reads as a manual page of the instrument, not a help popup.
Covers patch language, execution model, every node type (osc, trig, adsr,
filter, noise, seq, delay, poly+voice) and the four control nodes (knob,
fader, step_seq, piano_roll), plus practical tips on gain staging and
hot-reload behavior. Each example block carries a TRY button that swaps the
editor contents with the snippet so you can hear it immediately (Ctrl/Cmd-Z
to bring your patch back).
wget inside the alpine container resolves `localhost` to ::1, but nginx
only binds IPv4 with `listen 80;`, so the healthcheck saw 'Connection
refused' even though the container was happily serving traffic to Caddy.
Pinning the check to 127.0.0.1 keeps it strictly IPv4.
The web/ directory is fully self-contained (index.html + worklet.js, all JS
deps pulled from esm.sh via the importmap). Package it as a tiny nginx:alpine
image so Coolify can build + serve it behind Caddy.
- Dockerfile: nginx:1.27-alpine, copies web/ to the document root, healthcheck.
- nginx.conf: serves /, no-cache for index.html and worklet.js (so engine
changes land immediately after a redeploy), short cache for everything else,
gzip on text payloads, JS MIME for AudioWorklet.
- .dockerignore: keep the image small (excludes Python sources, docs,
references, sandbox is included since it's served from /sandbox/).
Aligns web/index.html with the design language captured in docs/design-system.md
(reference: web/sandbox/studio.html). The whole UI now reads as a single rack
module: corner screws, top/bottom bars, screen recess, and L2 sub-panels.
- Replace dark-blue token palette with the warm-neutral hardware palette
and the shared --metal-specular / --metal-brush / --metal-bevel layers.
- Wrap header + main + footer in a .hardware shell with 4 corner screws.
- Editor lives inside a .screen recess (deep inset shadows, transparent
CodeMirror background, amber cursor + selection).
- Splitter is now a hairline that lights amber on hover/drag.
- Right pane groups widgets by kind into shared sub-panels (.knobs, .faders,
.seq); each piano_roll is its own panel.
- drawKnob ported with all 8 layers (drop shadow, amber arc, dark rim,
metallic disc with concentric brushing + vertical lighting + specular
band + rim light + bevel + inset + engraved notch). DPR-aware canvas.
- Faders use a deep slot track with side ticks and a metallic cap.
- Step seq cells become .led with amber glow + beat dividers.
- Piano roll keys + cells recolored to warm/amber palette.
- Wave widgets render with amber glow on a recessed background.
- RUN/STOP button group with led swap; bottom-bar shows IDLE/RUNNING.
Also: ignore local-only /referencias (heavy reference images, not source).
Captures every decision made during the studio.html sandbox iteration
so the same visual language can be applied to the rest of the app
(and to new components later) without re-deriving it.
Sections:
- Vision + reference instruments
- Lighting model (single rule: light from above)
- Color tokens with semantic naming
- The 3-layer "metal" language as shared CSS custom properties
- Surface hierarchy (3 depth layers with progressively brighter bases)
- Component anatomies: rack, bars, screen, sub-panels, knobs, faders,
step LEDs, buttons, screws, engraved labels, numeric displays
- Typography, spacing scale, interaction conventions
- "What is intentionally NOT here" — rejected ideas to keep the
language disciplined
- A "how to add a new component" checklist
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The amber arc was drawn at radius ~30px from center on a 56×56
canvas — the bottom of the arc (at angles near 6 o'clock) sat at
y ≈ 58 and got clipped by the canvas's own bounding box. Visible
as a flat cut-off at extreme positions.
Fix: bump the canvas to 72×72 and use fixed-pixel values for the
knob's geometry instead of fractions of `size`, so the visible knob
diameter stays at ~52px regardless of canvas size and there's now
~10px of margin all around for the arc and drop shadow.
- KNOB_SIZE: 56 → 72
- totalR: size * 0.46 → 26 (fixed)
- rimW: size * 0.045 → 2.5 (fixed)
- notch half-base: size * 0.026 → 1.5 (fixed)
- cy: size/2 + 1 → size/2 (no need for the offset on the larger canvas)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four channel-volume faders matching the patch (KICK/HAT/MEL/MIX),
in their own sub-panel with the same brushed-metal treatment as
.knobs and .seq.
- Track is a deep slot cut into the panel — heavy inset shadow,
thin highlight at the bottom edge for chamfer feel.
- Side ticks drawn with repeating-linear-gradient (1px on / 6px off).
- Cap uses the same metal language as the knob disc: brushed stripes
+ vertical light gradient + grip line in the middle + 4-edge bevel
via inset shadows + drop shadow underneath.
- Click anywhere on the track jumps the cap to that value, then
dragging continues. Pointer capture on the track itself so the cap
follows even outside the bounds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same metal treatment now applies to the outer hardware frame, the
top/bottom bars and the sub-panels (knobs + seq). Three CSS custom
properties capture the shared visual language so each frame just
plugs them in:
- --metal-specular: vertical gradient with a soft bright band on the
upper portion
- --metal-brush: very fine repeating horizontal stripes
- --metal-bevel: 4-edge inset shadow set (bright top + dark bottom +
highlighted left + dark right)
Per-element base colours retain a depth hierarchy: the outer
.hardware is the darkest, top/bottom bars sit slightly brighter, and
.knobs/.seq are the brightest plates so they read as mounted on top.
Drop shadows scaled to scope: .hardware gets a strong 0 8px 32px,
the bars get a small 0 2px 4px, and the sub-panels keep their two
layered drop shadows for depth.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same lighting language as the knob disc, adapted for rectangular
panels (horizontal brushing instead of concentric).
Layered backgrounds:
- (1) horizontal specular band on the upper portion of the panel
- (2) very fine repeating horizontal stripes (brushed steel feel)
- (3) base vertical gradient (light from above on dark anodised metal)
Bevel via inset box-shadows: bright top edge + dark bottom edge +
faint side highlights/shadows. Drop shadow under each panel gives
visual depth so they read as separate plates mounted on the rack.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous version was too flat. Real metal needs concentric brushing
(not radial), a strong horizontal specular band, multiple light
sources and a defined bevel.
Disc rendering now layers:
- Radial base gradient (matte foundation, slightly dark at edge)
- Concentric brushing rings (lathe-turned aluminium, alternating
bright/dark with deterministic pseudo-random alpha)
- Vertical lighting overlay (light-from-above gradient)
- Horizontal specular band on the upper portion (light source reflection)
- Subtle rim light from below (typical of softbox-lit studio gear)
- Bright bevel crescent on the upper edge + dark crescent on the lower
- Inset shadow line where disc meets the dark rim
Indicator notch refined to read as engraved (dark groove + thin
bright lower lip catching light on the inner edge).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reading the close-up: the knob is dominated by a big metallic chrome
disc that occupies most of its surface. The dark part is just a thin
outer rim. The indicator is a small dark notch on the disc that
rotates with the value (the disc itself stays vertically lit).
- Thin dark rim around the outside (~3px @ 56).
- Large metallic disc fills the inside (radial gradient, brushed-metal
striations from center outward, top crescent highlight).
- Indicator is a small dark triangular notch on the disc, base near
the center, tip toward the rim, rotated to the value angle.
- Amber arc kept outside everything as a value-progress meter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three changes following the reference more closely:
1. Knobs now have a metallic outer bezel (chrome ring): vertical
gradient running silver at the top → dark at the bottom, with a
thin highlight on the upper crescent. The dark dial sits inside
it with a slight inner shadow showing depth. Size bumped to 56px
so the bezel is visible.
2. Layout split into two stacks:
- left-stack: top-bar / screen / bottom-bar (vertical strip)
- right-stack: knobs / seq
3. Top bar: STOP+RUN as a tight pair (no gap), buttons stretch to
the bar's full height. Bottom bar matches the top bar visually
and shows a "● RUNNING_" label with the pulsing amber dot, no
longer inside the code area.
4. Code area is now *recessed* into the rack — no separate bordered
panel. Inset shadows + slightly darker background simulate a
cutout / screen window in the metal frame.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aligning the mockup more closely with the reference image:
- Knob body is now a pure charcoal/black radial gradient (no warm
brown tint). Top-left specular dim, top crescent gloss, outer dark
ring. Drop shadow underneath so the knob "sits on" the panel.
- Value readouts ("120.0", "2.50", ...) in cream/white, no inset
amber LCD frame. Amber is reserved for arcs / LEDs / bullet labels
exclusively.
- Panel palette pulled toward neutral dark (less brown saturation).
- Sidebar with the description bullets removed; layout is just the
hardware unit at full width.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A fourth aesthetic direction beyond the three knob variants — based
on the user's reference image (Moog/Roland/Korg vintage rack gear).
- Warm amber+charcoal palette (replaces the cyan phosphor accent).
- Beveled metal panels with corner screws (radial-gradient circles
with a slot mark).
- Knobs: brushed-metal radial gradient, knurled perimeter ridges,
specular highlight, white-warm engraved indicator, amber arc with
glow.
- LEDs for step cells: dim amber-off when inactive, full amber-on
with radial glow when active. Animated playhead outline at 8 Hz.
- Code "screen" with engraved-screen feel (inset shadow, faint amber
bloom). Status line "> RUNNING_" with blinking cursor.
- Engraved labels (small caps, double text-shadow for inset).
- Tabular numeric value displays in their own dark inset readouts
(LCD-style).
- Header buttons (STOP / RUN) with green run LED, pulsing red status.
Static mockup — no audio engine wired. Knobs are draggable to evaluate
the feel; step LEDs toggle on click. Decision pending: pick this or
one of A/B/C from knobs.html and align all surfaces to that language.
Standalone page at web/sandbox/knobs.html showing three aesthetic
directions side-by-side:
- A "hardware": radial gradient + perimeter ridges + specular highlight,
reads as a photographed knob.
- B "geometric": flat shapes, dot indicator at perimeter + short tick
from center; OP-1 / diagram register.
- C "phosphor": outline + heavy glow on accent arc and indicator;
synthwave / vacuum-tube feel.
Each variant shows 4 static knobs (0/33/66/100%) plus an interactive
draggable instance. DPR-aware canvas, vertical drag with shift-fine,
double-click to recenter. Pick one and the rest of the surfaces align.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds docs/roadmap.md outlining the 4-track plan (foundation, surface
aesthetics, organizable panel, theming) and ships the first track.
- Resizable splitter between editor and control surface (drag the seam,
double-click to reset). Width persists in localStorage.
- Custom scrollbars (WebKit pseudo-elements + Firefox scrollbar-color)
applied globally so CodeMirror's .cm-scroller, the right pane and the
piano roll all match the dark theme.
- Header separators between transport / gain / info groups.
- Smooth transitions on buttons, range thumbs and surface borders.
- :focus-visible rings using accent-glow color token.
- Pulse animation on the live status dot.
- New design-system tokens for layout (--right-w, --splitter-w),
timing (--t-fast/base/slow), and panel hierarchy (--panel-hi,
--gutter-hi, --divider, --fg-mute, --accent-glow).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Patch language with osc/noise/trig/seq/adsr/filter/delay/poly + voice templates
and inline live values. Two runtimes:
- code_sinth/ — Python engine (numpy + sounddevice). Hot-reload via mtime
watcher. Offline render to WAV. Static-HTTP+WS visualizer (viz/) that
injects waveforms next to each `node X = ...` line.
- web/ — port of the engine to JS running in AudioWorklet. Single static
page with CodeMirror 6 editor (line widgets for live waveforms) and a
control surface on the right with knobs/faders/step_seq/piano_roll
declared from the patch. State preserved across hot-reload.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>