Implements scroll correction after cam.setZoom() so the world point
under the mouse stays fixed. Formula accounts for Phaser's
center-based zoom: scrollX += (mouseX - cw/2) * (1/zBefore - 1/zAfter).
Tab switches between the two test scenes in both directions.
Also fixes centerWorld formula in ZoomTestScene overlay and logs.
Text overlay now uses a dedicated HUD camera (zoom=1, fixed scroll)
so it's never scaled by the world zoom. World objects and HUD objects
are separated via camera ignore lists. Added red screen-center
crosshair to HUD layer as a precise alignment reference.
Vite dev server gets a /api/log middleware (POST appends to
game-test.log, DELETE clears it). ZoomTestScene writes a zoom event
with before/after state on every scroll, plus a full snapshot every
2 seconds. Log entries are newline-delimited JSON.
Separate test environment at /test.html (own Vite entry, own Phaser
instance). ZoomTestScene renders a 50×50 tile grid with crosshair
markers and a live HUD overlay showing zoom, scroll, viewport in px
and tiles, mouse world/screen/tile coords, and renderer info.
Zoom uses plain cam.setZoom() — no mouse tracking — to observe
Phaser's default center-anchor behavior.
- Scroll wheel now zooms toward the mouse cursor instead of screen center
- Middle mouse button held: pan camera by dragging
- Both actions respect current zoom level