/*
 * Spell Announce overlay — floats full card faces (enemy spell casts, reveals)
 * center-screen for a few seconds so the player can read them.
 *
 * Layering: above the enlarged in-place card (9500, game-board.css), below
 * game-end / consent overlays (9999).
 */

#spell-announce-overlay {
  position: fixed;
  inset: 0;
  z-index: 9600;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  background: transparent;
  opacity: 0;
  transition: opacity 0.35s ease;
}

#spell-announce-overlay.visible {
  opacity: 1;
}

#spell-announce-overlay.visible::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center,
      rgba(8, 6, 24, 0.55) 0%,
      rgba(8, 6, 24, 0.35) 45%,
      rgba(8, 6, 24, 0.05) 75%,
      transparent 100%);
}

.spell-announce-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.6vmin;
  pointer-events: auto;
  cursor: pointer;
}

.spell-announce-label {
  font-size: 2.6vmin;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #ffe9b0;
  text-shadow:
    0 0 12px rgba(255, 196, 87, 0.65),
    0 2px 6px rgba(0, 0, 0, 0.9);
  animation: spell-announce-label-in 0.55s cubic-bezier(0.22, 1.18, 0.32, 1) both;
}

.spell-announce-cards {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2vmin;
  /* Capture the ambient unit for the wrap below to multiply. A custom property
     cannot reference itself, so the capture happens one level up — and going
     through the unit is what keeps the :root phone floor and the 4K
     counter-scale reaching this surface instead of being re-derived here. */
  --spell-announce-base-unit: var(--card-unit);
}

/* Physically enlarged card faces — popup-preview category, like
   #card-hover-preview (allowed per card-rendering rules).

   The enlargement scales --card-unit, never --card-width alone: every internal
   of a card (title, description, cost, status overlay) is derived from the
   unit, so re-declaring only the frame stretches the border while leaving the
   contents at ambient scale. At the previous literal 24.6vmin over a 1vmin
   unit the frame was exactly 2x with 1x text inside it. */
.spell-announce-card-wrap {
  /* The floor matters more here than anywhere else. This is the surface whose
     entire job is "look at this card", and it was the only enlarged card
     surface without one: measured on a 932x300 landscape page box the reveal
     came out 93px wide, barely above a hand card and well under the 159px the
     storyboard's equivalent card gets from its own floor. The art rasters
     correctly at 3x either way, so the card did not look low-res because of
     resolution — it looked low-res because it was small. */
  /* Floored, but never past the page box: a phone's box is the height the
     browser actually hands the document, and the reveal carries a caption
     above the cards, so the floor yields to whatever 22.2 units can occupy of
     the visible height minus that chrome. */
  /* Captured separately so the GROWN face below can multiply it — a custom
     property cannot reference itself across the inheritance boundary. */
  --spell-announce-slot-unit: max(
    calc(var(--spell-announce-base-unit, 1vmin) * 2),
    min(12.97px, calc((100dvh - 44px) / 22.2))
  );
  --card-unit: var(--spell-announce-slot-unit);
  --card-width: calc(12.29 * var(--card-unit));
  --card-height: calc(22.2 * var(--card-unit));
  /* Fixed dimensions let the child enlarge without moving this layout slot or
     neighboring revealed cards. Flex centering keeps a zoom-enlarged child
     (whose LAYOUT box grows, unlike a transform) centered in the slot. */
  width: var(--card-width);
  height: var(--card-height);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
  /* Fade-only entrance: transform motion on this ancestor would change the
     coordinate system underneath the center-anchored hover zoom. */
  animation: spell-announce-card-in 0.5s cubic-bezier(0.2, 0.9, 0.25, 1.2) backwards;
  /* Depth WITHOUT a filter: an ancestor filter renders the whole revealed
     card through an intermediate surface, which softens its text and art at
     every size — "revealing enemy cards is still lowres/blurry" was this
     wrapper's drop-shadows. Box shadows paint behind the face at zero
     compositing cost; both blurs are diffuse enough that the rectangular box
     behind the frame art reads the same. (Same opt-out as game-board.css and
     mulligan.css.) */
  box-shadow: 0 1.2vmin 3vmin rgba(0, 0, 0, 0.65),
    0 0 2.4vmin rgba(148, 128, 255, 0.3);
}

