diff --git a/src/apps/dashboard/tests/integrated/test_views.py b/src/apps/dashboard/tests/integrated/test_views.py index f6e1583..bcf305b 100644 --- a/src/apps/dashboard/tests/integrated/test_views.py +++ b/src/apps/dashboard/tests/integrated/test_views.py @@ -517,6 +517,34 @@ class KitBagViewTest(TestCase): "fa-regular fa-id-badge must be gone from kit-bag-deck", ) + def test_no_deck_equipped_renders_placeholder_card_stack_icon(self): + """Sprint A.4 follow-up — when the user has no equipped_deck, the + kit-bag Deck section renders the same .deck-stack-icon SVG inside a + .kit-bag-placeholder wrapper (no fan-out trigger; CSS dims it to + --quaUser at 0.3 alpha to match the empty dice slot).""" + import lxml.html + # Clear the auto-equipped Earthman to land in the placeholder branch. + self.user.equipped_deck = None + self.user.save(update_fields=["equipped_deck"]) + response = self.client.get(self.url) + parsed = lxml.html.fromstring(response.content) + # equipped-deck branch is skipped → placeholder branch fires. + self.assertEqual( + len(parsed.cssselect(".kit-bag-deck")), 0, + "No equipped deck → no .kit-bag-deck wrapper", + ) + placeholders = parsed.cssselect(".kit-bag-section .kit-bag-placeholder") + # First placeholder is the Deck slot (Dice + Trinket slots also use + # .kit-bag-placeholder when empty); assert at least one carries the + # card-stack SVG. + deck_placeholder = placeholders[0] + [_] = deck_placeholder.cssselect("svg.deck-stack-icon") + # Old fa-id-badge must be gone. + self.assertEqual( + len(deck_placeholder.cssselect("i.fa-id-badge")), 0, + "fa-regular fa-id-badge must be gone from kit-bag-placeholder", + ) + def test_polarized_equipped_deck_tooltip_has_x2_decoration(self): """Same (x2) decoration as the gameboard applet — polarized decks signal segment-doubling in the tooltip card-count line via --terUser diff --git a/src/static_src/scss/_gameboard.scss b/src/static_src/scss/_gameboard.scss index e8d9334..cba5742 100644 --- a/src/static_src/scss/_gameboard.scss +++ b/src/static_src/scss/_gameboard.scss @@ -123,16 +123,14 @@ body.page-gameboard { .deck-stack-icon__card--3 { transform: translateY( 0.4px); } } -// Sprint A.4 — fan-out trigger lives at the icon level (not nested in -// #id_applet_game_kit) so the same `.deck-stack-icon` works wherever it's -// dropped: gameboard's .token.deck-variant, kit-bag dialog's .kit-bag-deck, -// future room.html pile + deck-bag. Hover/active/focus on the icon itself -// OR any of its known wrappers triggers the splay; cards 2 + 3 fan out from -// under card 1, card 1 stays put. Tooltip portal is wired to the same -// `.token:hover` / `.kit-bag-deck:hover` triggers via JS so the splay + -// tooltip-appearance co-activate. -.deck-stack-icon:hover, -.deck-stack-icon:active, +// Sprint A.4 — fan-out trigger is wrapper-only (NOT self-triggered on the +// SVG itself) so placeholder-mode icons inside .kit-bag-placeholder stay +// static + dim like the empty dice slot. Real-deck wrappers (.token.deck- +// variant on gameboard, .kit-bag-deck in kit-bag dialog, future room.html +// pile + deck-bag) drive the splay; cards 2 + 3 fan out from under card 1, +// card 1 stays put. Tooltip portal is wired to the same `.token:hover` / +// `.kit-bag-deck:hover` triggers via JS so splay + tooltip-appearance +// co-activate. .token.deck-variant:hover .deck-stack-icon, .token.deck-variant:active .deck-stack-icon, .token.deck-variant:focus .deck-stack-icon, @@ -143,6 +141,18 @@ body.page-gameboard { .deck-stack-icon__card--3 { transform: translate( 5px, -2px) rotate( 12deg); } } +// Sprint A.4 — placeholder-mode dim styling. When the icon is inside a +// .kit-bag-placeholder (no deck equipped) or game_kit applet's empty-state +// .kit-item (no decks unlocked), color + fill drop to `--quaUser` at 0.3 +// alpha to match the existing empty-slot treatment (`.kit-bag-placeholder` +// at `_game-kit.scss:143`, `.kit-item { opacity: 0.6 }` here). No animation +// since the wrapper isn't in the splay-trigger list above. +.kit-bag-placeholder .deck-stack-icon, +.kit-item .deck-stack-icon { + color: rgba(var(--quaUser), 0.15); + .deck-stack-icon__card { fill: rgba(var(--quiUser), 0.15); } +} + #id_applet_new_game { display: flex; flex-direction: column;