Eight small tickets in one PR. Stacked on fix/write-failure-handling; target that branch.
- HAD-175: sign-in and create-game forms called
preventDefaulton neither, so a submit could navigate away as a GET. - HAD-176: the home page had no
<title>. Every other route already had one. - HAD-177: the move list now follows the game, unless the reader has scrolled back
to look at something. Direct
scrollTop, so it respects reduced motion for free. - HAD-178: resigning is irreversible and was one click. Now a confirmation step
that auto-dismisses after five seconds, announced with
role="alert". - HAD-179: form errors in the login, create-game and challenge views appear after
a user action but were not announced. Added
role="alert". - HAD-197: the result banner coloured wins green and losses red for spectators too, from White's perspective, so a spectator of a Black win saw red.
- HAD-198: reloading a finished game composed the share text before the opponent's handle resolved, leaving "opponent" in the post. It now recomposes when the handle arrives, and stops as soon as you edit the text yourself.
- HAD-199: rematch offers were never seen after reloading a finished game, because the Jetstream connection was only opened for active ones.
No tests: all of this is component behaviour (scroll position, a confirmation flow, ARIA attributes) and there is no component-test harness in the project yet.