- Nebula gas layer: soft coloured cloud sprites at depth 3, tinted with a
per-system palette color assigned deterministically at galaxy generation
(SystemGenerator stamps content.atmosphere.color). Only nebula-type
systems render it; all other types are untouched.
- Ripple effect: a full-screen WebGL composite on the world camera that
displaces the starfield and world objects while the HUD stays crisp via
a new UI/world camera split (UiCameras.js). Data-driven per archetype in
data/systems.json (nebula = ripple, all others = none). Canvas fallback
degrades to no effect.
- Demo mode: ?fx=<type> URL param retargets the run to the richest system
of that archetype, fully charted with all gates active, for judging the
effect in isolation.
- New ice and lava planet art (slots 9–14 in planets.png) replacing the
placeholder terran/rocky/gas reuse.
- Node test suites for the nebula palette/determinism/cloud texture and
the ripple math/data contract/shader/facade (50+ checks, bare Node).
- Full-screen RESEARCH window: looping archive feed, category tabs, branching
DAG tech tree (top-down layout), per-tech dossier + RESEARCH button, deck
progress bar
- Pure rules layer (ResearchModel / ResearchState) is Node-testable; the
window is a passive view and GameScene owns effects, toasts, and saves
- First category **Exploration** (Tether Level 1–4, Tether Anchoring, Signal
Amplification) lives in data/research/exploration.json; adding a category
= one JSON file + one registry line + one manifest line
- Effects seam: `tether.level` grows the home tether via TetherField.setLevel;
`capability` flags land on scene.researchCapabilities for future systems
- Save/restore round-trips an in-flight project (remainingMs captured at save,
startedAt rebuilt on load); old saves without research still load
- Dev tooling: dev/cdp-shot.mjs (CDP screenshot with readiness wait),
dev/research-shot.html/.mjs (boots the console + starts a run for a shot)
- Assets: gasgiant planet frame 03, takeoff/landing clips, research-computer
feed; planets.png/.psd updated
- New `js/utils/Decode.js` with a pure `ScrambleDecode` class plus
`DECODE_CHARS`, `DECODE_DURATION`, and a per-line `decodeDur()` helper,
so one effect serves both scenes.
- MenuScene now delegates its seed scramble to the shared utility instead
of inlining the reveal math and alphabet.
- GameScene's system dossier types itself in on arrival: each line starts
empty and decodes left-to-right, staggered top-to-bottom, with the
timeline anchored on the first update frame; state self-clears once all
lines settle so `update()` pays nothing afterward.
- Add Node dev tests for the shared effect contract (`dev/decode.test.mjs`)
and for the real GameScene dossier decode against actual galaxy/report
data with a stubbed scene (`dev/system-hud.test.mjs`).
- Document both new test commands in the README and update the planets
PSD asset.
Adds the player's home planet to the starting system, rendered from the new
planets.png spritesheet. The planet is a solid disc: the ship may come within
shipClearance of its rim but can never cross it, and clicks on the planet
clamp to the keep-out rim so the ship always has a reachable destination.
- js/entities/Planet.js: solid-disc entity with a circle keep-out constraint
(constrainShip/resolve, pure and scene-free) plus edgePoint/aimPoint helpers
- data/planets.json (+ manifest entry): texture, frame size, scale, homePlanet,
shipClearance, spawnDistanceFromEdge
- Ship.js: exposes a radius (half the hull width) for the keep-out math
- GameScene.js: loads the spritesheet, spawns the home world at the origin,
starts the ship ~150 px off its rim in a seed-derived direction, and applies
the constraint each frame after the ship moves
- dev/planet.test.mjs: Node tests of the constraint against real config;
dev/test-game.html gains a <base href> so asset paths resolve from /dev