- Introduce `Ship.state` ('normal' | 'mining') with `setState()` and an
`onStateChange` callback so the scene can react to state exits.
- Any player-initiated movement (world click or compass autopilot) now
drops the ship back to 'normal', which ends the mining sequence via the
scene's handler; Mining.update() enforces the gate as a belt-and-braces.
- Rename `Mining.isLocked` to `isActive` and update GameScene click logic:
clicks no longer hold during extension — they move the ship and abort the
arm's reach.
- Tighten the popup-button swallow window from 300 ms to 20 ms and add a
`containsScreen()` hit-test so only the exact button press is consumed,
not subsequent deliberate clicks on the panel area.
- Expand the headless mining test to cover the new movement-abort contract:
world click mid-extension breaks the arm, autopilot retracts the beam,
and ship state transitions are asserted at every stage.
- Click a rock to open a world-anchored mining popup (Mine/Stop/Cancel)
- Mining state machine locks the ship during the ~1.5 s arm extension, then fires an animated beam with ore motes, shock rings, sparks, and periodic surges
- ESC breaks the beam or closes the menu; outside clicks dismiss without flying
- Generalize the top-center console toast so discovery, tether, and mining calls share one slot
- Add a "mining" SFX entry (system-scan.mp3) and update preload/test to cover all configured sounds
- Ship a headless browser test (dev/mining-test.*) that drives the full arm sequence through the real input pipeline