/* ===== Event effects (catch / death / badge) =====
 * All effect elements live in #fx (a sibling of #canvas inside the scaled
 * 1920x1080 stage) and are positioned in design coordinates. Only transform,
 * opacity and filter are animated — compositor-friendly, so the effects stay
 * cheap even when the OBS browser source runs without GPU acceleration.
 */

#fx {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
#fx > * { position: absolute; }

#fx-particles {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
}

/* while a slot is animated, its real content is hidden (layout unchanged) */
.team-slot.fx-hidden img { visibility: hidden; }

/* --- catch --- */
.fx-ball svg { width: 100%; height: 100%; }
.fx-ball { transform-origin: 50% 90%; filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.45)); }
/* opening: the halves fly apart */
.fx-ball .ball-top, .fx-ball .ball-bottom, .fx-ball .ball-band,
.fx-ball .ball-button, .fx-ball .ball-button-inner {
  transition: transform 0.35s ease-out, opacity 0.35s ease-out;
}
.fx-ball.open .ball-top { transform: translateY(-30px) rotate(-14deg); }
.fx-ball.open .ball-bottom { transform: translateY(14px); }
.fx-ball.open .ball-band,
.fx-ball.open .ball-button,
.fx-ball.open .ball-button-inner { opacity: 0; }

.fx-mon {
  object-fit: contain;
  filter: drop-shadow(0 3px 10px rgba(0, 0, 0, 0.5));
}
.fx-mon.shiny { animation: fx-shiny-pulse 0.9s ease-in-out infinite alternate; }
@keyframes fx-shiny-pulse {
  from { filter: drop-shadow(0 0 4px rgba(255, 230, 120, 0.7)); }
  to   { filter: drop-shadow(0 0 14px rgba(255, 230, 120, 1)); }
}

.fx-flash {
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0) 65%);
}

/* --- death --- */
.fx-dead, .fx-ghost {
  object-fit: contain;
}
.fx-ghost { filter: grayscale(1) brightness(1.6) blur(1px); }
.fx-tomb svg { width: 100%; height: 100%; }
.fx-tomb { filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.5)); }

/* --- leader transition (levelcap header) --- */
/* clip container: leaders never spill past the header (hard bottom edge) */
.fx-leader-clip {
  overflow: hidden;
  pointer-events: none;
}
.fx-leader-clip > * { position: absolute; }
.fx-leader {
  object-fit: contain;
  object-position: center bottom;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.5));
}
/* the cap number travels with the leader — styled like .cap-values */
.fx-cap {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--overlay-font, system-ui, sans-serif);
  font-size: 36px;
  font-weight: 800;
  letter-spacing: 1px;
  line-height: 1;
  color: var(--accent);
  white-space: nowrap;
}
/* while the transition plays, the header's real leader image (and, when the
   cap changed, the real number) are covered; the fx copies play on top */
.header-box.fx-leader-lock .leader-img { visibility: hidden; }
.header-box.fx-cap-lock .cap-values { visibility: hidden; }

/* --- Top-4 member checkpoints (stage panel in the badges slot) --- */
/* fx clones of not-yet-beaten trainers arrive gray, like the panel icons */
.fx-leader.fx-locked { filter: grayscale(1) brightness(0.45); opacity: 0.55; }
/* fourth win / champion beaten: the whole panel content is covered while the
   clones animate on top (squad out, champion in / champion finale) */
.header-box.fx-panel-lock .member-icon,
.header-box.fx-panel-lock .champ-img,
.header-box.fx-panel-lock .stage-panel-tag,
.header-box.fx-panel-lock .badge-row { visibility: hidden; }

/* --- badge --- */
.fx-badge {
  object-fit: contain;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.55));
}
.fx-badge.glow { animation: fx-badge-glow 0.7s ease-in-out infinite alternate; }
@keyframes fx-badge-glow {
  from { filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.55)); }
  to   { filter: drop-shadow(0 0 18px rgba(255, 255, 255, 0.95)); }
}
