Commit Graph

228 Commits

Author SHA1 Message Date
adlee-was-taken
7f0f580631 Add client-side card reveal before swap and YOUR TURN badge update
Reveal face-down cards briefly (1s) before swap completes, using
client-side state diffing instead of a separate server message.
Local player reveals use existing card data; opponent reveals use
server-sent card_revealed as a fallback. Defers incoming game_state
updates during the reveal window to prevent overwrites.

Also update YOUR TURN badge to cyan with suit symbols.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:35:49 -05:00
adlee-was-taken
215849703c Add inline comments across client and server codebase
Full-codebase commenting pass focused on the tricky, fragile, and
non-obvious spots: animation coordination flags in app.js, AI decision
safety checks in ai.py, scoring evaluation order in game.py, animation
engine magic numbers in card-animations.js, and server infrastructure
coupling in main.py/handlers.py/room.py. No logic changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:17:19 -05:00
adlee-was-taken
72eab2c811 TUI visual polish: felt table, status bar, scoreboard delay
- Dark green felt background for game screen
- Status bar: dark brown bg with amber text instead of blue
- YOUR TURN badge: green bg with white text instead of bright gold
- 3s delay before hole-complete scoreboard overlay
- Dealer indicator changed from Ⓓ to (D)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:56:01 -05:00
adlee-was-taken
dfb3397dcb Overhaul TUI navigation, quit handling, and scoreboard tags
- Replace [esc][esc] quit with [q] quit globally (immediate on login,
  confirmation prompt elsewhere)
- [esc] is now consistently "back": signup→login, lobby→log out (with
  confirm), in-room host→leave (with confirm), in-room guest→leave
- Extract ConfirmScreen to shared screens/confirm.py
- Move dealer Ⓓ indicator to bottom-left corner of player box border
- Scoreboard now tags OUT (went out first) and  (lowest score)
- Send finisher_id and player id in round_over server message
- Room code moved inside in-room section with amber border
- Lobby title uses branded 🏌️ GolfCards.club ♠♥♣♦
- Amber borders and dark green backgrounds on login/lobby containers
- Deck preview renders actual card-back shapes (▓▒▓/▒▓▒)
- Help/standings panels close only with [esc], hint updated
- Game footer: s[⇥]andings [h]elp on left, [q]uit on right

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:41:45 -05:00
adlee-was-taken
b1d3aa7b77 Add session persistence, splash screen, and TUI polish
Save JWT token to ~/.config/golfcards/session.json after login so
subsequent launches skip the login screen when the session is still
valid. A new splash screen shows the token check status (SUCCESS /
NONE FOUND / EXPIRED) before routing to lobby or login.

Also: move OUT indicator to player box bottom border, remove checkmark,
center scoreboard overlay, use alternating shade blocks (▓▒▓/▒▓▒) for
card backs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 19:35:03 -05:00
adlee-was-taken
67d06d9799 Mark stale games as abandoned in DB during cleanup and on startup
- Periodic room cleanup now updates games_v2 status to 'abandoned'
- Server startup marks all orphaned active games as abandoned
- Prevents stale games from accumulating in the admin portal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:25:03 -05:00
adlee-was-taken
82aa3dfb3e Add auto-cleanup of stale game rooms after 5 minutes of inactivity
Rooms that sit idle (no player actions or CPU turns) for longer than
ROOM_IDLE_TIMEOUT_SECONDS (default 300s) are now automatically cleaned
up: CPU tasks cancelled, players notified with room_expired, WebSockets
closed, and room removed from memory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:17:57 -05:00
adlee-was-taken
7001232658 Add single-escape navigation: back from signup/lobby, leave room
- Single Esc: goes back one step (signup→login, lobby→connect, room→lobby)
- Double Esc: still quits the app
- Footer bar shows [Esc] Back and [Esc][Esc] Quit hints on all screens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 20:17:10 -05:00
adlee-was-taken
13e98d330a Add TUI signup flow, quit/help/standings modals, and UI refinements
- Add signup with invite code support, remove guest login
- Add quit confirmation (q), help screen (h), standings tab
- Unified footer: [h]elp [q]uit | action text | [tab] standings
- Amber card highlighting persists through entire initial flip phase
- Player box border only highlights on turn (green) or knock (red)
- Play area gold border only during player's actual turn
- Game end returns to lobby create/join instead of login screen
- Lobby reset_to_pre_room for replayability without reconnecting
- Dynamic opponent layout fits all in one row when terminal is wide enough
- Hole emoji () in status bar, branded title with suits on connect screen
- DECK label spacing, Hole terminology in scoreboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 20:14:04 -05:00
adlee-was-taken
bfe29bb665 Add TUI lobby settings, clickable cards, and UI polish
- Lobby: collapsible Game Settings, House Rules, Deck Style sections
- Lobby: CPU profile picker via [+], random CPU via [?], remove via [-]
- Lobby: all settings (rounds, decks, flip mode, house rules, deck colors)
  sent to server on start_game instead of hardcoded defaults
