From e2c7a55dac2f2d1bab0fb7d91c1faadbb39dbd12 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Mon, 23 Feb 2026 19:16:20 -0500 Subject: [PATCH] Fix held card displacement in landscape and tooltip crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- client/app.js | 9 +++++---- client/card-animations.js | 2 +- scripts/deploy-staging.sh | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100755 scripts/deploy-staging.sh diff --git a/client/app.js b/client/app.js index a2a0e61..7ad43a2 100644 --- a/client/app.js +++ b/client/app.js @@ -379,7 +379,7 @@ class GolfGame { // Only show tooltips on your turn if (!this.isMyTurn() && !this.gameState?.waiting_for_initial_flip) return; - const value = this.getCardPointValue(cardData); + const value = this.getCardPointValueForTooltip(cardData); const special = this.getCardSpecialNote(cardData); let content = `${value} pts`; @@ -409,14 +409,15 @@ class GolfGame { if (this.tooltip) this.tooltip.classList.add('hidden'); } - getCardPointValue(cardData) { + getCardPointValueForTooltip(cardData) { const values = this.gameState?.card_values || this.getDefaultCardValues(); - return values[cardData.rank] ?? 0; + const rules = this.gameState?.scoring_rules || {}; + return this.getCardPointValue(cardData, values, rules); } getCardSpecialNote(cardData) { const rank = cardData.rank; - const value = this.getCardPointValue(cardData); + const value = this.getCardPointValueForTooltip(cardData); if (value < 0) return 'Negative - keep it!'; if (rank === 'K' && value === 0) return 'Safe card'; if (rank === 'K' && value === -2) return 'Super King!'; diff --git a/client/card-animations.js b/client/card-animations.js index cbb29a1..db0212f 100644 --- a/client/card-animations.js +++ b/client/card-animations.js @@ -765,7 +765,7 @@ class CardAnimations { // Quick shake animation - target cards only, not labels const T = window.TIMING?.turnPulse || {}; - const cards = element.querySelectorAll(':scope > .pile-wrapper > .card, :scope > .pile-wrapper > .discard-stack'); + const cards = element.querySelectorAll(':scope > .pile-wrapper > .card, :scope > .pile-wrapper > .discard-stack > #discard'); const doShake = () => { if (!this.activeAnimations.has(id)) return; diff --git a/scripts/deploy-staging.sh b/scripts/deploy-staging.sh new file mode 100755 index 0000000..1e58af2 --- /dev/null +++ b/scripts/deploy-staging.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +DROPLET="root@129.212.150.189" +REMOTE_DIR="/opt/golfgame" + +echo "Syncing to staging ($DROPLET)..." +rsync -az --delete \ + --exclude='.git' \ + --exclude='__pycache__' \ + --exclude='node_modules' \ + --exclude='.env' \ + --exclude='internal/' \ + server/ "$DROPLET:$REMOTE_DIR/server/" +rsync -az --delete \ + --exclude='.git' \ + --exclude='__pycache__' \ + --exclude='node_modules' \ + client/ "$DROPLET:$REMOTE_DIR/client/" + +echo "Rebuilding app container..." +ssh $DROPLET "cd $REMOTE_DIR && docker compose -f docker-compose.staging.yml up -d --build app" +echo "Staging deploy complete."