feat(ui): map canvas follows light/dark theme; fix invisible gear control
The map view now selects a DARK_THEME or LIGHT_THEME palette from the resolved app theme and threads it through every primitive builder, so the canvas, planets, ship groups, cargo routes, battle/bombing markers, fog, reach + selection rings, pending-Send tracks, and the pick overlay all switch with the rest of the chrome. A theme flip remounts the renderer preserving the camera — Pixi bakes the background at init and every primitive bakes its colour at build, so a live re-tint is not possible on the same instance. This also fixes the reported bug: the gear-popover trigger and the loading overlay hardcoded a dark navy background, so in light theme the gear was invisible (dark icon on dark chip) until hover flipped it to a white chip. Both now use the --color-surface-overlay token and read correctly in both themes. The light palette mirrors the dark one role-for-role, darkened / saturated for contrast on a light background while keeping the incoming, battle, and bombing accents vivid. The values are a first pass meant to be refined during the F8 manual-QA loop. Removes the now-dead "Phase 35" references from the code and lifts the map-recoloring prohibition from the design-system / renderer docs; the battle scene stays a fixed-palette data-viz surface. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -130,19 +130,122 @@ export class World {
|
||||
}
|
||||
}
|
||||
|
||||
// Theme carries the default colours used when a primitive's `style`
|
||||
// leaves a colour unset. Phase 9 ships a single dark theme; runtime
|
||||
// theme switching is deferred to Phase 35.
|
||||
// Theme is the renderer's colour palette. It carries both the generic
|
||||
// fallbacks used when a primitive's `style` omits a colour and the
|
||||
// semantic colours every primitive builder paints with (planets, ship
|
||||
// groups, cargo routes, battle / bombing markers, reach + selection
|
||||
// rings, pending-Send tracks, and the pick-mode overlay). Two concrete
|
||||
// palettes are shipped — `DARK_THEME` and `LIGHT_THEME` — and the map
|
||||
// view selects between them from the resolved app theme
|
||||
// (`$lib/theme/theme.svelte.ts`), so the canvas follows the user's
|
||||
// light / dark choice like the rest of the chrome.
|
||||
//
|
||||
// Only colours live here: per-primitive alphas, widths, and radii are
|
||||
// emphasis / geometry, not theme, and stay as constants in the builder
|
||||
// modules. The light palette mirrors the dark one role-for-role but
|
||||
// darkens / saturates each hue so it reads against a light background;
|
||||
// the incoming-group, battle, and bombing accents stay deliberately
|
||||
// vivid in both palettes.
|
||||
export interface Theme {
|
||||
// Canvas background and the visibility-fog veil drawn over
|
||||
// unscanned hyperspace.
|
||||
background: number;
|
||||
fog: number;
|
||||
// Generic fallbacks for primitives whose `style` omits a colour.
|
||||
pointFill: number;
|
||||
circleStroke: number;
|
||||
lineStroke: number;
|
||||
// Planet glyphs, one colour per `ReportPlanet.kind`.
|
||||
planetLocal: number;
|
||||
planetOther: number;
|
||||
planetUninhabited: number;
|
||||
planetUnidentified: number;
|
||||
// Ship groups. The in-space track reuses `shipLocal` and the
|
||||
// incoming trajectory line reuses `shipIncoming`.
|
||||
shipLocal: number;
|
||||
shipOther: number;
|
||||
shipIncoming: number;
|
||||
shipUnidentified: number;
|
||||
// Cargo-route arrows, one colour per load type.
|
||||
routeCol: number;
|
||||
routeCap: number;
|
||||
routeMat: number;
|
||||
routeEmp: number;
|
||||
// Battle X-crosses and bombing rings (damaged vs wiped).
|
||||
battleMarker: number;
|
||||
bombingDamaged: number;
|
||||
bombingWiped: number;
|
||||
// Reach rings, the selected-planet ring, and pending-Send tracks.
|
||||
reachCircle: number;
|
||||
selectionRing: number;
|
||||
pendingSend: number;
|
||||
// Pick-mode overlay: the anchor / cursor-line / hover highlight
|
||||
// colour and the multiply tint applied to non-reachable primitives.
|
||||
pickHighlight: number;
|
||||
pickDimTint: number;
|
||||
}
|
||||
|
||||
export const DARK_THEME: Theme = {
|
||||
background: 0x0a0e1a,
|
||||
fog: 0x12162a,
|
||||
pointFill: 0xe8eaf6,
|
||||
circleStroke: 0x4fc3f7,
|
||||
lineStroke: 0xa5d6a7,
|
||||
planetLocal: 0x6dd2ff,
|
||||
planetOther: 0xff8a65,
|
||||
planetUninhabited: 0xb0bec5,
|
||||
planetUnidentified: 0x546e7a,
|
||||
shipLocal: 0xfff176,
|
||||
shipOther: 0xff6f40,
|
||||
shipIncoming: 0xff5252,
|
||||
shipUnidentified: 0x9aa3a8,
|
||||
routeCol: 0x4fc3f7,
|
||||
routeCap: 0xffb74d,
|
||||
routeMat: 0x81c784,
|
||||
routeEmp: 0x90a4ae,
|
||||
battleMarker: 0xffd400,
|
||||
bombingDamaged: 0xffd400,
|
||||
bombingWiped: 0xff3030,
|
||||
reachCircle: 0x6d8cff,
|
||||
selectionRing: 0x6d8cff,
|
||||
pendingSend: 0x66bb6a,
|
||||
pickHighlight: 0xffe082,
|
||||
pickDimTint: 0x303841,
|
||||
};
|
||||
|
||||
// LIGHT_THEME mirrors DARK_THEME role-for-role. The background matches
|
||||
// the app's light shell background (`--color-bg` in `tokens.css`) so
|
||||
// the canvas blends into the surrounding chrome instead of reading as a
|
||||
// dark rectangle; the fog is a faint darkening over the lighter base.
|
||||
// Hues are darkened / saturated relative to the dark palette so small
|
||||
// glyphs and thin strokes stay legible on a light surface, while the
|
||||
// incoming (red), battle (amber), and bombing (amber / red) accents are
|
||||
// kept vivid. Values are a first pass meant to be refined during the
|
||||
// owner's F8 manual-QA loop.
|
||||
export const LIGHT_THEME: Theme = {
|
||||
background: 0xf3f5fb,
|
||||
fog: 0xe2e7f1,
|
||||
pointFill: 0x1a2138,
|
||||
circleStroke: 0x1565c0,
|
||||
lineStroke: 0x2e7d32,
|
||||
planetLocal: 0x1565c0,
|
||||
planetOther: 0xe64a19,
|
||||
planetUninhabited: 0x78909c,
|
||||
planetUnidentified: 0x90a4ae,
|
||||
shipLocal: 0xc79100,
|
||||
shipOther: 0xd84315,
|
||||
shipIncoming: 0xd50000,
|
||||
shipUnidentified: 0x607d8b,
|
||||
routeCol: 0x0288d1,
|
||||
routeCap: 0xef6c00,
|
||||
routeMat: 0x2e7d32,
|
||||
routeEmp: 0x607d8b,
|
||||
battleMarker: 0xf57f17,
|
||||
bombingDamaged: 0xf57f17,
|
||||
bombingWiped: 0xc62828,
|
||||
reachCircle: 0x3949ab,
|
||||
selectionRing: 0x3949ab,
|
||||
pendingSend: 0x388e3c,
|
||||
pickHighlight: 0xef6c00,
|
||||
pickDimTint: 0xaeb6c4,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user