- 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).
- Add MineralHud component (js/ui/MineralHud.js) showing "MINERALS n / N"
plus a fill bar in the upper-right corner, replacing the old tether
stack. One tween drives both the counting number and the bar so they
never drift; a cyan flash ripples on landings; amber at capacity.
- Wire Mining to emit an onOre(gained, hold) seam per extraction tick and
per fragment landing so the HUD fills live as the rock shrinks, not
only at the batch 'absorbed' event.
- Remove refreshTetherHud / fmtRange from GameScene; instantiate MineralHud
in create(), feed it via refreshMineralHud() from ore seams and mining
events, destroy on shutdown.
- Add data/mineralhud.json config (corner pad, bar geometry, count-up and
flash tuning) and register it in the manifest.
- Tests: new dev/mineral-hud.test.mjs covering layout, count-up/bar sync,
superseded-tween guard, capacity/clamping, teardown; extend
dev/mining.test.mjs to assert onOre ticks; drop tether-HUD checks from
dev/system-hud.test.mjs; add setOrigin/setScrollFactor no-ops to the
Phaser stub.
- Extract minerals from the latched asteroid at ratePerSec × miningSpeed; each mineral shrinks the rock by 1 px so the beam stays latched to its rim.
- Break rocks that lose ~1/3 of their original size: large ones halve in place (beam keeps mining one half), small ones shatter into pieces that fly home and load the hold.
- Add ship.minerals hold with addMinerals/setMinerals capped at stats.mineralStorage; a full hold ends the run instead of grinding the rock away.
- Persist the hold in save/restore (captureState writes ship.minerals, applyRestore restores it) and keep legacy saves working when the field is absent.
- Play new mining_split sfx on each break and surface split/absorbed/storageFull events as console toasts.
- Expose AsteroidCluster rock surgery (setSize/addRock/removeMember) for runtime splits, and add headless Phaser stub + loader plus a mining test suite covering extraction, halving, shattering, full-hold stop, and the hold API.