/* Mana-Ausgabe (render/effect-header.js): die ausgegebenen Punkte leuchten kurz hell
   auf und laufen leer, darueber steigt ein kleines "-n" auf. Ein Durchlauf, kein Loop.
   Auffuellen siehe unten (.is-gained). */
.effectManaPip.is-spent {
  animation: effectManaSpend .9s cubic-bezier(.3, .6, .3, 1) both;
}
@keyframes effectManaSpend {
  0%   { background: linear-gradient(180deg, #7ff4e9, #43c7bd); box-shadow: 0 0 6px rgba(77, 208, 196, .54); transform: scaleY(1); }
  18%  { background: #eafffd; box-shadow: 0 0 12px 2px rgba(160, 255, 245, .9); transform: scaleY(1.9); }
  100% { background: rgba(77, 208, 196, .13); box-shadow: 0 0 0 rgba(77, 208, 196, 0); transform: scaleY(1); }
}
.effectManaBar { position: relative; }
.effectManaSpendDelta {
  position: absolute;
  bottom: 100%;
  margin-bottom: 2px;
  font-size: 11px;
  font-weight: 700;
  color: #9ff7ee;
  text-shadow: 0 0 6px rgba(77, 208, 196, .85);
  pointer-events: none;
  white-space: nowrap;
  animation: effectManaDelta .9s ease-out both;
}
@keyframes effectManaDelta {
  0%   { opacity: 0; transform: translate(-50%, 4px); }
  20%  { opacity: 1; transform: translate(-50%, 0); }
  100% { opacity: 0; transform: translate(-50%, -8px); }
}
/* Auffuellen: neu gefuellte Punkte gluehen einmal hell auf und setzen sich.
   Hoehere Spezifitaet als der Dauerpuls bei voller Leiste (main-07). */
.effectManaRow .effectManaBar .effectManaPip.is-full.is-gained {
  animation: effectManaGain .9s cubic-bezier(.3, .6, .3, 1) both;
}
@keyframes effectManaGain {
  0%   { opacity: .2; filter: brightness(1); box-shadow: 0 0 0 rgba(77, 208, 196, 0); transform: scaleY(1); }
  30%  { opacity: 1; filter: brightness(1.9); box-shadow: 0 0 12px 2px rgba(160, 255, 245, .85); transform: scaleY(1.9); }
  100% { opacity: 1; filter: brightness(1); box-shadow: 0 0 6px rgba(77, 208, 196, .54); transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
  .effectManaPip.is-spent,
  .effectManaRow .effectManaBar .effectManaPip.is-full.is-gained { animation: none; }
  .effectManaSpendDelta { display: none; }
}

/* Kristall der Mana-Figuren (render/crystal-state.js): reicht das Mana nicht mehr fuer
   die Faehigkeit, wird der Kristall farblos, reicht es wieder, faerbt er sich. Ueber dem
   neuen Bild liegt kurz das alte und wird weich weggewischt. Die Bilder unterscheiden
   sich nur im Kristall, also wandert sichtbar nur dessen Farbe: beim Leeren sinkt sie
   nach unten weg, beim Aufladen steigt sie von unten auf. */
#board .chip .pieceAsset.crystalFrom {
  position: absolute;
  inset: -6%;               /* deckungsgleich mit dem Bild darunter (112 %, mittig) */
  filter: none;             /* Schatten liefert das Bild darunter, sonst doppelt */
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 300%;
  mask-size: 100% 300%;
  pointer-events: none;
}
#board .chip .pieceAsset.crystalFrom-drain {
  -webkit-mask-image: linear-gradient(to bottom, transparent 42%, #000 58%);
  mask-image: linear-gradient(to bottom, transparent 42%, #000 58%);
  animation: mpCrystalDrain 1.2s cubic-bezier(.45, .05, .4, 1) both;
  animation-delay: calc(150ms + var(--mp-t, 0ms));
}
#board .chip .pieceAsset.crystalFrom-charge {
  -webkit-mask-image: linear-gradient(to top, transparent 42%, #000 58%);
  mask-image: linear-gradient(to top, transparent 42%, #000 58%);
  animation: mpCrystalCharge 1.1s cubic-bezier(.45, .05, .4, 1) both;
  animation-delay: calc(250ms + var(--mp-t, 0ms));
}
/* Bereit-Signal am Ende des Aufladens (render/crystal-flare.js): nur der Kristall
   (Maske = Unterschied der beiden Bilder) leuchtet einmal hell auf, an seiner
   staerksten Stelle blitzt ein kleiner Glanzstern. */
#board .chip .crystalFlare {
  position: absolute;
  inset: -6%;
  width: 112%;
  height: 112%;
  object-fit: contain;
  pointer-events: none;
  -webkit-mask-size: contain;  /* wie object-fit: das Feld ist nicht immer quadratisch */
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  mix-blend-mode: plus-lighter;
  animation: mpCrystalFlare 1s ease-out both;
  animation-delay: calc(1150ms + var(--mp-t, 0ms));
}
@keyframes mpCrystalFlare {
  0%   { opacity: 0; }
  25%  { opacity: 1; }
  45%  { opacity: .85; }
  100% { opacity: 0; }
}
#board .chip .crystalGlint {
  position: absolute;
  width: 44%;
  aspect-ratio: 1;
  translate: -50% -50%;
  pointer-events: none;
  background: radial-gradient(circle, #fff 0 7%, rgba(255, 255, 255, .5) 12%, transparent 22%);
  animation: mpCrystalGlint .85s cubic-bezier(.2, .7, .3, 1) both;
  animation-delay: calc(1250ms + var(--mp-t, 0ms));
}
#board .chip .crystalGlint::before,
#board .chip .crystalGlint::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(closest-side, #fff, rgba(255, 255, 255, .55) 45%, transparent);
}
#board .chip .crystalGlint::before { inset: 46% 0; }
#board .chip .crystalGlint::after  { inset: 0 46%; }
@keyframes mpCrystalGlint {
  0%   { opacity: 0; scale: .2; rotate: 0deg; }
  35%  { opacity: 1; scale: 1;  rotate: 30deg; }
  100% { opacity: 0; scale: .5; rotate: 75deg; }
}
@keyframes mpCrystalDrain {
  from { -webkit-mask-position: 0 100%; mask-position: 0 100%; }
  to   { -webkit-mask-position: 0 0;    mask-position: 0 0; }
}
@keyframes mpCrystalCharge {
  from { -webkit-mask-position: 0 0;    mask-position: 0 0; }
  to   { -webkit-mask-position: 0 100%; mask-position: 0 100%; }
}
/* Koenigsfiguren mit Kristall (Lich, Kapitaen, Koenig; render/crystal-flare.js): eine
   Kopie des Kristalls (gleiche Maske wie beim Aufleuchten) liegt deckend auf dem Bild
   und atmet in der Helligkeit, etwas dunkler als gemalt bis deutlich heller, ohne Schein
   um die Figur. Takt an der Wanduhr, alle Koenige gleich (data-anim-period). */
#board .chip .crystalPulse {
  position: absolute;
  inset: -6%;
  width: 112%;
  height: 112%;
  object-fit: contain;
  pointer-events: none;
  -webkit-mask-size: contain;  /* wie object-fit: das Feld ist nicht immer quadratisch */
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  animation: mpCrystalPulse 4.8s ease-in-out infinite;
  animation-delay: var(--mp-t, 0ms);
}
@keyframes mpCrystalPulse {
  0%, 100% { filter: brightness(.8); }
  50%      { filter: brightness(2) saturate(1.15); }
}
/* Treten die anderen Figuren zurueck (Zielwahl), ruht auch der Kristall; unter
   fremdem Verfall pulsiert er so fahl wie die Figur. */
#board:has(.sq.pickCandidate) .sq:not(.pickCandidate) .crystalPulse,
#board:has(.sq.actionTarget) .sq:not(.actionTarget):not(.actionActor) .crystalPulse { visibility: hidden; }
#board .chip.auraTouched-debuff .crystalPulse { animation-name: mpCrystalPulseDebuff; }
@keyframes mpCrystalPulseDebuff {
  0%, 100% { filter: brightness(.64) saturate(.55); }
  50%      { filter: brightness(1.6) saturate(.6); }
}
/* Im Schach pulsiert der Kristall rot, im Takt des roten Schach-Rings (2,4 s,
   main-06 kingCheckBreath); schachmatt bleibt er tiefrot und atmet nur noch schwer.
   Gleiche Ebene, nur umgefaerbt. */
#board .sq.kingInCheck .chip .crystalPulse {
  animation-name: mpCrystalCheck;
  animation-duration: 2.4s;
}
#board .sq.kingMated .chip .crystalPulse {
  animation-name: mpCrystalMate;
  animation-duration: 4.8s;
}
@keyframes mpCrystalCheck {
  0%, 100% { filter: grayscale(1) sepia(1) saturate(9) hue-rotate(-40deg) brightness(.8); }
  50%      { filter: grayscale(1) sepia(1) saturate(9) hue-rotate(-40deg) brightness(1.4); }
}
@keyframes mpCrystalMate {
  0%, 100% { filter: grayscale(1) sepia(1) saturate(9) hue-rotate(-42deg) brightness(.5); }
  50%      { filter: grayscale(1) sepia(1) saturate(9) hue-rotate(-42deg) brightness(.72); }
}

/* Kopien der Figur ausserhalb des Bretts (Geister der Effekt-Ebene, z. B. bei der
   Wiederbelebung) zeigen nur das aktuelle Bild. Ohne die Brett-Regeln oben stuenden
   altes und neues Bild dort sonst nebeneinander. */
.chip .crystalFrom,
.chip .crystalFlare,
.chip .crystalGlint,
.chip .crystalPulse { display: none; }
#board .chip .crystalFrom,
#board .chip .crystalFlare,
#board .chip .crystalGlint,
#board .chip .crystalPulse { display: block; }
@media (prefers-reduced-motion: reduce) {
  #board .chip .pieceAsset.crystalFrom,
  #board .chip .crystalFlare,
  #board .chip .crystalGlint,
  #board .chip .crystalPulse { display: none; }
}
