- SoundManager via Web Audio API (no asset files needed) with procedural
SFX for jump, spring, powerup, stomp, break, death, milestone, new-best
- Sound persists mute state in localStorage; mute button on Menu and Game
- Pause system: ESC key or onscreen pause button, modal overlay with
Resume and Main Menu options, physics correctly paused/resumed
- First-run tutorial overlay explaining controls and platform types,
dismissed and remembered via localStorage flag
- Touch indicator hints fade after 3.5s on touch devices only
- Menu start triggers AudioContext initialization (browser autoplay rules)
- GameOverScene supports ENTER/SPACE shortcut for retry, NEW BEST text
now pulses, sounds fire on each transition
- Fix Rocket/PropellerHat hitboxes (relative to sprite size, not magic offsets)
- Spring now destroys itself on use with squash animation instead of staying invisible
- Guard all powerups against double-trigger via consumed flag
- Save genesis glow tween reference for clean destroy
- Player.die() disables collisions (no more post-death platform bounces)
- Replace hardcoded enemy spawn cap 0.5 with DIFFICULTY.maxEnemyRate
- Enemy spawn position now anchored to platform X (-60/+60), not random
- Powerup spawn clamped to screen bounds
- Skip powerup spawn on breaking platforms (was unfair)
- ScoreManager.addPoints() public method; remove direct score mutation
- HUD elements use setScrollFactor(0) instead of per-frame repositioning
- All magic numbers extracted to SCORE / PHYSICS / POWERUP_DURATION config
- Remove dead code: showDeathVignette, drawDebug, createParticles, deathOverlay
- Remove dead constants: PLATFORM_WIDTH/HEIGHT, PLAYER_MAX_SPEED, tileBias
- Remove SUBMIT TO CHAIN fake button, replace with Coming Soon text
- Safer cleanup loop: collect-then-destroy instead of mutating during iterate
- gwei particles now have setScrollFactor(0.3) for parallax depth