A.4 cont.: deck back-image renders inside card-stack icon + kit-bag dialog Deck section adopts the icon + size+pattern polish — TDD. Three follow-up improvements after user browser-verified A.4's first cut: (1) image-equipped decks (Minchiate today, future Earthman) now render the deck's actual <deck-slug>-back.png as the card-stack icon's visible faces instead of the placeholder --priUser solid fill — feels like a real deck, not a generic stand-in. (2) The kit-bag dialog Deck section (#id_kit_bag_dialog .kit-bag-deck) gets the same new card-stack icon (was still showing the old fa-regular fa-id-badge), with (×2) tooltip decoration on polarized decks for consistency w. the gameboard applet. (3) Visual polish: icon bumped 1.5× (1.5rem → 2.25rem width; 2.4rem → 3.6rem height, 5:8 aspect preserved); SVG <pattern> switched from patternUnits=userSpaceOnUse (which painted the image at fixed user-space coordinates and let the rect slide out from under it on hover, reading as "low opacity" to the user) to patternUnits=objectBoundingBox + patternContentUnits=objectBoundingBox (transform-aware — image tracks the rect through rest-state offsets + hover fan-out). New DeckVariant.back_image_url property mirrors A.2's TarotCard.image_url pattern: returns full static-asset URL for <deck-slug>-back.png when has_card_images=True, else empty string. Template partial _deck_stack_icon.html extended w. conditional <defs><pattern> block that renders only when deck.has_card_images is true; each of the 3 card rects then carries an inline style="fill: url(#deck-back-<short_key>)" overriding the SCSS default fill: rgba(--priUser, 1) (inline style beats CSS, the only way to opt out of the cascade default per-element). When no deck is passed (kit-bag placeholder branch) or deck has no images (Earthman + RWS), the partial falls through to the placeholder fill — single template handles both modes. _kit_bag_panel.html Deck section: equipped-deck branch swaps <i class="fa-regular fa-id-badge"> for {% include _deck_stack_icon.html with deck=equipped_deck %} + adds (×2) span in --terUser for equipped_deck.is_polarized; placeholder branch swaps for the same include without deck= so the partial's conditional falls through. SCSS reorg: lifted the .deck-stack-icon base rules out of the #id_applet_game_kit nest (they were scoped to gameboard's Game Kit applet only) into top-level scope so the same SCSS applies in the kit-bag dialog context too. Hover/active/focus trigger selector list broadened to cover .deck-stack-icon itself + .token.deck-variant wrapper + .kit-bag-deck wrapper. 4 new ITs total: 2 in GameboardViewTest (image-equipped Minchiate's <pattern> defines + inline fill style on all 3 rects + asset URL ref; non-image Earthman has NEITHER pattern nor inline fill); 2 in dashboard.KitBagViewTest (kit-bag Deck section renders svg.deck-stack-icon + lacks fa-id-badge; polarized equipped deck tooltip carries .tt-x2 — element-presence assertion since literal "×2" character had encoding issues in the dashboard test file vs the gameboard one, which is fine since the template-side rendering of the literal × is exercised by the parent template). Tests: 4 new green; 1297/1297 IT+UT total green (69s; +4 from A.4's 1293). Visual verify pending: refresh /gameboard/ → Minchiate icon should show 3 stacked Minchiate card-backs at 1.5× size, fan out on hover w. back image tracking; refresh kit-bag dialog → same icon visible in Deck section w. (×2) on Earthman tooltip
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,54 +79,70 @@ body.page-gameboard {
|
||||
.kit-item { font-size: 1.5rem; }
|
||||
|
||||
.kit-item { opacity: 0.6; }
|
||||
|
||||
// Sprint A.4 — card-deck stack icon (.deck-stack-icon) replaces the
|
||||
// fa-regular fa-id-badge for .token.deck-variant. 3 stacked card-back
|
||||
// rects, 5° CW rest tilt, fan-out on hover/active/focus of the parent
|
||||
// .token (animation + tooltip portal trigger lockstep on the same
|
||||
// pseudo-class set). See [[project-card-deck-icon]].
|
||||
.deck-stack-icon {
|
||||
display: inline-block;
|
||||
width: 1.5rem; // match the prior fa-id-badge visual weight
|
||||
height: 2.4rem; // 5:8 tarot card aspect
|
||||
color: rgba(var(--terUser), 1); // stroke color via currentColor
|
||||
overflow: visible; // fan-out exceeds the viewBox bounds
|
||||
filter: drop-shadow(0.08rem 0.08rem 0.15rem rgba(0, 0, 0, 0.6));
|
||||
|
||||
.deck-stack-icon__stack {
|
||||
transform: rotate(5deg);
|
||||
transform-origin: 50% 50%;
|
||||
transform-box: fill-box;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.deck-stack-icon__card {
|
||||
fill: rgba(var(--priUser), 1);
|
||||
stroke: currentColor;
|
||||
stroke-width: 1;
|
||||
transform-origin: 50% 50%;
|
||||
transform-box: fill-box;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
// Rest: tightly stacked w. tiny vertical offsets (suggests stack
|
||||
// depth without separating the cards visually).
|
||||
.deck-stack-icon__card--1 { transform: translateY(-0.4px); }
|
||||
.deck-stack-icon__card--3 { transform: translateY( 0.4px); }
|
||||
}
|
||||
|
||||
// Hover/active/focus on the parent .token fans cards 2 + 3 out from
|
||||
// under card 1; card 1 stays put. Tooltip portal is wired to the
|
||||
// same `.token:hover` trigger via JS so the 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 {
|
||||
.deck-stack-icon__card--2 { transform: translate(-5px, -2px) rotate(-12deg); }
|
||||
.deck-stack-icon__card--3 { transform: translate( 5px, -2px) rotate( 12deg); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sprint A.4 — card-deck stack icon (.deck-stack-icon) replaces the
|
||||
// fa-regular fa-id-badge wherever a deck appears in icon form: gameboard's
|
||||
// .token.deck-variant, kit-bag dialog's .kit-bag-deck, future room.html pile
|
||||
// + deck-bag. Lifted out of the #id_applet_game_kit nest so the base sizing
|
||||
// + rest-state SCSS applies in any deck-icon context. 3 stacked card-back
|
||||
// rects, 5° CW rest tilt; see [[project-card-deck-icon]] for the design rules.
|
||||
// When the deck has card-images, the rect fills are overridden inline w. an
|
||||
// SVG <pattern> referencing the deck's <deck-slug>-back.png; otherwise the
|
||||
// placeholder `fill: rgba(--priUser, 1)` shows through.
|
||||
.deck-stack-icon {
|
||||
display: inline-block;
|
||||
// 2026-05-25 PM user spec: 1.5× the prior fa-id-badge visual weight
|
||||
// since the icon is no longer constrained to placeholder-icon dimensions
|
||||
// (now a meaningful first-class deck visualization).
|
||||
width: 2.25rem; // 1.5rem × 1.5
|
||||
height: 3.6rem; // 1.5× while preserving 5:8 tarot card aspect
|
||||
color: rgba(var(--terUser), 1); // stroke color via currentColor
|
||||
overflow: visible; // fan-out exceeds the viewBox bounds
|
||||
filter: drop-shadow(0.08rem 0.08rem 0.15rem rgba(0, 0, 0, 0.6));
|
||||
|
||||
.deck-stack-icon__stack {
|
||||
transform: rotate(5deg);
|
||||
transform-origin: 50% 50%;
|
||||
transform-box: fill-box;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.deck-stack-icon__card {
|
||||
fill: rgba(var(--priUser), 1);
|
||||
stroke: currentColor;
|
||||
stroke-width: 1;
|
||||
transform-origin: 50% 50%;
|
||||
transform-box: fill-box;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
// Rest: tightly stacked w. tiny vertical offsets (suggests stack
|
||||
// depth without separating the cards visually).
|
||||
.deck-stack-icon__card--1 { transform: translateY(-0.4px); }
|
||||
.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,
|
||||
.token.deck-variant:hover .deck-stack-icon,
|
||||
.token.deck-variant:active .deck-stack-icon,
|
||||
.token.deck-variant:focus .deck-stack-icon,
|
||||
.kit-bag-deck:hover .deck-stack-icon,
|
||||
.kit-bag-deck:active .deck-stack-icon,
|
||||
.kit-bag-deck:focus .deck-stack-icon {
|
||||
.deck-stack-icon__card--2 { transform: translate(-5px, -2px) rotate(-12deg); }
|
||||
.deck-stack-icon__card--3 { transform: translate( 5px, -2px) rotate( 12deg); }
|
||||
}
|
||||
|
||||
#id_applet_new_game {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user