- index.html/style.css: destructive-styled #match-quit-btn in the in-match
HUD row, two-click arm/confirm (no heavyweight modal).
- multiplayerMatch.ts: wires the button (send player:quit, tear down
timer/listeners/opponent pane immediately, no server reply awaited),
adds an optional onQuit constructor callback for a future host
(#14/#15) to route back to the main menu -- nothing mounts
MultiplayerMatch yet, so this ticket's own quit-button wiring is what
exercises it.
- ui/banBanner.ts (new): standalone renderBanBanner(container,
bannedUntil) countdown, ready for #14 to mount into #menu-matchmaking.
Not wired anywhere yet: per session.js/queue.js, quitting a
matchmaking match pushes nothing to the quitter directly -- the only
wire message carrying ban info is queue:banned, sent in reply to a
later queue:join while banned.
Verified against a real backend + real browser tab driving
MultiplayerMatch through an actual matchmaking match (paired against a
raw ws opponent): quit sends player:quit, opponent gets
room:playerLeft + room:closed(reason:quit) with no ban message; a
follow-up queue:join from the quitter correctly receives queue:banned
(bannedUntil ~120s out) and renderBanBanner counts it down live.
Repeated via room:create/room:join (private room): identical
teardown/onQuit behavior, opponent gets zero ban-related messages, and
the quitter's earlier matchmaking ban is left completely unchanged.