- Game: clickable cards (hand positions, deck, discard pile)
- Game: immediate visual feedback on initial card flips
- Game: action bar shows escaped keyboard hints (Keyboard: Choose [d]eck...)
- Game: play area uses fixed-width rounded box instead of horizontal lines
- Game: position numbers on card top-left corner (replacing ┌) on all states
- Game: deck color preview swatches next to style dropdown
- Fix opponent box height mismatch when match connectors present
- Rebrand to GolfCards.club
- Add spacing between status bar/opponents and above local hand

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:23:27 -05:00
adlee-was-taken
e601c3eac4 Add DAILY_OPEN_SIGNUPS and DAILY_SIGNUPS_PER_IP to compose env vars
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:38:25 -05:00
adlee-was-taken
6461a7f0c7 Add metered open signups, per-IP limits, and auth security hardening
Enables public beta signup metering: DAILY_OPEN_SIGNUPS env var controls
how many users can register without an invite code per day (0=disabled,
-1=unlimited, N=daily cap). Invite codes always bypass the limit.

Also adds per-IP signup throttling (DAILY_SIGNUPS_PER_IP, default 3/day)
and fail-closed rate limiting on auth endpoints when Redis is down.

Client dynamically fetches /api/auth/signup-info to show invite field
as optional with remaining slots when open signups are enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:28:28 -05:00
adlee-was-taken
3d02d739e5 Set prod log level default to WARNING
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 02:00:33 -05:00
adlee-was-taken
3ca52eb7d1 Bump version to 3.1.6, update docs
Update version across pyproject.toml, FastAPI app, HTML footers,
and V3.17 doc. Mark kicked-ball bug as resolved in docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:59:54 -05:00
adlee-was-taken
3c63af91f2 Bump mobile logo-golfer gap from 12px to 15px
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:56:43 -05:00
adlee-was-taken
5fcf8bab60 Fix logo-golfer spacing: source order bug, tighten landscape, widen mobile
Base .golfer-container rule was after the mobile @media override,
clobbering it. Moved base rule before the media query. Landscape
gets -2px (snug), mobile gets 12px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:55:28 -05:00
adlee-was-taken
8bc8595b39 Adjust logo-golfer spacing: tighter landscape, more room on mobile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:54:08 -05:00
adlee-was-taken
7c58543ec8 Tighten landscape logo-golfer gap, alternate suit colors on ball logo
Reduce golfer-container margin from 10px to 4px in landscape (2-row)
mode while keeping 10px on mobile. Swap bottom suits to checkerboard
pattern: club/diamond on top, heart/spade on bottom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:52:25 -05:00
adlee-was-taken
4b00094140 Add spacing between logo ball and golfer container
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:48:44 -05:00
adlee-was-taken
65d6598a51 Fix kicked ball launching from golfer's back foot at narrow viewports
Wrap golfer+ball in a positioned container so the ball is absolutely
anchored to the golfer's front foot, independent of inline flow/viewport.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:47:06 -05:00
adlee-was-taken
baa471307e Tune lobby header: 2x2 suit grid, mobile spacing, tighter row gap
- Rearrange golf ball SVG suits from single row to 2x2 grid
- Add even spacing between logo, golfer, and title in mobile view
- Remove row-gap between logo row and title row in landscape view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:35:25 -05:00
adlee-was-taken
26778e4b02 Fix lobby header: use inline-grid for logo/title layout
The 749px media query was triggering at mid-range widths, collapsing
the two-row logo+title into a single line. Fix by:
- Using inline-grid on h1 for bulletproof two-row layout
- Lowering single-line breakpoint from 749px to 500px
- Widening lobby container to 550px for title to fit naturally
- Constraining game controls to 400px max-width

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:22:34 -05:00
adlee-was-taken
cce2d661a2 Fix logo-row centering at mid-range widths (750-1120px)
Change .logo-row from inline-block to block so the golf ball logo
always left-aligns flush with the G, regardless of viewport width.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:26:52 -05:00
adlee-was-taken
1b748470a0 Use width:fit-content on h1 for bulletproof logo-title alignment
The h1 shrinks to its widest child (GolfCards.club), centers via
margin auto, and text-align left aligns both lines within it.
No breakpoint-dependent transforms needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:14:56 -05:00
adlee-was-taken
d32ae83ce2 Nudge mobile header line 18px left via text-indent
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:07:58 -05:00
adlee-was-taken
e542cadedf Bump mobile single-line breakpoint to 749px to cover all phones
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:06:39 -05:00
adlee-was-taken
cd2d7535e3 Replace translateX hack with text-align left on h1 for logo alignment
Logo and title naturally left-align within the centered lobby box.
Mobile (<480px) gets text-align center + inline display for single line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:02:17 -05:00
adlee-was-taken
4dff1da875 Only trigger single-line mode at <=449px, shift everywhere else
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:59:51 -05:00
adlee-was-taken
8f21a40a6a Make logo-row inline on mobile for single-line header layout
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:58:28 -05:00
adlee-was-taken
0ae999aca6 Revert flex approach, use default translateX with max-width reset for mobile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:57:49 -05:00
adlee-was-taken
a87cd7f4b0 Use inline-flex column on h1 to left-align logo row with title
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:56:38 -05:00
adlee-was-taken
eb072dbfb4 Set logo-row shift to 750px breakpoint (mobile ends ~750px)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:54:10 -05:00
adlee-was-taken
4c16147ace Set logo-row shift breakpoint to 900px to match actual layout break
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:51:40 -05:00
adlee-was-taken
cac1e26bac Split the difference: logo-row shift at 600px breakpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:49:21 -05:00
adlee-was-taken
31dcb70fc8 Bump logo-row shift breakpoint to 768px so mobile stays centered
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:47:31 -05:00
adlee-was-taken
15339d390f Use min-width breakpoint for logo shift, tighten logo-title gap
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:45:38 -05:00
adlee-was-taken
c523b144f5 Tighten logo-golfer gap and shift row further left on landscape
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:40:52 -05:00
adlee-was-taken
0f3ae992f9 Wrap logo+golfer in .logo-row and translateX left on landscape
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:36:00 -05:00
adlee-was-taken
ce6b276c11 Increase logo left shift to -3.5rem to align with GolfCards text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:33:16 -05:00
adlee-was-taken
231e666407 Fix logo shift direction: move left on landscape, not right
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:31:38 -05:00
adlee-was-taken
7842de3a96 Shift logo+golfer group right on landscape via margin-left
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:29:47 -05:00
adlee-was-taken
aab41c5413 Restore logo-golfer-ball order in header
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:23:49 -05:00
adlee-was-taken
625320992e Move golfer emoji left of logo, make .club inline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:22:53 -05:00
adlee-was-taken
61713f28c8 Style GolfCards title with .club on second line
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:13:40 -05:00
adlee-was-taken
0eac6d443c Rename lobby title from Golf to GolfCards.Club
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:11:39 -05:00
adlee-was-taken
dc936d7e1c Add v3.1.5 footer with copyright to lobby and waiting room
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:08:39 -05:00
adlee-was-taken
1cdf1cf281 Tune round-end pause and reduce deck shake frequency
Cut lastPlayPause to 2s and increase shake interval by 80% (3s→5.4s)
so the draw/discard nudge feels less nagging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:06:17 -05:00
adlee-was-taken
17f7d8ce7a Fix draw-swap animation race and smarter CPU go-out decisions
Increase post_draw_settle timing (1.1s→1.3s) and swap retry delay
(100ms→350ms) to prevent draw animation from being cut short by the
arriving swap animation. Also make CPU go-out decisions consider
opponent scores and avoid swapping high cards (8+) into hidden slots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:57:59 -05:00
adlee-was-taken
9a5bc888cb Compact scoresheet modal to reduce scrolling with 4 players
Tighten padding, gaps, card sizes, and margins across all scoresheet
elements so the full modal fits without scrolling on most viewports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:41:03 -05:00
adlee-was-taken
3dcad3dfdf Fix round-end reveal timing: pause after last play, handle deferred state
Two issues fixed:

1. renderGame() was called before the lastPlayPause delay, causing the
   board to jump to final card positions while the swap animation was
   still visually playing. Moved renderGame() to after the wait+pause.

2. When the local player makes the final play, their swap animation
   defers the round_over game_state to pendingGameState. The deferred
   state bypassed the round-end intercept, so preRevealState was never
   set — causing the scoresheet to appear immediately without the
   reveal animation. Now completeSwapAnimation checks for round_over
   transitions and sets preRevealState. Also added a wait loop in
   runRoundEndReveal for robustness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:35:02 -05:00