A.4 card-deck stack icon + game_kit applet's Card Decks polarization (×2) tooltip decoration — TDD. Sprint A.4 of [[project-image-based-deck-face-rendering]] (folded down from the originally-standalone Sprint D per [[project-card-deck-icon]] 2026-05-25 PM scope-fold). Replaces the <i class="fa-regular fa-id-badge"> placeholder on .token.deck-variant in the gameboard's Game Kit applet w. a new inline SVG card-stack icon: 3 rect children (rx=2.5, 20×32 viewport units inside a 32×48 viewBox to land 5:8 tarot card aspect), stacked tightly at rest w. ±0.4px vertical micro-offsets (suggests stack depth without separating cards visually), whole stack rotated 5° clockwise via .deck-stack-icon__stack group transform. On :hover / :active / :focus of the parent .token.deck-variant, cards 2 + 3 fan out symmetrically — card 2 translates (-5px, -2px) + rotates -12°, card 3 translates (+5px, -2px) + rotates +12° — card 1 stays put on top. Fan-out CSS pseudo-classes match the existing JS-portal tooltip trigger so the splay animation + tooltip-appearance co-activate as user spec'd. Placeholder card-back design: solid --priUser fill + currentColor stroke (= --terUser); detailed Earthman planet-impact illustration deferred to a future art-asset commit (the SVG structure is ready to receive richer fills + pattern elements without re-jigging the stack/fan transforms). Drop-shadow for "lifted off the felt" depth cue: 0.08rem 0.08rem 0.15rem rgba(0, 0, 0, 0.6) — softer than the my-sign-stage card's tray-card-style 1,1 black silhouette since the icon is small + always on a felt background. SVG itself uses overflow: visible so the fan-out exceeds the viewBox bounds; transform-box: fill-box + transform-origin: 50% 50% ensure rotation centers on each card's own geometric center (not the viewBox center). New _deck_stack_icon.html partial in templates/apps/gameboard/_partials/ keeps the SVG markup DRY for the future room.html pile + deck-bag rollouts (per [[project-card-deck-icon]] "other surfaces deferred to later sprints"). New .tt-x2 style in %tt-token-fields placeholder mixin — --terUser color + font-weight 600 — appended inline in .tt-description for is_polarized=True decks (Earthman today): "106-card Tarot deck (×2)" where the (×2) signals "double-polarized = 6 segments = fills 2× as many seats" per [[project-card-deck-icon]]'s decoration rule. Non-polarized decks (Tarot RWS, future Minchiate) render the description without the suffix. 3 new ITs in GameboardViewTest: SVG card-stack renders w. 3 rect children + fa-id-badge gone; polarized Earthman tooltip carries .tt-x2 w. "×2" content; non-polarized RWS tooltip lacks .tt-x2. Out of scope this commit: the dedicated /game-kit/ page's .gk-deck-card rectangles (different template — _game_kit_sections.html) keep their fa-id-badge for now; folding them into the new icon happens in a follow-up "Card Decks rectangle teardown" sprint per user spec ("by the time we finish A.8 the dynamically shaped rectangles around the deck <i> els and their names will be no more"). Tests: 3 new ITs green; 27/27 GameboardViewTest class green; 1293/1293 IT+UT total green (68s; +3 from A.3-polish's 1290). Visual verify pending: browser refresh expected to show the stacked-3-card icon w. 5° rest tilt, fan-out on hover, tooltip + (×2) decoration on Earthman

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-05-25 00:40:10 -04:00
parent 436a710478
commit b9bb73db69
5 changed files with 123 additions and 3 deletions

View File

@@ -413,6 +413,52 @@ class GameboardViewTest(TestCase):
def test_game_kit_has_dice_set_placeholder(self):
[_] = self.parsed.cssselect("#id_game_kit #id_kit_dice_set")
def test_deck_token_renders_card_stack_svg_not_fa_id_badge(self):
"""Sprint A.4 — `.token.deck-variant` icon is the inline SVG card-stack
(`.deck-stack-icon`), not the old `<i class="fa-regular fa-id-badge">`
placeholder. Stack contains 3 rect children w. `.deck-stack-icon__card`
classes the CSS keys off for the rest-stack + hover fan-out."""
deck = self.parsed.cssselect("#id_game_kit #id_kit_earthman_deck")[0]
# New SVG icon present
[svg] = deck.cssselect("svg.deck-stack-icon")
cards = svg.cssselect(".deck-stack-icon__card")
self.assertEqual(
len(cards), 3,
"Card-stack icon must render 3 rect cards (top + 2 fan-out)",
)
# Old FA icon removed
self.assertEqual(
len(deck.cssselect("i.fa-id-badge")), 0,
"fa-regular fa-id-badge must be gone from deck-variant token",
)
def test_polarized_deck_tooltip_has_x2_decoration(self):
"""Earthman is the only is_polarized=True deck today (per A.0 migration).
Its tooltip's card-count line should carry a `(×2)` suffix in --terUser
per [[project-card-deck-icon]]'s `is_polarized` tooltip-decoration rule."""
deck = self.parsed.cssselect("#id_game_kit #id_kit_earthman_deck")[0]
tt = deck.cssselect(".tt")[0]
[x2] = tt.cssselect(".tt-x2")
self.assertIn("×2", x2.text_content()) # ×2
def test_nonpolarized_deck_tooltip_lacks_x2_decoration(self):
"""Non-polarized decks (Tarot RWS, future Minchiate) don't get the
`(×2)` decoration — the suffix signals 'double-polarized = 6 segments
= fills 2× as many seats' which only applies to polarized decks."""
from apps.epic.models import DeckVariant
# Use the migration-renamed RWS deck (formerly fiorentine-minchiate).
rws = DeckVariant.objects.get(slug="tarot-rider-waite-smith")
self.user.unlocked_decks.add(rws)
response = self.client.get("/gameboard/")
import lxml.html
parsed = lxml.html.fromstring(response.content)
deck = parsed.cssselect("#id_game_kit #id_kit_tarot_deck")[0]
tt = deck.cssselect(".tt")[0]
self.assertEqual(
len(tt.cssselect(".tt-x2")), 0,
"Non-polarized RWS deck must not show (×2) in tooltip",
)
class GameboardDeckInUseTest(TestCase):
"""Sprint 2: game kit applet renders in-use state for a deck assigned to an active seat."""