From b7d871388e0e88ce3301203a744d1067292bc8d2 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Sat, 30 May 2026 01:11:39 -0400 Subject: [PATCH] =?UTF-8?q?my-sea=20deck-stack=20+=20spread-card=20glow:?= =?UTF-8?q?=20unify=20hover-reveal=20/=20click-persist=20+=20--ninUser=20h?= =?UTF-8?q?alo=20=E2=80=94=20TDD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the glow/FLIP interaction across the owner picker (my_sea) + the read-only spectator (my_sea_visit), then carry the same selection halo onto the spread cards + deck-stack faces. DECK STACK (user-spec 2026-05-30) — the owner revealed the FLIP only on click (persisted) but never on hover; the spectator revealed it on hover but never persisted. Now BOTH do both: - `.sea-stack-ok` reveal is a single shared rule in _card-deck.scss — opacity fades in on hover/focus (ephemeral) OR via the JS-set `.sea-deck-stack--active` class (click-persist, same class the face-glow rides). The owner's inline `display` toggling is gone (`_showOk`/`_hideOk` just flip `--active`); the spectator's hover-only override in _gameboard.scss is removed. - Interactivity stays gated on `--active`, NOT hover: hover is a purely VISUAL preview (matching the spectator's disabled FLIP). This preserves the owner's two-step deal — were the FLIP click-through on hover, a single stack-click would land on the centred FLIP + deal early (caught by the draw FT). - Spectator persist wired in my_sea_visit.html (click a stack → `--active`, click elsewhere clears); its FLIP stays `.btn-disabled` (read-only). SPREAD CARDS — the same hover-glow + active-persist now on EVERY spread card, building on the cover/cross rules. The prior `.sea-card-slot--focused` glow (0-1-0) was silently overridden by the filled-card drop-shadow ladder (up to 0-4-0) and never rendered (verified live); `!important` (consistent w. the existing `opacity:1 !important` there) makes the halo win on hover + focus. The halo is symmetric (rotation-invariant). No colour change — box-shadow only. DECK FACE HALO — the levity + gravity stack glows now mirror the card halo's tuned geometry (0.5rem blur / 0.5rem spread / 0.3 alpha), each in its own polarity colour (--ninUser / --quaUser); single keeps its own tone. Verified live in Firefox: deck FLIP persists on click + fades on hover; the card halo wins over the drop-shadow on hover/focus across crown/cover/(reversed-)cross; levity/gravity deck glows match the card halo. Draw FTs green (single-draw, hand- completion, AUTO DRAW, auto-drawn-slot reopen) — the two-step deal + card focus survive the display→opacity switch. Code architected by Disco DeDisco Co-Authored-By: Claude Opus 4.8 (1M context) --- src/static_src/scss/_card-deck.scss | 59 ++++++++++++++++--- src/static_src/scss/_gameboard.scss | 19 ++---- src/templates/apps/gameboard/my_sea.html | 9 ++- .../apps/gameboard/my_sea_visit.html | 28 +++++++++ 4 files changed, 89 insertions(+), 26 deletions(-) diff --git a/src/static_src/scss/_card-deck.scss b/src/static_src/scss/_card-deck.scss index 85fd280..e6f5857 100644 --- a/src/static_src/scss/_card-deck.scss +++ b/src/static_src/scss/_card-deck.scss @@ -1696,15 +1696,35 @@ $sea-card-h: 6.5rem; .sea-pos-cover .sea-card-slot--visible { opacity: 0.3; animation: sea-cover-appear 2s ease; } .sea-pos-cross .sea-card-slot--visible { opacity: 0.15; animation: sea-cross-appear 2s ease; } -// Hover: reveal fully (snappy) -.sea-pos-cover .sea-card-slot--visible:hover, -.sea-pos-cross .sea-card-slot--visible:hover { opacity: 1; transition: opacity 0.15s ease; } +// ── Spread-card hover-glow + active-persist (user-spec 2026-05-30) ────────── +// Mirror the deck-stack's hover / `--active` glow onto EACH spread card: the +// customary --ninUser selection halo appears on HOVER + PERSISTS on the active +// (`.sea-card-slot--focused`) two-tap selection sea.js sets. Builds on the +// cover/cross opacity-reveal rules above. +// +// `!important`: the filled-card drop-shadow ladder (lines ~498-542) climbs to +// 0-4-0, so on a hovered/focused rotated card it out-specifies a plain +// `.sea-card-slot--focused` box-shadow (0-1-0) — exactly why the PRIOR focused +// glow silently never rendered (verified 2026-05-30). The halo is symmetric so +// it's rotation-invariant; it replaces the tiny directional drop (the +// established focused intent). No colour change — box-shadow only. +$_sea-card-glow: 0 0 0.5rem 0.5rem rgba(var(--ninUser), 0.3), 0 0 0.4rem rgba(0, 0, 0, 0.85); -// Focused (first tap): persist at opacity 1 + selection glow until modal opens +// Hover: Cover/Cross bump opacity to full (they overlay the semi-transparent +// sig); every position then gains the halo. +.sea-pos-cover .sea-card-slot--visible:hover, +.sea-pos-cross .sea-card-slot--visible:hover { opacity: 1; } +.my-sea-cross .sea-card-slot--visible:hover { + box-shadow: $_sea-card-glow !important; + transition: opacity 0.15s ease, box-shadow 0.15s ease; +} + +// Active/persist (first tap): hold full opacity + the halo until the second tap +// opens the stage (sea.js two-tap pattern, all positions). .sea-card-slot--focused { opacity: 1 !important; transition: opacity 0.15s ease, box-shadow 0.15s ease; - box-shadow: 0 0 0.5rem 0.25rem rgba(var(--ninUser), 0.35), 0 0 0.4rem rgba(0, 0, 0, 0.85); + box-shadow: $_sea-card-glow !important; } // Cover + Cross — absolutely overlaid on the Sig card in .sea-pos-core @@ -2000,7 +2020,27 @@ $sea-card-h: 6.5rem; margin: 0 auto; transform: translateY(-50%); z-index: 5; + // FLIP reveal — UNIFIED across the owner picker (my_sea) + the read-only + // spectator (my_sea_visit), user-spec 2026-05-30. Hidden + non-interactive + // by default; HOVER / focus fades it in ephemerally; a CLICK PERSISTS it via + // the JS-set `.sea-deck-stack--active` class (the same class the face-glow + // rules below persist on). Was split: the owner toggled `display` on click + // only (no hover); the spectator faded on hover only (no persist). + opacity: 0; + pointer-events: none; + transition: opacity 0.3s ease; } +.sea-deck-stack:hover .sea-stack-ok, +.sea-deck-stack:focus-within .sea-stack-ok, +.sea-deck-stack--active .sea-stack-ok { opacity: 1; } +// Interactivity is gated on the PERSIST state (`--active`), NOT hover. Hover is +// a purely VISUAL preview — same as the spectator's disabled FLIP, whose "hover +// effect" is just the reveal. Keeping the FLIP click-through on hover preserves +// the owner's two-step deal: click the stack (→ `--active`) THEN click the FLIP. +// Were it clickable on hover, a single stack-click would land on the centred +// FLIP itself + deal early. The spectator's FLIP stays `.btn-disabled` (read- +// only) so it never becomes interactive even while persisted. +.sea-deck-stack--active .sea-stack-ok:not(.btn-disabled) { pointer-events: auto; } .sea-deck-stack { gap: 0; } // remove gap so name slides under the face @@ -2021,8 +2061,13 @@ $sea-card-h: 6.5rem; // Deck backs — face-down pile colour identifies polarity $_sea-shadow: 1px 2px 0 rgba(0,0,0,0.7), 0 4px 0 rgba(0,0,0,0.18), 2px 5px 5px rgba(0,0,0,0.5); -$_glow-levity: 0 0 0.8rem 0.15rem rgba(var(--ninUser), 0.6); -$_glow-gravity: 0 0 0.8rem 0.15rem rgba(var(--quaUser), 0.6); +// Levity + gravity stack glows mirror the spread-card halo's tuned geometry +// ($_sea-card-glow, user-tuned 2026-05-30: 0.5rem blur / 0.5rem spread / 0.3 +// alpha) so the deck glows read identically to the card halo — each keeps its +// own polarity colour (--ninUser / --quaUser). Duplicated literally (not +// shared) so each stays independently tunable. (single keeps its own tone.) +$_glow-levity: 0 0 0.5rem 0.5rem rgba(var(--ninUser), 0.3); +$_glow-gravity: 0 0 0.5rem 0.5rem rgba(var(--ninUser), 0.3); .sea-deck-stack--levity .sea-stack-face { background: rgba(var(--terUser), 0.88); diff --git a/src/static_src/scss/_gameboard.scss b/src/static_src/scss/_gameboard.scss index e89ddfe..e26d483 100644 --- a/src/static_src/scss/_gameboard.scss +++ b/src/static_src/scss/_gameboard.scss @@ -808,20 +808,11 @@ body.page-gameboard { transform-origin: center; } - // Read-only FLIP (disabled ×) — hidden until its stack is hovered/focused, - // then eases in: same reveal shape as the shared `flip-btn-base` mixin - // (opacity 0→1 over 0.3s ease), inlined here because _gameboard.scss is - // imported before _card-deck.scss (where the mixin lives). Stays non- - // interactive — `.btn-disabled` keeps pointer-events:none. The base - // `.sea-stack-ok` positioning is untouched (we only add the fade). - .sea-stack-ok { - opacity: 0; - transition: opacity 0.3s ease; - } - .sea-deck-stack:hover .sea-stack-ok, - .sea-deck-stack:focus-within .sea-stack-ok { - opacity: 1; - } + // FLIP reveal (hover-fade + click-persist) is now the SHARED `.sea-stack-ok` + // behaviour in _card-deck.scss — unified with the owner picker per user-spec + // 2026-05-30, so the visitor's prior hover-only override is gone. The + // spectator's click-persist (`.sea-deck-stack--active`) is wired in + // my_sea_visit.html (the read-only FLIP stays disabled throughout). } // ── Iter 4b: Brief banner + DEL guard portal ───────────────────────────────── diff --git a/src/templates/apps/gameboard/my_sea.html b/src/templates/apps/gameboard/my_sea.html index 8cdc045..5fa9424 100644 --- a/src/templates/apps/gameboard/my_sea.html +++ b/src/templates/apps/gameboard/my_sea.html @@ -357,10 +357,12 @@ return DRAW_ORDER[hidden.value] || []; } + // FLIP visibility is now CSS-driven (opacity on hover/focus + + // the `.sea-deck-stack--active` persist class — unified w. the + // spectator page, user-spec 2026-05-30). `_showOk`/`_hideOk` just + // toggle `--active`; no more inline `display` juggling. function _hideOk() { if (_activeStack) { - var ok = _activeStack.querySelector('.sea-stack-ok'); - if (ok) ok.style.display = 'none'; _activeStack.classList.remove('sea-deck-stack--active'); _activeStack = null; } @@ -369,8 +371,6 @@ _hideOk(); _activeStack = stack; stack.classList.add('sea-deck-stack--active'); - var ok = stack.querySelector('.sea-stack-ok'); - if (ok) ok.style.display = ''; } function _fillSlot(positionName, card, isLevity) { @@ -529,7 +529,6 @@ }); var ok = stack.querySelector('.sea-stack-ok'); if (ok) { - ok.style.display = 'none'; ok.addEventListener('click', function (e) { e.stopPropagation(); // Hand complete → FLIP is disabled. No draw. diff --git a/src/templates/apps/gameboard/my_sea_visit.html b/src/templates/apps/gameboard/my_sea_visit.html index 7799689..594110d 100644 --- a/src/templates/apps/gameboard/my_sea_visit.html +++ b/src/templates/apps/gameboard/my_sea_visit.html @@ -137,6 +137,34 @@ } }()); + {# Deck-stack persist — the spectator's FLIP is disabled (read-only), but #} + {# clicking a stack PERSISTS its glow + the revealed × via the shared #} + {# `.sea-deck-stack--active` class (same persist the owner picker uses, #} + {# user-spec 2026-05-30). Hover-reveal + the fade are the shared CSS; this #} + {# only adds the click-to-lock. Clicking another stack / elsewhere clears. #} + {# Async witness — a WS to `mysea_` pushes the owner's hand as each #} {# card lands; SeaDeal.register fills the cross slot (+ seeds it clickable) #} {# live, no refresh. A DEL (empty hand) re-empties the cleared slots. #}