commits
The min-h-[44px] on the sign-out button was stretching the header from
53px to 69px on all viewports. Adding -my-2.5 lets the 44px hit area
extend into the header padding without growing the header itself.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Future contributors need to know that the app must work well on phones
down to iPhone SE 2/3 (375x600). Codifies the md breakpoint policy and
the 44px tap-target floor so the next layout change does not silently
regress mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avatars and color placeholders bump from h-8 to h-9 and gain shrink-0
so they don't collapse when the action slot is busy at narrow widths.
Outer gap drops to gap-2 on mobile (md:gap-3 on desktop) so a two-button
action group doesn't push the clock against the name.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds min-w-0 on flex parents (without which truncate is a no-op inside
flex), truncate + ellipsis on the display name, and min-h-[44px] on the
sign-out button so the hit area meets Apple HIG's 44px floor on touch
devices. Visual chrome unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile (<768px) now uses the MoveDrawerPanel triggered from the bottom
PlayerBar; desktop (>=768px) keeps the side-by-side sidebar layout.
Outer padding reduced to p-2 on mobile so the board reclaims ~16px of
horizontal space on small phones. Drawer auto-closes when activeGame.id
changes to avoid a stale-open state across games.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bottom-sheet drawer that wraps the existing MoveList. Two stateless
pieces (trigger + panel) so the trigger can be slotted into PlayerBar
while the panel sits at screen level. Dismissible via backdrop tap,
close button, or Escape key. Mobile-only (md:hidden); desktop continues
to use the sidebar MoveList.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eight tasks: TDD MoveDrawer (Task 1), wire it into GameScreen with the
md-breakpoint switch (Task 2), Header tap-targets+truncate (Task 3),
PlayerBar tweaks (Task 4), GameStatus tap-target (Task 5), verify
Lobby/Login (Task 6), CLAUDE.md (Task 7), final acceptance (Task 8).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Captures the brainstormed design for making all pages render well on
phones down to iPhone SE 2/3 (375x600 effective viewport). Single
breakpoint (md), one new component (MoveDrawer), tap-target bumps to
44px floor. Header keeps a single treatment for maintenance simplicity.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace pure-black neutral palette with dark walnut (wood-*) background,
casino felt green (felt-*) accents, and warm brass gold (gold-*) for branding
- Add Playfair Display (headings) + DM Sans (UI) via Google Fonts
- Subtle repeating-conic-gradient checkerboard on body for chess texture
- LobbyScreen: replace 2x2 button grid with refined vertical menu list
with decorative chess piece icons (knight/bishop/rook/queen per speed)
- Header: gold Playfair Display wordmark with king logo mark
- LoginScreen: large serif title, form in warm dark panel
- GameStatus modal: Playfair Display heading, felt-green CTA button
- PlayerBar/MoveList/ClockDisplay: neutral-* replaced with wood-* tokens
- Fix LoginScreen test: Loading... to proper ellipsis character
Fix: republish SpacetimeDB module to resolve schema/client mismatch.
Server had old 10-field game schema; client bindings expected 13 fields
(timeControlSecs, whiteTimeMs, blackTimeMs added in prior commit but never
published), causing RangeError on every WebSocket message. Document the
three-step sync procedure in CLAUDE.md so it does not recur.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lift dismissedGameId state from GameScreen into App so routing decisions
stay in one place; fixes black screen on "Back to Lobby" after game ends
- useGame now returns recently-ended games (not just active) so the
checkmate/resign/draw overlay can render before the lobby re-appears
- GameScreen accepts onDismiss prop instead of managing its own routing state
- Player bar active indicator now derived from orientation, not isWhite,
fixing colors in edge cases
- useGamePublisher waits for all player data before publishing to atproto
and marks games published only after confirming data is available
- Escape backslashes and double quotes in PGN tag values to prevent header
injection via crafted Bluesky display names
- registerPlayer: add length limits on DID/handle/displayName/avatarUrl and
make DID immutable after registration to prevent identity impersonation
- Add server-logic.test.ts mirroring makeMove reducer (15 tests) and expand
pgn.test.ts with escaping edge cases (3 tests); all 78 tests passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avatars and color placeholders bump from h-8 to h-9 and gain shrink-0
so they don't collapse when the action slot is busy at narrow widths.
Outer gap drops to gap-2 on mobile (md:gap-3 on desktop) so a two-button
action group doesn't push the clock against the name.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds min-w-0 on flex parents (without which truncate is a no-op inside
flex), truncate + ellipsis on the display name, and min-h-[44px] on the
sign-out button so the hit area meets Apple HIG's 44px floor on touch
devices. Visual chrome unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile (<768px) now uses the MoveDrawerPanel triggered from the bottom
PlayerBar; desktop (>=768px) keeps the side-by-side sidebar layout.
Outer padding reduced to p-2 on mobile so the board reclaims ~16px of
horizontal space on small phones. Drawer auto-closes when activeGame.id
changes to avoid a stale-open state across games.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bottom-sheet drawer that wraps the existing MoveList. Two stateless
pieces (trigger + panel) so the trigger can be slotted into PlayerBar
while the panel sits at screen level. Dismissible via backdrop tap,
close button, or Escape key. Mobile-only (md:hidden); desktop continues
to use the sidebar MoveList.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eight tasks: TDD MoveDrawer (Task 1), wire it into GameScreen with the
md-breakpoint switch (Task 2), Header tap-targets+truncate (Task 3),
PlayerBar tweaks (Task 4), GameStatus tap-target (Task 5), verify
Lobby/Login (Task 6), CLAUDE.md (Task 7), final acceptance (Task 8).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Captures the brainstormed design for making all pages render well on
phones down to iPhone SE 2/3 (375x600 effective viewport). Single
breakpoint (md), one new component (MoveDrawer), tap-target bumps to
44px floor. Header keeps a single treatment for maintenance simplicity.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace pure-black neutral palette with dark walnut (wood-*) background,
casino felt green (felt-*) accents, and warm brass gold (gold-*) for branding
- Add Playfair Display (headings) + DM Sans (UI) via Google Fonts
- Subtle repeating-conic-gradient checkerboard on body for chess texture
- LobbyScreen: replace 2x2 button grid with refined vertical menu list
with decorative chess piece icons (knight/bishop/rook/queen per speed)
- Header: gold Playfair Display wordmark with king logo mark
- LoginScreen: large serif title, form in warm dark panel
- GameStatus modal: Playfair Display heading, felt-green CTA button
- PlayerBar/MoveList/ClockDisplay: neutral-* replaced with wood-* tokens
- Fix LoginScreen test: Loading... to proper ellipsis character
Fix: republish SpacetimeDB module to resolve schema/client mismatch.
Server had old 10-field game schema; client bindings expected 13 fields
(timeControlSecs, whiteTimeMs, blackTimeMs added in prior commit but never
published), causing RangeError on every WebSocket message. Document the
three-step sync procedure in CLAUDE.md so it does not recur.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lift dismissedGameId state from GameScreen into App so routing decisions
stay in one place; fixes black screen on "Back to Lobby" after game ends
- useGame now returns recently-ended games (not just active) so the
checkmate/resign/draw overlay can render before the lobby re-appears
- GameScreen accepts onDismiss prop instead of managing its own routing state
- Player bar active indicator now derived from orientation, not isWhite,
fixing colors in edge cases
- useGamePublisher waits for all player data before publishing to atproto
and marks games published only after confirming data is available
- Escape backslashes and double quotes in PGN tag values to prevent header
injection via crafted Bluesky display names
- registerPlayer: add length limits on DID/handle/displayName/avatarUrl and
make DID immutable after registration to prevent identity impersonation
- Add server-logic.test.ts mirroring makeMove reducer (15 tests) and expand
pgn.test.ts with escaping edge cases (3 tests); all 78 tests passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>