/* Turn hand-off.
 *
 * Both reference games make this the loudest beat in a match — Hearthstone lays a
 * plate and a sunburst across the middle of the table and you cannot miss whose turn
 * it is. Modern announced a hand-off with a 12px line and three dots tucked under the
 * action button, which is effectively invisible on a 430px-tall phone in landscape.
 *
 * Two rules this layer must never break:
 *   - pointer-events stays none, so a drag begun before the hand-off survives it.
 *   - nothing here reflows the board; the layer is fixed and composited on its own.
 *
 * CSP forbids inline styles, so the duration multiplier arrives as a custom property
 * set through style.setProperty() rather than as an inline animation shorthand.
 */

.turnbanner {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 110;            /* over the stage and target arrows, under dialogs */
  pointer-events: none;
  --tb: 1;                 /* duration multiplier: 1 normal, .45 in fast mode */
  --tb-hue: var(--gold-bright);
}

.turnbanner[data-side="opp"] { --tb-hue: var(--opp); }

.turnbanner__burst {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(150vw, 1400px);
  height: min(46vh, 260px);
  transform: translate(-50%, -50%);
  background: radial-gradient(
    ellipse at center,
    color-mix(in srgb, var(--tb-hue) 34%, transparent) 0%,
    color-mix(in srgb, var(--tb-hue) 10%, transparent) 38%,
    transparent 70%
  );
  animation: tb-burst calc(1600ms * var(--tb)) var(--ease-lift) forwards;
}

/* The scrim is what makes this legible over ANY battlefield. The painted scenes run
   from near-black void gates to hot magenta groves, so glow alone is not enough
   separation for gold type — both reference games put a solid plate behind the words
   for exactly this reason. Kept short and edge-faded so it darkens a band, not the
   board. */
.turnbanner__band::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 100vw;
  height: clamp(54px, 17vh, 94px);
  z-index: -1;
  background: linear-gradient(
    to right,
    transparent,
    #000000bf 18%,
    #000000d9 50%,
    #000000bf 82%,
    transparent
  );
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--tb-hue) 30%, transparent),
    inset 0 -1px 0 color-mix(in srgb, var(--tb-hue) 30%, transparent);
}

.turnbanner__band {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(10px, 2.4vw, 26px);
  padding: 0 clamp(12px, 3vw, 34px);
  animation: tb-band calc(1600ms * var(--tb)) var(--ease-lift) forwards;
}

/* The rules are what make a line of text read as a plate rather than as a caption. */
.turnbanner__rule {
  display: block;
  width: clamp(48px, 16vw, 240px);
  height: 1px;
  background: linear-gradient(
    to var(--tb-dir, right),
    transparent,
    color-mix(in srgb, var(--tb-hue) 85%, transparent)
  );
  box-shadow: 0 0 10px color-mix(in srgb, var(--tb-hue) 45%, transparent);
}

.turnbanner__rule:first-child { --tb-dir: right; }
.turnbanner__rule:last-child  { --tb-dir: left; }

.turnbanner__text {
  font: 400 clamp(20px, 4.4vw, 44px) / 1 var(--display);
  letter-spacing: clamp(3px, 1vw, 10px);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--tb-hue);
  text-shadow:
    0 0 18px color-mix(in srgb, var(--tb-hue) 55%, transparent),
    0 3px 14px #000c;
  animation: tb-text calc(1600ms * var(--tb)) var(--ease-pop) forwards;
}

@keyframes tb-burst {
  0%   { opacity: 0; transform: translate(-50%, -50%) scaleY(.4); }
  14%  { opacity: 1; transform: translate(-50%, -50%) scaleY(1); }
  62%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scaleY(.9); }
}

/* Wiping the band open from the centre reads as the table handing over, where a
   plain fade reads as a notification arriving. */
@keyframes tb-band {
  0%   { opacity: 0; transform: scaleX(.55); }
  16%  { opacity: 1; transform: scaleX(1); }
  66%  { opacity: 1; transform: scaleX(1); }
  100% { opacity: 0; transform: scaleX(1.06); }
}

@keyframes tb-text {
  0%   { opacity: 0; transform: scale(.9) translateY(6px); }
  18%  { opacity: 1; transform: scale(1) translateY(0); }
  66%  { opacity: 1; transform: scale(1) translateY(0); }
  100% { opacity: 0; transform: scale(1.02) translateY(-8px); }
}

/* Reduced motion still gets the announcement — it is information, not decoration —
   but it arrives and leaves on opacity alone. */
.turnbanner[data-motion="reduced"] .turnbanner__burst,
.turnbanner[data-motion="reduced"] .turnbanner__band,
.turnbanner[data-motion="reduced"] .turnbanner__text {
  animation: tb-fade calc(900ms * var(--tb)) linear forwards;
}

@keyframes tb-fade {
  0%, 100% { opacity: 0; }
  12%, 74% { opacity: 1; }
}
