.is-cue-source {
  z-index: 9;
}

.is-cue-source:not(.hand-card),
.hand-card.is-cue-source .hand-card-visual {
  animation: source-action 0.7s ease-in-out;
}

.is-cue-target {
  z-index: 8;
}

.is-cue-target:not(.hand-card),
.hand-card.is-cue-target .hand-card-visual {
  animation: target-pulse 0.7s ease-in-out;
}

/* Setup means two things: the battle beginning, and a player choosing an Oche. Only the first
   stirs the Decks, and the actor is what tells them apart - nobody acts on the battle beginning. */
.cue-setup.cue-actor-none .deck-card-back {
  animation: shuffle 0.65s ease-in-out;
}

/*
  ---- The table's motion language ------------------------------------------------------------

  Journeys are timed LINEARLY and eased by waypoint spacing instead: a curve is applied between
  each pair of keyframes, so a curve over a multi-waypoint path stops the card at every one.
  Waypoints sit at p = u^2 / (u^2 + (1-u)^2). A pop or a fade has no path and keeps its own curve.

  --cue-pace scales a run to match the shortened beat it plays inside; the page sets both from one
  number, so shortening either alone would cut the other off. Only the riffle and the deal use it.

  Cross-table distances come from matchPresentation.js as custom properties - they depend on where
  the two ends land at this screen size, which no stylesheet can know.
*/
.shuffle-riffle {
  position: absolute;
  z-index: 3;
  inset: 0;
  pointer-events: none;

  /* Less room outside the Deck than the piles need, so the stack opens inward. The gap between
     the piles is unchanged, so the shuffle keeps its shape. */
  @media (max-width: 1180px) {
    --riffle-split-left: 24%;
    --riffle-split-right: 94%;
  }

  /* The phone Deck has least room, so the stack opens almost entirely into the table. */
  @media (max-width: 720px) {
    --riffle-split-left: 10%;
    --riffle-split-right: 108%;
  }
}

/* Seen from directly above, so a card crossing the far pile says its height by growing and
   casting further - there is no edge-on view of a Deck from up here. */
.riffle-card {
  position: absolute;
  inset: 0;
  display: block;
}

/* The split is a share of the card's own width, so it keeps its shape at every size. The stagger
   is what makes the cards cross back one at a time rather than as two halves. */
.cue-shuffle .riffle-card {
  animation-duration: calc(0.5s * var(--cue-pace, 1));
  animation-timing-function: linear;
  animation-delay: calc(var(--riffle-order, 0) * 0.031s * var(--cue-pace, 1));
  animation-fill-mode: both;
}

.cue-shuffle .riffle-card.is-left {
  animation-name: riffle-left;
}

.cue-shuffle .riffle-card.is-right {
  animation-name: riffle-right;
}

/* While the stack is in pieces the pieces ARE the stack - the back underneath would show
   through the gap they open. */
.deck-stack.is-riffling {
  z-index: 8;
}

.deck-stack.is-riffling > .deck-card-back > .oche-card-back {
  opacity: 0;
}

/* Squared up once the last card is home, by the Deck that shuffled and not the other one. */
.cue-shuffle.cue-actor-local .player-zone .deck-card-back,
.cue-shuffle.cue-actor-opponent .opponent-zone .deck-card-back {
  animation: deck-square-up calc(0.3s * var(--cue-pace, 1)) linear
    calc(0.86s * var(--cue-pace, 1));
}

/* A draw arcs off the Deck and turns over at the top of the arc; the opponent's never turns. */
.cue-draw .hand-card.is-cue-target {
  z-index: 30;
}

.cue-draw .hand-card.is-cue-target .hand-card-visual {
  animation: draw-arc calc(0.86s * var(--cue-pace, 1)) linear;
}

.cue-draw .opponent-hand .oche-card-back.is-drawn {
  position: relative;
  z-index: 4;
  animation: draw-arc-face-down calc(0.86s * var(--cue-pace, 1)) linear;
}

