- LiveNoteStaff: new range prop. With a written range set, notes render
at their TRUE staff position with real ledger lines (no 8va/8vb
shifting) and the box height is computed to fit the whole range
(treble F5/E4, bass A3/G2 diatonic math; staff anchored asymmetrically
below the top headroom). Mic bar keeps compact octave-marker behavior.
- AssistMode: passes the written range of the current pool (strings x
frets, honoring the note filter) — guitar high notes now show with
ledger lines instead of being octave-shifted.
- Assist fretboard bug: positions (played-note markers) were gated on
showHints which Assist passed as false — they never rendered. Now
always on (non-interactive, no tooltips).
The Assist card wrapped the LiveNoteStaff in .sheet-music-container,
which clips (overflow: hidden) — extreme ledger lines poked out of the
64px box by a few px. LiveNoteStaff now takes a height prop; stave y is
computed as (h-38)/2 - 40.5 (equals the old -28 for h=64). Assist uses
88px; mic bar keeps 64px.
- Strings filter: per-string toggle buttons (replaces fret-window-only
semantics as a third 'limits notes' control); combines with fret window
and key filter in targetPool (fretted instruments).
- Key sync checkbox: display key signature can follow the target key
(major/minor mapping), default off — both remain independently settable.
- LiveNoteStaff: optional fixed clef — guitar/bass now keep their usual
clef instead of flipping at middle C; octave markers handle range.
- Unified metronome widget (MetronomeWidget) with animated linear pendulum
synced to the audible click; shown in ALL modes next to the tuner.
Phrase BPM now reads from settings.rhythm.bpm (single source); the
phrase-local BPM control was removed from the setup panel.
- Tests: 160/160; tsc + eslint clean; build ok.