- Rebalance the three cargo hold upgrades (8/12/16) from a credits-only sink to a mixed cost of credits and minerals, so expanding the hold draws on both trade income and the mining economy.
- Update research descriptions, build data, tests, docs, and code comments to reflect the new two-resource costs.
- Introduce CargoHold (pure class) as the ship's trade-goods carrier: fixed bays, one good each, capacity = unlocked bays, save/restore round-trip. Ship.cargo + setCargoHold/cargoRoom wired into stats.
- Add three credit-costed cargo builds (cargo-bay-8/12/16) that expand the hold 4→8→12→16 (MAX wins). BuildWindow affordability now covers both minerals and credits; GameScene.beginBuild debits credit lines and _applyCargoUpgrade expands the hold on completion.
- Add tradePreview/resultingCargo to Economy.js as the shop's pure calculator: sell/buy pricing, net credits, the two caps (can't go negative, end hold fits capacity), and atomic sell-to-free-room-for-buy.
- New ShopView + TradeGrid compose the buy/sell screen over the shop clip: SELL grid of cargo bays (tap to check), BUY grid with quantity steppers, live NET preview, Confirm/Clear, and a session-local Buyback tab (neutral undo at the sale price, locked until a sale). Wired into SurfaceScene's SHOP button.
- data/shopui.json drives the shop layout/animation knobs; economy.json gains cargo.maxSlots (16-slot grid); ship.json base cargoHold drops to 4 unlocked bays.
- Headless tests: dev/cargo.test.mjs (hold rules + trade preview caps), dev/shop-ui.test.mjs (construct, sell, buy, caps, buyback, clear), plus updated builds/ship-behavior suites; phaser-stub gains Geom.Rectangle for the hitArea path.
- BUILT rows are now lit — accent fill, glow ring, icon halo, and a
stamped seal — so installed upgrades read as done at a glance.
- The readout now names the world a build was actually installed on
(new BuildState.builtOn): ship upgrades show "SHIP-WIDE · INSTALLED
FROM KEPLER-186F" instead of the planet the console sits on.
- BUILT outranks BUSY, so an installed upgrade no longer reads as
waiting while another build is in flight; its cost line reads PAID.
- Category tabs gain progress pips: filled = built, pulsing = in
progress, hollow = not yet.
- Dev-only headless harness (dev/build-shot.html/.mjs) boots the game
and stages the full row-state matrix for one-frame screenshots.
- Refresh the planet sheet artwork (planets.png/.psd).
- Use `video.resume()` instead of `video.play()` in Build, Map, Quest,
and Research windows: Phaser v4's `play()` is a no-op after `pause()`
because the `_playCalled` flag stays true, leaving the feed frozen
after close → reopen. `resume()` handles both first open and re-open.
- Play the 'construct' SFX when the planet HUD lines start their
scramble-decode animation in SurfaceScene.
- New `data/research/mining.json` tree (Improved/Advanced Mining Arm, Improved Storage) as blueprints that unlock matching builds
- Three new ship-scoped builds in the console's Mining tab: mining arm rate 1.5/2.0 minerals/s and hold cap 350; MAX-guarded effects applied to `ship.stats`
- Tether Level 3 promoted from research-direct effect to a build (tether-l3) gated on L2 tether, consistent with L2 blueprint pattern
- `BuildState.isBuiltAnywhere` + `isShipScoped` so ship upgrades count as built wherever the ship lands (no re-buy), records still key the planet
- `GameScene._restoreMiningUpgrades` re-derives ship mining stats from build records on load; `_applyMiningUpgrade` handles rate/capacity with toasts and HUD refresh
- New procedural icons: tether3, mining, mining2, storage
- Updated tests (builds, research-builds), diagnostics (BuildDiag v4), docs, README, manifest
- Center the ✕ close glyph and "IN PROGRESS" labels via setOrigin(0.5, …);
Phaser Text defaults to origin (0,0), so they were anchored top-left
and sat off-center on their plates
- Widen detail buttons from 152 to 190 px so the widest label
("IN PROGRESS 88%") no longer bleeds past the plate edges
- Treat 'closing' as open in isOpen so a close tap is consumed by the
window while it fades out, instead of leaking through as a world click
- Introduce the BUILD deck slot on planet surfaces: full-screen BuildWindow
(looping feed video, category tabs, build list, dossier + cost + BUILD
button) backed by pure BuildModel/BuildState rules
- Move tether level 2 from a research effect to a one-off planet build
(200 minerals, 20 s, requires L1 tether on the world); home world starts
with tether-l1 pre-installed as a rule re-asserted after load
- Add `node dev/server.mjs` static server sending Cache-Control: no-store to
stop browsers heuristically caching ES modules (the "new data + old JS" bug)
- Fix world-name casing leak: CommsPanel keeps canonical spelling in the
landing payload; GameScene.startLanding normalizes via WorldNames.canonicalPlanetName
so name-keyed build/tether lookups match
- Add in-game diagnostics (orbitDiag/orbitDiagBrief), dev/build-check.html
self-check page, and Node tests for builds, world names, and save staging
- Persist builds (built records + in-flight remaining time) in the save bank;
tick on the game-loop clock so a build survives takeoff mid-build