- Locked gates (neutral → faction, below minLevel) now render their
swirling center in the controlling faction's hue as an in-world
"that gate belongs to someone" tell, complementing the comm window's
grayed REQUEST JUMP and lock message.
- JumpGate.setFactionTint tints the active swirl (setTint) or recolors
the procedural fallback field discs; null clears back to the ordinary
swirl. Falsy-but-valid hues (e.g. 0x000000) are not treated as clear.
- GameScene.gateFactionTintFor resolves the destination faction's color;
_refreshGateFactionTints re-resolves all gates at build, once the XP
ledger exists (save may have already lifted the lock), and on each
level-up event to clear tints as the lock lifts.
- Test harness extended with setTint/setFillStyle mocks; new checks cover
tint apply/clear/falsy-hue on the sprite path and field-disc recolor
+ restore on the fallback path.
- Waypoints were comms-only beacons with no landing or trade; a second
deep-space station is a more useful destination in their place
- The old waypoint chance in systems.json becomes
deepSpaceStation.second, so a system can roll 0–2 stations
- StationFrames now assigns a distinct sprite variant per station
(Galaxy.stationFrames is id → [frame, …]) and a two-station system
always wears two different variants
- Rename the route-gate pulse from "destination's waypoint" to
"route's next stop" so the term no longer refers to a removed kind
- New shared RoutePulse entity draws a steady ring + two radar ripples
scaled to the host's keepout radius, with configurable alpha/period
- JumpGate wears the full pulse (route.pulse) when it is the route's next
stop; Planet and Station wear the subdued variant (route.objectPulse)
when they are the destination object in the destination system
- GameScene marks exactly one entity per frame via setRouteTarget() and
drives its update loop; all others are cleared
- Add data/gates.json sections for pulse and objectPulse geometry/alpha
- Rename laval-surface-02.png to lava-surface-02.png and add the
corresponding video asset
- Extend jumpgate, planet, and station test stubs with Phaser Display.Color
and recording graphics; add dev/route-pulse.test.mjs unit tests and
dev/route-pulse-live.{html,mjs} browser integration checks
- Replace direct-click-to-jump with a shared comms panel variant that shows LINK ACTIVE/DORMANT status, REQUEST JUMP (disabled while dormant), and CANCEL
- Render gates from the new 256x256 spritesheet (frame 0 body, frame 1 active swirl) with procedural fallback when the texture is missing
- Active gate swirl spins clockwise and breathes alpha between configurable bounds; dormant gates keep the body at full alpha with the swirl hidden
- Wire CommsPanel to a dynamic primary-button action id so the same panel serves world and gate variants
- Add dev probe page (dev/gate-comms.html/.mjs) and update jumpgate/jump-travel tests for the new sprite path, fallback renderer, and comm-window flow
- Introduce a dynamic "system" research category built at runtime with two techs: `{System} Map` (granted on entry) and `Unlock {System} Jumpgates` (researchable once every NAV point is discovered).
- Wire gate activation through the research effects seam so completing the jumpgate tech activates the system's gates plus linked return gates, anchors level-1 tethers at each activated gate, and saves/restores via a new `activatedGates` set.
- Extend ResearchModel with optional tree hooks (`available`, `lockNote`) so dynamic categories can gate research on live world state without adding static requires.
- Add map and gate procedural icons, update tests for the new category contract and icon roster, and document the system category in project notes.
- Galaxy shrunk to 200 systems (data/galaxy.json) — always fully known,
generation ~15 ms; roster/content two-level design unchanged.
- Object composition replaces planetCount (data/systems.json → objectCount):
10% barren (jump-gate-only), else 2/3/4/5 objects (planets + free-space
stations) at 15/30/30/15. One unified roll (rollSystemComposition) shared
by the content generator and the frame pass.
- Barren systems: no planets, no stations, no asteroid clusters; their
single gate sits on the star→destination ray at barrenDistance (8192 px).
Strong connectivity keeps them reachable.
- Jump gates are DORMANT by default: every gate record carries
active:false, the entity renders dim with a still field. Activation is
the seam for the tether mechanic (an activated gate anchors a level-1
tether). data/gates.json gains barrenDistance.
- Frame diversity (js/galaxy/PlanetFrames.js): one galaxy-wide pass spreads
(class, frame) across the galaxy — fixed spatial order, least-used face
among already-assigned nearest stars, seeded tie-breaks. Stamps
planet.frame + content.homeFrame, read by GameScene.
- Tests: dev/frames.test.mjs added; jumps/galaxy/discovery/jumpgate/asteroids
suites updated to the new rules (composition buckets, barren gates,
active flags, frame determinism/spread, 5-object max, index clamps).
- Docs (README, PROJECT_NOTES) and stale 40k references updated.
- 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