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>
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>
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>
- 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>
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>
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>
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>
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>
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>
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>
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>
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>
Force discard pile DOM update before draw animation starts to prevent
stale card display when previous swap animation blocked renderGame.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move CPU +/- buttons inline into Players header row with "CPU:" label
- Tighten vertical spacing for mobile stacked layout (≤700px)
- Fit Decks/Holes/Card Backs settings in single row on mobile
- Reduce room code banner and auth bar edge margins
- Consistent spacing across all stacked viewport widths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Style the flip overlay's front face to match player hand cards (gradient
background, proper border/shadow) instead of using generic card-front
styles. Hide the underlying card during the animation so the green table
shows through the flip rather than a white card peeking behind it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The turn pulse shake was targeting .discard-stack, which is an ancestor of
#held-card-floating. A CSS transform on any ancestor breaks position:fixed,
causing the held card to render far from the deck area. Now target #discard
directly instead.
Also fix duplicate getCardPointValue methods — the 3-arg scoring version
shadowed the 1-arg tooltip version, leaving cardValues undefined on hover.
Add staging deploy script (rsync working tree, no git pull needed).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix dumb AI knocks (e.g. Maya knocking on 13 points) by adding opponent
threat checks and a hard cap of 10 to should_knock_early(). Remove dead
should_go_out_early() call whose return value was never used. Retune knock
chance tiers to be more conservative at higher projected scores.
On the client side, fix round-end reveal sequencing so the last player's
swap/discard animation plays before the reveal sequence starts, and prevent
re-renders from clobbering swap animations during reveals. Also make the
turn-pulse shake configurable via timing-config and target only cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mirrors production config with reduced memory limits (128M app, 96M
postgres, 32M redis, 48M traefik) and staging defaults. Rate limiting
disabled for easier testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LOG_LEVEL and ENVIRONMENT were hardcoded, overriding .env values.
Now uses ${VAR:-default} so .env settings are respected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Support LOG_LEVEL_{MODULE} env vars (GAME, AI, HANDLERS, ROOM, AUTH,
STORES) to override the global log level for specific modules. Active
overrides are logged at startup. Includes staging/production presets
in .env.example files and a V3.18 stub doc for PostgreSQL storage
efficiency investigation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Default gradient on base .status-message (dark green)
- Add round-over/game-over (gold) and reveal (purple) gradient styles
- Tag action prompts (swap, flip, discard) as your-turn type
- Match final-turn badge font size and padding to status message on mobile
- Hide status message when empty
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Align header-col-center to flex-start on mobile so the status and
final-turn badges sit flush left. Match final-turn-badge border-radius
and padding to status-message for consistent shape.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mute button in header-right throws off visual centering of the status
text. Left-aligning looks intentional rather than off-center.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
overflow:hidden on body.mobile-portrait was blocking scroll on all
screens. Scope it to only when the game screen is active using :has().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>