A.5-polish-2 FLIP-to-back bug fixes — TDD. Two user-reported bugs from the first FLIP-to-back commit (1963ad4): (1) FLIPping made the entire card disappear instead of showing the back; (2) the FLIP btn stayed visible during the animation when it should hide just like the tarot-fan view's flip btn does. Root cause of (1): the back-image element was rendered with inline style="display:none" in the template. Inline styles beat CSS class rules in the cascade — my .sig-stage-card.is-flipped-to-back .sig-stage-card-back-img { display: block } rule was the right specificity but couldn't override an inline style attribute. So the toggle hid the front (CSS-controlled, no inline override) but failed to show the back (CSS blocked by inline). Net: empty stage. Fix: removed the inline style on the back-img element; default .sig-stage-card-back-img { display: none } rule (already present in SCSS) handles the hidden default, and the .is-flipped-to-back toggle now flips visibility cleanly. Both rules are pure-CSS so they cascade as expected. Root cause of (2): the non-polarized FLIP handler was a bare class toggle (no animation, no data-flipping attr), so there was no SCSS hook to hide the btn. Plus there was no equivalent SCSS rule even for the polarized _flipPolarityAnimated flow which DID set data-flipping — the polarized flip just animated without hiding the btn either. Fix: (a) added _flipToBackAnimated() JS function mirroring _flipPolarityAnimated's shape — rotateY 0→90→0 at 500ms ease, swap visual content at the halfway point (here: class toggle instead of revInput/polarity flip), set stageCard.dataset.flipping = '1' for the duration so SCSS has a hook. (b) New SCSS rule .my-sign-stage:has(.sig-stage-card[data-flipping]) .my-sign-flip-btn { opacity: 0; pointer-events: none } mirrors the tarot-fan view's pattern (_card-deck.scss:459 — .tarot-fan-wrap:has(.fan-card[data-flipping]) .fan-flip-btn). The :has() selector covers BOTH the polarized animation (which already sets data-flipping) AND the new non-polarized animation, so the btn hide-during-flip behavior now lands consistently across both flip modes — fixes a latent polished-flow gap not just the new code path. No new tests — the existing 3 ITs from 1963ad4 already verify the template/scaffold contract (data-deck-polarized attr + back-img element conditional render); the bug fixes here are CSS/JS-level behavior best caught by visual verify (no automated test would have caught the inline-style cascade issue since the IT asserted on element presence, not display state). 1303/1303 IT+UT total green (71s, unchanged from 1963ad4 since no new tests in this commit)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -887,6 +887,18 @@ html:has(.sig-backdrop) {
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint A.5 — hide FLIP btn during the flip animation. `data-flipping="1"`
|
||||||
|
// is set on .sig-stage-card by _flipPolarityAnimated (polarized) AND
|
||||||
|
// _flipToBackAnimated (non-polarized) for the 500ms animation duration; CSS
|
||||||
|
// :has() selects the parent .my-sign-stage when any child carries that attr
|
||||||
|
// and zeros the btn so it doesn't visually interfere w. the rotateY mid-spin.
|
||||||
|
// Mirrors the tarot-fan view's pattern (`_card-deck.scss:459` —
|
||||||
|
// `.tarot-fan-wrap:has(.fan-card[data-flipping]) .fan-flip-btn`).
|
||||||
|
.my-sign-stage:has(.sig-stage-card[data-flipping]) .my-sign-flip-btn {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Mini card grid ───────────────────────────────────────────────────────────
|
// ─── Mini card grid ───────────────────────────────────────────────────────────
|
||||||
// flex: 0 0 auto — shrinks to card content; no background (backdrop blur).
|
// flex: 0 0 auto — shrinks to card content; no background (backdrop blur).
|
||||||
// align-content: start prevents CSS grid from distributing extra height between rows.
|
// align-content: start prevents CSS grid from distributing extra height between rows.
|
||||||
|
|||||||
@@ -42,9 +42,11 @@
|
|||||||
{# non-polarized decks). Pre-rendered back-image element; CSS #}
|
{# non-polarized decks). Pre-rendered back-image element; CSS #}
|
||||||
{# toggles visibility via `.sig-stage-card.is-flipped-to-back`. #}
|
{# toggles visibility via `.sig-stage-card.is-flipped-to-back`. #}
|
||||||
{% if request.user.equipped_deck.has_card_images and not request.user.equipped_deck.is_polarized %}
|
{% if request.user.equipped_deck.has_card_images and not request.user.equipped_deck.is_polarized %}
|
||||||
|
{# No inline style — `.sig-stage-card-back-img` defaults to #}
|
||||||
|
{# `display: none` via SCSS; `.sig-stage-card.is-flipped-to-back` #}
|
||||||
|
{# overrides to `display: block`. Inline would beat the toggle. #}
|
||||||
<img class="sig-stage-card-back-img" alt=""
|
<img class="sig-stage-card-back-img" alt=""
|
||||||
src="{{ request.user.equipped_deck.back_image_url }}"
|
src="{{ request.user.equipped_deck.back_image_url }}">
|
||||||
style="display:none">
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="fan-card-corner fan-card-corner--tl">
|
<div class="fan-card-corner fan-card-corner--tl">
|
||||||
<span class="fan-corner-rank"></span>
|
<span class="fan-corner-rank"></span>
|
||||||
@@ -359,20 +361,38 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flipBtn) {
|
// Sprint A.5 — non-polarized FLIP animation. Mirrors the polarized
|
||||||
flipBtn.addEventListener('click', function () {
|
// `_flipPolarityAnimated` shape (rotateY-90 mid-spin + dataset.flipping
|
||||||
if (!_currentCard) return;
|
// for the duration so SCSS can hide the btn) but swaps a class
|
||||||
// Sprint A.5 — non-polarized decks (Minchiate, RWS): FLIP
|
// toggle for the polarity revInput-flip at the halfway point.
|
||||||
// shows the deck card-back instead of cycling polarity (no
|
function _flipToBackAnimated() {
|
||||||
// gravity/levity to toggle on these decks). Stat block stays
|
if (!stageCard || stageCard.dataset.flipping) return;
|
||||||
// unchanged — user spec 2026-05-25 PM. Polarized decks
|
stageCard.dataset.flipping = '1';
|
||||||
// (Earthman) keep the existing polarity-flip animation.
|
var rest = 'translateX(0px) rotateY(0deg) scale(1)';
|
||||||
if (pageEl.dataset.deckPolarized === 'false') {
|
var mid = 'translateX(0px) rotateY(90deg) scale(1)';
|
||||||
|
stageCard.animate([
|
||||||
|
{ transform: rest },
|
||||||
|
{ transform: mid, offset: 0.5 },
|
||||||
|
{ transform: rest },
|
||||||
|
], { duration: 500, easing: 'ease' });
|
||||||
|
setTimeout(function () {
|
||||||
stageCard.classList.toggle('is-flipped-to-back');
|
stageCard.classList.toggle('is-flipped-to-back');
|
||||||
if (flipBtn) flipBtn.classList.toggle(
|
if (flipBtn) flipBtn.classList.toggle(
|
||||||
'is-reversed',
|
'is-reversed',
|
||||||
stageCard.classList.contains('is-flipped-to-back')
|
stageCard.classList.contains('is-flipped-to-back')
|
||||||
);
|
);
|
||||||
|
}, 250);
|
||||||
|
setTimeout(function () { delete stageCard.dataset.flipping; }, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flipBtn) {
|
||||||
|
flipBtn.addEventListener('click', function () {
|
||||||
|
if (!_currentCard) return;
|
||||||
|
// Non-polarized decks (Minchiate, RWS): FLIP shows the deck
|
||||||
|
// card-back; stat block stays unchanged — user spec 2026-05-25 PM.
|
||||||
|
// Polarized decks (Earthman) keep the existing polarity cycle.
|
||||||
|
if (pageEl.dataset.deckPolarized === 'false') {
|
||||||
|
_flipToBackAnimated();
|
||||||
} else {
|
} else {
|
||||||
_flipPolarityAnimated();
|
_flipPolarityAnimated();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user