sea deck stack: rename the stale .sea-stack-ok class to .sea-stack-flip (the btn renders FLIP now) — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful

Pure rename, no behavior change — the deck-stack reveal btn kept the name `.sea-stack-ok` from when it said OK; it has rendered FLIP for a while. Renamed across all 8 references: _card-deck.scss (reveal + pointer-events rules) + a _gameboard.scss comment; the 3 templates that emit or query it (_sea_overlay.html, _my_sea_deck_stack.html, my_sea.html inline JS); and the 3 tests that select it (test_game_room_select_sea FT, test_game_my_sea FT, test_sea_visit IT rendered-HTML asserts). Verified 47 green across all three surfaces (visit IT + gameroom PickSeaDeal stack FT + my_sea CardDraw FT).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-08 13:04:51 -04:00
parent c9fc5a2fd4
commit d50645b216
8 changed files with 25 additions and 25 deletions

View File

@@ -165,9 +165,9 @@ class MySeaVisitContextTest(TestCase):
self.assertIn("sea-deck-stack--gravity", html)
self.assertIn("sea-deck-stack--levity", html)
# FLIP is the disabled (×) state; never an enabled FLIP for a visitor.
self.assertIn("sea-stack-ok btn-disabled", html)
self.assertIn("sea-stack-flip btn-disabled", html)
self.assertNotIn(
'class="btn btn-reveal sea-stack-ok" type="button">FLIP', html)
'class="btn btn-reveal sea-stack-flip" type="button">FLIP', html)
def test_stack_keys_on_owner_deck_not_viewer_deck(self):
# Viewer has no deck, owner has one → the stack still renders (it's the

View File

@@ -756,7 +756,7 @@ class MySeaCardDrawTest(FunctionalTest):
)
stack.click()
flip = self.wait_for(
lambda: stack.find_element(By.CSS_SELECTOR, ".sea-stack-ok")
lambda: stack.find_element(By.CSS_SELECTOR, ".sea-stack-flip")
)
self.wait_for(lambda: self.assertTrue(flip.is_displayed()))
flip.click()

View File

