WorldMapPanel owns the world state and applied the /api/jump response
locally, so MissionControl's lifted /api/system state (LOCAL SYSTEM tab,
CARGO HOLD, SECTOR row) stayed on the previous system until a full refresh.
The panel now takes an onJumped callback that MissionControl wires to an
/api/system refetch after every successful jump.
Persist the selected tab ID to localStorage (sw-active-tab) on every change
and restore it on mount when it matches one of the seven valid tab IDs. The
Radix Tabs become controlled for this; SSR and first client render still agree
on the default, so there is no hydration mismatch.
Production freeze reported after the v0.9.3 (#21) deploy: every API route
hung and all panels stayed at LOADING. Root cause was not the #21 layout
(verified healthy across all 7 tabs/viewports) but makeName's unbounded
rejection loop over a finite 16x8=128 system-name pool — once a save grew
past ~128 systems, any jump into an undiscovered system spun forever on
Node's single thread (sql.js is synchronous), blocking the whole process.
makeName and makeCrewName now fall back to numbered variants ('Kepler Drift 2')
once their pools are exhausted, so they always terminate.