- Introduce Star entity (procedural texture per spectral class) drawn at the origin of every non-home system; only the starting system's central body is the home world
- Freeze `homeSystemId` at roster build so lazily generated content for newly arrived systems no longer misreads as home and deals a second home world
- Anchor tether-l1 builds on newly discovered worlds (effects.tether in data/builds.json) and re-materialize installed tethers after jump cuts / scene rebuilds
- Discovery now reports the central body in every system ("Home World" vs. spectral-class star label); stars are solid but not comms targets
- Add dev tools: nav-reach-probe (soft-lock analysis), star unit tests, tether-newworld browser test; fix landing video references and Phaser stubs
- `_applyResearchEffects` now receives the node id explicitly instead of
reading `node.id`, which is undefined (the id is the key in the tree's
`nodes` map, not a field on the object) — this was silently skipping
`activateGates` so researched jumpgates stayed dark
- Add `systemIdOfGatesNode()` as the pure inverse of `systemNodeId()` for
the gates node, with round-trip tests
- Reconcile gate activation in `_onEnterSystem()`: if the gates tech is
already unlocked, re-run `_activateSystemJumpgates` (idempotent) so a
missed activation self-heals on the next entry/jump/reload
- Make `_activateSystemJumpgates` idempotent by tracking fresh keys and
early-returning when everything is already online
- Add `navPoints()` and `navChart()` to SystemCategory.js as pure,
testable cores for the jumpgate unlock condition (discovered/missing
split over all NAV points)
- Add `js/dev/NavDiag.js` with `orbitNav()` / `orbitNavBrief()` console
commands that print the live NAV chart and which objects are still
undiscovered, installed by `main.js` on every page load
- Update `data/landing.json` to reference the correct gasgiant surface/shop
videos for slot 03
- Add tests for `navPoints`, `navChart`, and `systemIdOfGatesNode`
- Document the activation wiring bug, the `orbitNav()` diagnostic, and the
new pure functions in PROJECT_NOTES.md
- Add JumpTravel.js with pure arrival geometry (return-gate lookup, spawn point past keepout) and wire it into GameScene.jumpThroughGate to re-stage the run via the save pipeline and scene restart
- Add gate hit-test (gateAt) so active gates trigger the jump on click while dormant ones show a console nudge and fall through to fly-here
- Add jump config block to gates.json (feature switch, arrival gap, delay, toast templates) and update landing.json gasgiant shop clips
- Add dev/jump-travel.test.mjs covering config, geometry, real-galaxy coverage, and determinism; refresh PROJECT_NOTES for the new mechanic
- Clicking a planet or station now opens the comms panel without moving the ship; world clicks are no longer fly-here targets, keeping mining beams live during panel interaction
- Add double-click (350 ms) skip for landing and takeoff clips in SurfaceScene so players can cut to the deck or flight world immediately
- Push restored mineral hold through the upper-right HUD on load so the readout matches the saved value instead of staying at zero
- Replace removed Phaser v4 Container.removeChildren() with removeAll(true) in JumpGate and Station destroy paths
- Update landing.json shop entries for terran frames 2–3 and document the new skip behavior
- Add dev harnesses for surface-skip, hold-restore, scene-restart, container-probe, and import probes; extend comms-click and saves-ui tests to cover the new interactions
- Add new video assets `terran-surface-03.mp4` and `terran-takeoff-03.mp4`
- Fix the third terran entry in `landing.json`, which was incorrectly
duplicating the first entry, so it now references the new 03 videos
- Introduce data/gates.json + js/galaxy/JumpNetwork.js: a strongly-connected, degree-limited spanning tree over the nearest-star graph (plus local shortcuts) so every system holds 1–3 gates, all jumps are local, and no system is closed or trapped
- Place each gate on the tether circle of an anchor (planet / space station / home world), facing its destination star; enforce radius band, clearance from anchors, and gap between gates in SystemGenerator.layoutGates
- Add the JumpGate entity (procedural twin-pylon portal) with the same solid contract as Planet/Station, discoverable in cyan, listed in the HUD dossier; wire into GameScene solids + discovery
- Guarantee every system holds at least one gate anchor (barren systems get a deep-space station); cap the home system at 3 objects so it fits the tighter band
- Rework solar-system layout to a full pairwise band [minSpacing, maxSpacing] with rotation tuned toward gate bearings; update tests and docs accordingly
- Change radiusGrowth from 1.25 to 2.0 so level N doubles the previous
level (L2 = 10240, L3 = 20480, L4 = 40960 px)
- Update all data descriptions, docs, and test defaults to match
- Add refreshHudTetherLevel() in SurfaceScene so the HUD line re-decodes
when a tether build completes while on-surface
- Rename rocky-planet-02 asset (typo fix), add 03-a/03-b variants,
point rocky frames at indices 6–8 in planets.json
- Add dev/tether-flow harness to exercise the full L2 build flow end-to-end
- SHOP button now swaps the looping surface clip for the world's `shop`
video (e.g. terran-shop-01.mp4); pressing again swaps back. The slot
relabels between "Shop" and "Leave Shop" via a new ActionBar.setLabel.
- data/landing.json gains a per-frame `shop` entry; worlds without one get
a console note instead of a clip.
- SurfaceScene: toggleShop/leaveShop manage the shop video (pause/resume,
visibility), error handling falls back to the surface loop, and cleanup
on takeoff/shutdown disposes the new video and note glyphs.
- ActionBar: slots store their base fontSize so setLabel can shrink-to-fit
long labels; paintSlot re-asserts hover state after relabeling.
- GameScene now passes the world's type label and tether level into the SurfaceScene launch payload; new tetherLevelFor() resolves a world's anchored tether (by label or anchor position) for that line.
- SurfaceScene builds/decodes a two-line HUD (Ethnocentric name in the menu title shade with black stroke, Centauri line below) while the surface clip loops, driven by the shared scramble decode; it is torn down on take-off and shutdown.
- landing.json gains a hud config block for margins, fonts, spacing, strokes, and colors.
- Added dev-only harnesses (surface-hud.html/.mjs test page and surface-hud-shot.html/.mjs screenshot probe) to verify the HUD styling, decode settle, payload, and teardown in headless Firefox.
- Introduce a `takeoff` video entry in landing.json for each world; missing/
null entries leave the surface instantly (no regression)
- SurfaceScene.takeOff now plays the one-shot take-off clip full-screen,
hides the deck, and only then stops the scene and wakes GameScene
- Guard against a clip that never starts or runs past its duration so the
player is never stranded; finishTakeoff is idempotent
- Update surface-flow/surface-shot dev harnesses to assert and screenshot
the new take-off stage
- Re-map gas giant frames in planets.json from [0,1,2] to [3,4,5] to match
their sheet positions
- New SurfaceScene overlays GameScene when the player requests landing:
plays a one-shot landing clip, then a looping surface clip behind a
dedicated command deck (Shop/Build/Ship + Take Off + Menu).
- Wire comms panel "Request Landing" / "Land" buttons to launch the
surface; TAKE OFF stops SurfaceScene and wakes GameScene so the run
resumes exactly where it left off.
- ActionBar accepts an optional `buttons` override so scenes can supply a
different slot list while sharing layout/colors/animation.
- SavePanel gains a `stateScene` option so saves from the surface read
state from the paused GameScene underneath.
- Add data/landing.json (per-frame video map) and four placeholder
surface clips; CommsPanel now passes its full target payload through to
onAction so landing metadata survives the round-trip.
- Add dev harnesses: headless-Firefox screenshot helper, click-path test
for the real user flow, and a surface-flow assertion suite with parked
screenshot pages.