.card-animation-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 20;
    overflow: visible;
}

.card-animation-ghost {
    position: absolute;
    pointer-events: none;
    transform: translate3d(0, 0, 0);
    backface-visibility: hidden;
}

/* Applied to source cards in the south hand the moment their ghost
   flight starts, so the real card is hidden while the ghost flies to
   the table. Most plays are cleaned up automatically when Blazor's
   re-render removes the source .card from the DOM. When a played card
   shares its rank/suit with a kept card in the same column (e.g. 3 of 4
   sevens played from a double deck), Blazor reuses the surviving DOM
   positionally and the unchanged class string skips the diff write —
   the JS-added class lingers. cardAnimations.sweepStuckFlyAway is
   called after the post-play re-render to strip those leftovers. */
.card.card-flying-away {
    transition: opacity 220ms ease;
    opacity: 0;
    pointer-events: none;
}

/* Brief table shake when a bomb lands. cardAnimations.bomb() applies
   this keyframe via inline style.animation (not a class) so Blazor's
   class-attribute diff on .game-table can't wipe it mid-shake when the
   human's bomb empties their hand and ShowPartnerHand flips. The
   reduced-motion guard lives in JS — bomb() and playFromPartnerHand()
   both early-return before applying the shake. The shake transform
   stacks on top of the table's normal layout (which uses
   `position: fixed; inset: 0; margin: auto;` — neither relies on
   transform), so this never disturbs centering. */
@keyframes bomb-shake {
    0%, 100% { transform: translate(0, 0); }
    10%      { transform: translate(-7px, 4px); }
    20%      { transform: translate(6px, -3px); }
    30%      { transform: translate(-5px, -5px); }
    40%      { transform: translate(7px, 3px); }
    50%      { transform: translate(-4px, 4px); }
    60%      { transform: translate(5px, -2px); }
    70%      { transform: translate(-3px, 3px); }
    80%      { transform: translate(3px, -1px); }
    90%      { transform: translate(-1px, 1px); }
}

