- Add AI SYNC button to timeline toolbar, panel hidden by default (D-08)
- Panel: feature toggles (BEATS, ONSETS, CHROMA, RMS), GENERATE button, USE LLM toggle
- GENERATE disabled until audio loaded; re-enables on loadedmetadata event
- LLM toggle enabled/disabled based on /api/sync/llm-available at page load
- D-07: confirmation dialog before replacing existing timeline blocks
- D-11: section_range passed when a segment is selected in the overlay
- Segment selection watcher (200ms interval) updates info text dynamically
- Add AI sync panel styles — flat terminal aesthetic, no border-radius
- Add yt-url input, FETCH button, and yt-progress span to transport bar
- Add fetchWithProgress() SSE ReadableStream reader function
- Add renderProgressBar() terminal-style block fill renderer (DOWNLOADING ████)
- Wire FETCH button click handler with D-02 disable-during-download behavior
- Auto-load audio into player after download (D-01 same pipeline as upload)
- Add .yt-url-input and .yt-progress CSS styles (flat, monospace, no border-radius)
- Enable yt-url input on page load via JS
- Add #live-preview div between timeline-canvas and block-inspector
- Add show selector (show-select + btn-load-show) to transport bar
- Add keyboard-hint span at far right of transport bar
- Append .live-preview, .device-strip, .strip-label, .strip-color, .strip-anim, .keyboard-hint CSS styles
- Replace timeline placeholder with waveform canvas + playback cursor
- Replace transport placeholder with full transport bar controls
- Add play/pause/stop buttons, seek slider, time display, audio path input
- Add drawWaveform(), loadWaveform(), updatePosition(), formatTime() to app.js
- Dispatch msg.type=tick to updatePosition in handleMessage
- Wire transport buttons via WebSocket commands
- Add transport/waveform styles to style.css using existing CSS variables
- Deploy via ~/bin/deploy.sh
- Add <form id='add-device-form'> to DEVICES panel with 5 inputs (name, strip_type, led_count, ip, port) and submit button
- Add apiPost() and apiDelete() helper functions to app.js
- Update loadDevices() to render device rows with remove button (.device-remove)
- Add removeDevice(id) function with DELETE /api/devices/{id} + window export for onclick
- Add form submit handler: POST /api/devices, form reset, refresh device list
- Add panel IDs: devices-panel, animations-panel, timeline-panel, transport-panel to index.html
- DeviceRegistry with load/save/add/remove/instantiate and _DEVICE_CLASSES dict
- ShowStore with save/load/list_ids using aiofiles for async I/O
- FastAPI app with lifespan hook (startup: load registry/store, shutdown: save registry)
- API routes: GET/POST /api/devices/, DELETE /api/devices/{id}, GET/POST /api/shows/, GET /api/shows/{id}
- WebSocket stub at /ws with ConnectionManager and ack echo
- Frontend shell: DAW layout with header, sidebar (DEVICES + ANIMATIONS), TIMELINE, TRANSPORT
- Terminal aesthetic: dark theme, cyan accents, monospace fonts, no drop shadows
- .gitignore for runtime data (devices.json, shows/, __pycache__, .venv)