Minor bump: new public API, no removals.
Added — @zaes/tactical-graphics/openlayers:
- serializeTacticalGraphics / restoreTacticalGraphics. Save a map of graphics
to GeoJSON and rebuild them still editable, one base feature per graphic.
Records carry `tacticalGraphic` (the portable description) and `renderer`
(drawing resolution and security-operation scale).
- isDarkMode / setDarkModeFlag. Every colour accessor already read this flag;
consumers previously got a two-mode palette with no exported way to choose.
- assignRole / readRole / ROLE_KEY / readGraphicGeometryState, plus the
GraphicGeometryState and TacticalGraphicRendererState types.
- writeGraphicProperties takes an optional 4th argument carrying the geometry
inputs a holder needs to reproduce its shape.
Changed:
- Dark mode has a real palette. The graphics layer is no longer repainted by
the demo's CSS invert filter, which had been reaching it through OpenLayers'
shared-canvas optimisation; pending yellow was arriving as a near-black
olive. settings.ts now defaults to light, so an unconfigured consumer gets
the doctrinal FM 1-02.2 colours.
- MovementToContact's side arrows hold station against the graphic instead of
drifting with zoom.
Fixed:
- GraphicLinkRegistry was keyed on the empty string; controllers register in
their constructors, before a symbolId exists.
- SecurityOperationsController never registered, and lagged one pointer event
behind during a translate. Its labels never rotated.
- MissionTaskGraphicBase.setBaseFeature dropped the cached centre.
- Route-direction arrows and line of contact took hardcoded colours.
300 tests across 6 suites.