cb93bd9265
Two fixes the smoke test surfaced:
1. The forfeit-confirm modal at `Z_PAUSE_DIALOG` (225) was invisible
behind the pause card at `Z_PAUSE` (220). In Bevy 0.18, root-level
UI nodes don't reliably sort across stacking contexts via plain
`ZIndex` alone, so `spawn_modal` now adds `GlobalZIndex(z_panel)`
alongside the existing `ZIndex(z_panel)`. Every overlay built on
`ui_modal` (pause, forfeit-confirm, confirm-new-game, help, home,
leaderboard, profile, achievements, stats, game-over) inherits the
fix.
2. `handle_forfeit_request` no longer silently drops the request when
`move_count == 0` — pressing G or clicking the pause modal's
Forfeit button on a freshly-dealt game now opens the confirm modal,
and the only short-circuit is "game is already won", which now
fires an `InfoToastEvent` ("No game to forfeit") so the player
gets feedback. The `move_count > 0` half of the gate was the
reason a fresh-deal G press appeared to do nothing.
The G-key gate in `handle_keyboard_forfeit` is simplified to just
"not paused"; the rest of the forfeit-eligibility check moves into
`handle_forfeit_request` so it can surface the toast.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>