/* Descendant hover keeps the wrapper hovered even while the transformed face
   extends beyond its resting bounds. */
.spell-announce-card-wrap:hover {
  z-index: 5;
  box-shadow: none;
}

.spell-announce-cardface {
  transform-origin: center center;
  /* Hover enlargement is applied by spell-announce.js through the shared
     UI.Cards.applyHoverTransform engine (crisp zoom on zoom engines); a CSS
     transform:scale() here would stretch the resting rasterization. */
  /* The wrap IS the card slot, sized to exactly --card-width/--card-height.
     cards.css gives every .card a horizontal margin (2.64 card-units per
     side); inside this flex slot that margin overflowed the slot, default
     flex-shrink absorbed the overflow out of the CARD's own width (margins
     never shrink), and the card's overflow:hidden cropped ~17px off each
     side of the revealed face — a narrow strip with the title truncated.
     The face must fill its slot edge to edge, unshrinkable. */
  margin: 0;
  flex-shrink: 0;
}

/* THE SETTLED HOVER IS LAYOUT, NOT A TRANSFORM. The 1.6x hover used to stay a
   transform:scale for its whole life, which stretches the layer's rest-sized
   raster — the frame filigree and text arrived 1.6x-upsampled, the residue of
   "revealing enemy cards is still imperfect… probably sharper, but not quite
   perfect". The transform now only ANIMATES the growth; once it settles,
   spell-announce.js swaps to this class: the unit itself grows (the sanctioned
   enlargement per docs/card-rendering-regression-contract.md), the card
   re-lays-out at its displayed size, the art re-rasters 1:1, and the frame and
   text paint at native resolution. The wrap's fixed slot + flex centering keep
   the grown card centred; transitions are suppressed so the same-size swap is
   invisible, while CardTilt's per-frame rotation vars continue untouched. */
.spell-announce-cardface.spell-announce-grown {
  --card-unit: calc(var(--spell-announce-slot-unit) * var(--spell-announce-hover-scale, 1.6));
  --card-width: calc(12.29 * var(--card-unit));
  --card-height: calc(22.2 * var(--card-unit));
  transition: none;
  z-index: 5;
}

/* Compact is "three or more cards to show", not "small screen" — so it needs
   its own floor for exactly the same reason, held at the same 1.35/2 ratio to
   the full reveal so it still reads as the denser layout. Measured on a 932x300
   box it was rendering 54px cards while leaving ~700px of width unused. The
   width term keeps four of them on one row. */
.spell-announce-compact .spell-announce-card-wrap {
  /* Same slot-unit capture as the full layout, so the grown face's multiplier
     works identically in compact reveals. */
  --spell-announce-slot-unit: max(
    calc(var(--spell-announce-base-unit, 1vmin) * 1.35),
    min(
      8.75px,
      calc((100dvh - 44px) / 22.2),
      calc((100vw - 40px) / 4 / 12.29)
    )
  );
  --card-unit: var(--spell-announce-slot-unit);
}

/* The floating face receives pointer events for hover enlargement (its
   transformed box is the hover hit area). Clicks bubble to the stage, which
   dismisses — the card itself triggers no gameplay actions here because it
   lives outside the hand/board containers the drag/play systems query. */

@keyframes spell-announce-card-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* Spring-settled drop-in (the easing above supplies the soft overshoot). */
@keyframes spell-announce-label-in {
  from {
    opacity: 0;
    transform: translateY(-1.8vmin) scale(0.96);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Persistent reveal marker: a storyteller-revealed card sitting face-up in
   the opponent's hand glows softly so it reads as "exposed knowledge".
   z-index above the fan's card backs (nth-child stack tops out at 10 in
   game-board.css): the face-up card is the one worth pointing at, and the
   overlapping neighbors were stealing ~20% of its hover hitbox. */
#opponent-hand .card.revealed-in-hand {
  box-shadow:
    0 0 0.9vmin rgba(255, 214, 112, 0.85),
    0 0 2.2vmin rgba(255, 196, 87, 0.45);
  border-radius: inherit;
  z-index: 11;
}

@media (prefers-reduced-motion: reduce) {

  .spell-announce-card-wrap,
  .spell-announce-label {
    animation: none;
  }

  #spell-announce-overlay {
    transition: opacity 0.1s linear;
  }
}
