Previously the ModifierProfileEditor's layout picker was editor-only
UI state — it drove per-instance board preview and live validation,
but was dropped on save. This meant per-instance modifiers (square-
bound to their authoring layout) silently became orphans in the Lobby
if the user picked a different layout at apply time, with no signal
about the mismatch.
Changes:
- ModifierProfileEditor now writes the bound layout through to
profile.layoutId (schema already supported the optional field) and
rehydrates boundLayout from profile.layoutId on open / load /
undo / redo.
- Lobby rearranged so the Modifier Profile picker sits ABOVE the
Layout Picker. Picking a profile with a layoutId binding snaps
selectedLayout to match. Same behavior on URL ?modifierProfile
deep-links and after the editor closes with a new save.
- Mismatch banner (amber) surfaces when the user overrides the
layout after picking a bound profile, with a one-click "Switch
to <LayoutName>" restore.
Unit test added for library round-trip of layoutId; new
profile-layout-binding.spec.ts covers the four scenarios: snap,
manual override + mismatch banner, unbound profile leaves layout
alone, and editor-save persists layoutId.