/* The fan opens over the back half of the journey so the two read as one movement. The :hover
   exclusion is what keeps a card being pressed answering at once. */
.cue-draw .hand-card:not(.is-cue-target):not(:hover) {
  transition-delay: calc(0.34s * var(--cue-pace, 1));
}

/* The face is covered until the card is edge on, and gone before there is any of it to see. */
.draw-cover {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: block;
  animation: draw-cover-lift calc(0.86s * var(--cue-pace, 1)) linear both;
}

.draw-cover .oche-card-back,
.riffle-card .oche-card-back {
  width: 100%;
  height: 100%;
}

.cue-draw.cue-actor-local .player-zone .deck-card-back,
.cue-draw.cue-actor-opponent .opponent-zone .deck-card-back {
  animation: deck-press calc(0.86s * var(--cue-pace, 1)) linear;
}

/* All three kinds are one gesture - a card leaving a hand for a place on the table. A card with
   nowhere to land has no travelling mark and keeps the plain presentation. */
.cue-play .hand-card.is-cue-source .hand-card-visual,
.cue-evolve .hand-card.is-cue-source .hand-card-visual,
.cue-setup .hand-card.is-cue-source .hand-card-visual {
  animation: hand-play 0.52s linear both;
}

/*
  ---- One card, one place --------------------------------------------------------------------

  Keyed on the presentation's own state, NOT on the cue that carried the card off: a cue-scoped
  rule stops applying at the next cue, which put the card back in the hand it had already left.
*/
.battle-card-shell.is-cue-gone,
.hand-card.is-cue-gone .hand-card-visual {
  opacity: 0;
  pointer-events: none;
}

/* The press surface is around the card, not the card, so hiding the card leaves a full-size
   target holding nothing. It cannot leave the layout instead - it is still playing its exit. */
.hand-card.is-cue-gone,
.card-press:has(.battle-card-shell.is-cue-gone) {
  pointer-events: none;
}

.card-travel {
  display: block;
}

.card-play-overlay.is-travelling .card-travel {
  animation: play-travel 1s linear both;
}

.card-play-overlay.is-travelling strong {
  animation: play-name-out 1s ease-out both;
}

.is-cue-landing {
  animation: slot-land 1s linear both;
}

/*
  One movement across several cues, so the mark is the presentation's rather than any one cue's.
  --blow-lead holds the wind-up back by however long the table spends between declaration and
  damage, so the blow lands on the frame the number changes on. Unmeasured, the card turns where
  it stands. Placed after the plain source and target rules deliberately: this wins for both ends.
*/
.battle-card-shell.is-cue-striking {
  z-index: 9;
  animation: attack-lunge 1.4s linear var(--blow-lead, 0ms) both;
}

/* Aimed from the declaration, but knocked back only when the damage is actually on it. */
.cue-damage .battle-card-shell.is-cue-struck {
  z-index: 8;
  animation: attack-recoil 0.84s linear both;
}

.cue-damage .is-cue-target .damage-badge,
.cue-heal .is-cue-target .damage-badge {
  animation: counter-pop 0.55s ease-out;
}

.cue-knockout .is-cue-target {
  animation: knockout 0.85s ease-in both;
}

/* Taking a Prize, which until now has been the one card journey on the table with no movement at
   all: this named an <i> inside the rack, and the rack has only ever been card backs, so the rule
   has never matched anything in the product's history.

   It goes to the half that took it, because a Prize is taken by whoever knocked something over and
   comes out of their own rack - unscoped it would empty a card from both racks at once, which is
   the defect the Deck rule at the top of this file was corrected for.

   The last card goes rather than the first. The rack is a grid that loses its last cell when the
   count drops, so leaving from the end is the only choice that leaves every card staying behind
   where it already was. */
.cue-prize.cue-actor-local .player-zone .prizes .oche-card-back:last-child,
.cue-prize.cue-actor-opponent .opponent-zone .prizes .oche-card-back:last-child {
  animation: prize-take 0.6s ease-out both;
}

