HALightOutputTarget gains a `source_kind` field with two modes:
- `css` (existing): per-mapping LED segments averaged from a ColorStripSource.
- `color_vs` (new): one colour from a colour-returning ValueSource pushed to
every mapped entity (mapping LED ranges are ignored in this mode).
Backend wiring:
- Schema/route: add `source_kind` + `color_value_source_id` to create/update/
response payloads, with VS existence + return_type=color validation.
- Storage: persist new fields, with defensive `or ""` coalesce so legacy rows
written via resolve_ref with None survive the str-typed response schema.
- Processor: ha_light_target_processor reworked to drive both source kinds
(incl. update_target_settings hot-swap of source mode). New unit tests in
tests/core/test_ha_light_target_processor.py and extended store tests.
Frontend:
- ha-light editor modal: collapsed Color Strip + Color VS into one
"Color Source" picker with grouped headers; mappings list shows a
mode-aware hint when broadcasting a single colour.
- EntityPalette: support non-selectable header rows (with keyboard / filter
handling) for grouped source pickers.
Bundled UI polish (icon inheritance + cleanup):
- Custom card icons now flow into more surfaces: command palette, dashboard
target cards, scene-preset target picker, calibration test-device picker,
and the LED-target device picker. LED targets inherit their device's icon
when none is set on the target itself.
- Empty mod-card icon plates render as a dashed "+" placeholder when an
icon-picker hook is wired, so the action stays discoverable.
- Icon picker: distinct "HA light target" eyebrow label and supports
HA-light cards (data-ha-target-id) for channel-colour resolution.
- Update banner: "View release" now opens the in-app Update settings tab
instead of an external link; uses the sparkles icon.
- Color-strip delete: cleaner toast on 409 conflict.
Introduce BindableFloat abstraction that allows any numeric property to be
either a static value or dynamically driven by a ValueSource. Backward-compatible
serialization: plain float when unbound, {value, source_id} dict when bound.
Backend:
- storage/bindable.py — BindableFloat dataclass + bfloat() helper
- 25+ scalar properties converted across all entity types
- Runtime VS acquisition in ColorStripStreamManager for CSS bindings
- All stream hot loops use self.resolve() for live values
- KeyColorsColorStripStream now inherits ColorStripStream
Frontend:
- BindableScalarWidget (slider + VS picker toggle) for all editors
- TypeScript BindableFloat type + helpers
- Graph editor edges for all bindable properties
- Audio source channel IconSelect grid
Fixes: daylight longitude, candlelight wind_strength/candle_type from_dict
Key Colors refactor:
- New `key_colors` CSS source type with inline rectangles
- KeyColorsColorStripStream: extracts N colors from screen regions
- CSS editor: EntitySelect for picture source, IconSelect for color mode
- Configure Regions button on card opens pattern canvas editor
- Live WS preview at 5 FPS with rectangle overlay + color swatches
- Removed KC target type, pattern template entity, and related API routes
- Removed KC/pattern template sections from Targets tab
HA light target improvements:
- Update rate, transition, mappings, brightness VS now editable via PUT
- Card crosslinks for HA source, CSS source, brightness VS
- HA connection status icon, text metrics (Hz, uptime)
- Brightness value source selector in editor
All store tests were passing file paths instead of Database objects
after the JSON-to-SQLite migration. Updated fixtures to create temp
Database instances, rewrote backup e2e tests for binary .db format,
and fixed config tests for the simplified StorageConfig.