@@ -299,7 +299,7 @@ class PickSeaDealTest(ChannelsFunctionalTest):
))
self.browser.execute_script("arguments[0].click()", stack)
ok_btn = self.wait_for(lambda: self.browser.find_element(
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-ok"
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-flip"
))
# Choosing the spread scroll-snaps the felt onto two pages; the deck
# stacks sit on a different page than the post-OK scroll lands on in
@@ -320,14 +320,14 @@ class PickSeaDealTest(ChannelsFunctionalTest):
))
self.browser.execute_script("arguments[0].click()", stack)
self.wait_for(lambda: self.browser.find_element(
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-ok"
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-flip"
).is_displayed())
# Click the sea cards column (not a stack)
col = self.browser.find_element(By.CSS_SELECTOR, ".sea-cards-col")
self.browser.execute_script("arguments[0].click()", col)
self.wait_for(lambda: not any(
el.is_displayed()
for el in self.browser.find_elements(By.CSS_SELECTOR, ".sea-stack-ok")
for el in self.browser.find_elements(By.CSS_SELECTOR, ".sea-stack-flip")
))
# ── Card draw ─────────────────────────────────────────────────────── #
@@ -340,7 +340,7 @@ class PickSeaDealTest(ChannelsFunctionalTest):
))
self.browser.execute_script("arguments[0].click()", stack)
ok_btn = self.wait_for(lambda: self.browser.find_element(
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-ok"
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-flip"
))
self.browser.execute_script("arguments[0].click()", ok_btn)
self.wait_for(lambda: self.browser.find_element(
@@ -361,7 +361,7 @@ class PickSeaDealTest(ChannelsFunctionalTest):
))
self.browser.execute_script("arguments[0].click()", stack)
ok_btn = self.wait_for(lambda: self.browser.find_element(
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-ok"
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-flip"
))
self.browser.execute_script("arguments[0].click()", ok_btn)
@@ -370,7 +370,7 @@ class PickSeaDealTest(ChannelsFunctionalTest):
self.wait_for(lambda: self.assertIn(
"btn-disabled",
self.browser.find_element(
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-ok"
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-flip"
).get_attribute("class"),
))
@@ -383,7 +383,7 @@ class PickSeaDealTest(ChannelsFunctionalTest):
))
self.browser.execute_script("arguments[0].click()", stack)
ok_btn = self.wait_for(lambda: self.browser.find_element(
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-ok"
By.CSS_SELECTOR, ".sea-deck-stack--levity .sea-stack-flip"
))
self.browser.execute_script("arguments[0].click()", ok_btn)
self.wait_for(lambda: self.browser.find_element(

View File

@@ -2046,7 +2046,7 @@ $_sea-card-glow: 0 0 0.5rem 0.5rem rgba(var(--ninUser), 0.3), 0 0 0.4rem rgba(0,
z-index: 1; // sits above the name label
}
.sea-stack-ok {
.sea-stack-flip {
position: absolute;
top: 50%;
left: 0;
@@ -2064,9 +2064,9 @@ $_sea-card-glow: 0 0 0.5rem 0.5rem rgba(var(--ninUser), 0.3), 0 0 0.4rem rgba(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; }
.sea-deck-stack:hover .sea-stack-flip,
.sea-deck-stack:focus-within .sea-stack-flip,
.sea-deck-stack--active .sea-stack-flip { 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
@@ -2074,7 +2074,7 @@ $_sea-card-glow: 0 0 0.5rem 0.5rem rgba(var(--ninUser), 0.3), 0 0 0.4rem rgba(0,
// 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--active .sea-stack-flip:not(.btn-disabled) { pointer-events: auto; }
.sea-deck-stack { gap: 0; } // remove gap so name slides under the face

View File

@@ -954,7 +954,7 @@ body.page-gameboard {
transform-origin: center;
}
// FLIP reveal (hover-fade + click-persist) is now the SHARED `.sea-stack-ok`
// FLIP reveal (hover-fade + click-persist) is now the SHARED `.sea-stack-flip`
// 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

View File

@@ -10,13 +10,13 @@
<span class="sea-stacks-label">DECKS</span>
<div class="sea-deck-stack sea-deck-stack--gravity">
<div class="sea-stack-face">
<button class="btn btn-reveal sea-stack-ok{% if flip_disabled %} btn-disabled{% endif %}" type="button">{% if flip_disabled %}&times;{% else %}FLIP{% endif %}</button>
<button class="btn btn-reveal sea-stack-flip{% if flip_disabled %} btn-disabled{% endif %}" type="button">{% if flip_disabled %}&times;{% else %}FLIP{% endif %}</button>
</div>
<span class="sea-stack-name">Gravity</span>
</div>
<div class="sea-deck-stack sea-deck-stack--levity">
<div class="sea-stack-face">
<button class="btn btn-reveal sea-stack-ok{% if flip_disabled %} btn-disabled{% endif %}" type="button">{% if flip_disabled %}&times;{% else %}FLIP{% endif %}</button>
<button class="btn btn-reveal sea-stack-flip{% if flip_disabled %} btn-disabled{% endif %}" type="button">{% if flip_disabled %}&times;{% else %}FLIP{% endif %}</button>
</div>
<span class="sea-stack-name">Levity</span>
</div>
@@ -29,7 +29,7 @@
{% if deck.has_card_images %}
<img class="sea-stack-face-img" src="{{ deck.back_image_url }}" alt="">
{% endif %}
<button class="btn btn-reveal sea-stack-ok{% if flip_disabled %} btn-disabled{% endif %}" type="button">{% if flip_disabled %}&times;{% else %}FLIP{% endif %}</button>
<button class="btn btn-reveal sea-stack-flip{% if flip_disabled %} btn-disabled{% endif %}" type="button">{% if flip_disabled %}&times;{% else %}FLIP{% endif %}</button>
</div>
</div>
</div>

View File

@@ -131,13 +131,13 @@ via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
<span class="sea-stacks-label">DECKS</span>
<div class="sea-deck-stack sea-deck-stack--gravity">
<div class="sea-stack-face">
<button class="btn btn-reveal sea-stack-ok{% if hand_complete %} btn-disabled{% endif %}" type="button">{% if hand_complete %}&times;{% else %}FLIP{% endif %}</button>
<button class="btn btn-reveal sea-stack-flip{% if hand_complete %} btn-disabled{% endif %}" type="button">{% if hand_complete %}&times;{% else %}FLIP{% endif %}</button>
</div>
<span class="sea-stack-name">Gravity</span>
</div>
<div class="sea-deck-stack sea-deck-stack--levity">
<div class="sea-stack-face">
<button class="btn btn-reveal sea-stack-ok{% if hand_complete %} btn-disabled{% endif %}" type="button">{% if hand_complete %}&times;{% else %}FLIP{% endif %}</button>
<button class="btn btn-reveal sea-stack-flip{% if hand_complete %} btn-disabled{% endif %}" type="button">{% if hand_complete %}&times;{% else %}FLIP{% endif %}</button>
</div>
<span class="sea-stack-name">Levity</span>
</div>
@@ -261,7 +261,7 @@ via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
}
function _setComplete(on, live) {
_locked = on;
overlay.querySelectorAll('.sea-deck-stack .sea-stack-ok').forEach(function (btn) {
overlay.querySelectorAll('.sea-deck-stack .sea-stack-flip').forEach(function (btn) {
btn.classList.toggle('btn-disabled', on);
btn.innerHTML = on ? '×' : 'FLIP';
});
@@ -340,7 +340,7 @@ via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
e.stopPropagation();
if (_activeStack === stack) _hideOk(); else _showOk(stack);
});
var ok = stack.querySelector('.sea-stack-ok');
var ok = stack.querySelector('.sea-stack-flip');
if (ok) {
ok.addEventListener('click', function (e) {
e.stopPropagation();

View File

@@ -439,7 +439,7 @@
// draw, NOT at completion).
_locked = on;
picker.classList.toggle('my-sea-picker--locked', on);
picker.querySelectorAll('.sea-deck-stack .sea-stack-ok').forEach(function (btn) {
picker.querySelectorAll('.sea-deck-stack .sea-stack-flip').forEach(function (btn) {
btn.classList.toggle('btn-disabled', on);
// Mirrors DEL btn convention: disabled label is × (the
// template's initial render does the same), active is
@@ -477,7 +477,7 @@
if (_activeStack === stack) _hideOk();
else _showOk(stack);
});
var ok = stack.querySelector('.sea-stack-ok');
var ok = stack.querySelector('.sea-stack-flip');
if (ok) {
ok.addEventListener('click', function (e) {
e.stopPropagation();