Add react-router-dom with two routes: "/" → MyScenariosPage (scenario grid with
search, create, open, delete against the scenarios API) and "/editor" → AppShell.
"Sair do cenário" returns to the list. New: use-scenarios hook, ScenarioCard,
MyScenariosPage (+ tests, 235 web tests green).
API: backfill legacy initialConditions rows missing instanceId so GET /scenarios
serializes under the updated schema.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 1 of the Figma "[INSTRUTOR]" port plus hardening found during testing.
Design system
- theme/tokens.ts + global.css: Figma palette, type scale, spacing, radii,
shadows; injected as CSS vars at boot.
- ui/: 11 themed primitives (Button, IconButton, TopBar, Panel, Tabs, Card,
Slider, Field, Modal/AlertDialog, SimulationControl, MapActions), each tested.
App shell (Layout do instrutor)
- features/shell/AppShell.tsx: TopBar (logo + breadcrumb, gated center actions,
Sair/Salvar), full-bleed map, bottom-center Build/Play/Stop pill, bottom-right
zoom, no-ownship AlertDialog. Replaces ScenarioCreatorPage.
- stores/mapStore.ts exposes the Leaflet instance so the zoom pill can drive it;
AreaMapView registers it and drops Leaflet's default zoom control.
Physics truth
- Worker reports which engine loaded (real WASM vs JS mock); surfaced as a
status badge/warning so the instructor never mistakes the mock for real
dynamics. SimulationControls is now a status-only strip (actions moved to the
pill).
Tests
- 229 passing, coverage gate green. New: tokens, all 11 primitives, AppShell,
VesselPanel, vesselPanelStore. Fixed GeralTab to read draft by instanceId.
Docs
- docs/specs/features/instructor-ui/: extracted screen specs, reference maps,
phased PLAN.md, and DYNAMICS-GAP.md (MATLAB↔Ymir physics parity).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>