/*
 * Effekt-Ebene — gilt in beiden Looks.
 *
 * Fast alles hier wird ueber Custom Properties gesteuert, die der Game-Loop
 * pro Frame setzt (fx.js). Keyframes koennen nur feste Kurven; die Staerke
 * eines Screenshakes soll aber am Ergebnis haengen, und ein Ueberschuss soll
 * abbrechbar sein, wenn die Runde vorzeitig endet. Deshalb rechnet der Loop
 * und CSS zeichnet nur.
 */

/* Konfetti-Leinwand ueber allem, faengt keine Klicks ab */
.fx-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 200;
}

/* Der Blasen-Anker. .compare selbst geht nicht, das hat overflow:hidden. */
.quiz-header { position: relative; }

/* ---------------------------------------------------------------- Wackeln
 * Zwei Variablengruppen auf demselben Element: --shake-* kommt vom Loop,
 * --sx/--sy vom Stauchen. Beide muessen sich addieren, ohne sich gegenseitig
 * zu ueberschreiben, deshalb eine gemeinsame transform-Kette mit Defaults.
 *
 * Die Klasse wird nur waehrend der Animation gesetzt und danach wieder
 * entfernt. Ein dauerhaftes transform zwingt iOS Safari, das Element auf eine
 * eigene Compositing-Ebene zu legen; unter dieser Ebene schlug der helle
 * Seiten-Canvas durch den dunklen Arcade-Verlauf durch — ein breiter heller
 * Streifen hinter Statuszeile und Zielflaeche. Ausserdem kostet eine
 * dauerhafte Ebene Speicher und macht Text auf manchen Geraeten unscharf.
 */
.fx-anim {
  transform:
    translate3d(var(--shake-x, 0), var(--shake-y, 0), 0)
    rotate(var(--shake-r, 0deg))
    scale(var(--sx, 1), var(--sy, 1));
}

/* --------------------------------------------------------- Treffer am Ziel
 * Ring als box-shadow auf .compare selbst, nicht auf einem Kind: .compare hat
 * overflow:hidden und wuerde ihn wegschneiden.
 */
.compare.hit-good { animation: ring-good 520ms cubic-bezier(0.22, 1, 0.36, 1); }
.compare.hit-ok   { animation: ring-ok   520ms cubic-bezier(0.22, 1, 0.36, 1); }
.compare.hit-bad  { animation: ring-bad  460ms ease-out; }

@keyframes ring-good {
  0%   { box-shadow: 0 0 0 0 rgba(40, 200, 110, 0.9); }
  100% { box-shadow: 0 0 0 26px rgba(40, 200, 110, 0); }
}
@keyframes ring-ok {
  0%   { box-shadow: 0 0 0 0 rgba(230, 170, 0, 0.85); }
  100% { box-shadow: 0 0 0 20px rgba(230, 170, 0, 0); }
}
@keyframes ring-bad {
  0%   { box-shadow: 0 0 0 0 rgba(200, 50, 40, 0.55); }
  100% { box-shadow: 0 0 0 12px rgba(200, 50, 40, 0); }
}

/* Neues Ziel poppt herein; --enter laeuft mit Overshoot von 0 nach 1. */
.compare { --enter: 1; }
.compare > .compare-half.target {
  opacity: calc(0.35 + 0.65 * var(--enter));
}

/* Die eigene Mischung schiebt sich als zweite Haelfte herein. */
.compare-half.mix {
  position: absolute;
  inset: 0 0 0 auto;
  width: calc(50% * var(--reveal, 0));
  opacity: var(--reveal, 0);
  overflow: hidden;
}
.compare:not(.revealed) .compare-half.mix { display: none; }

/* --------------------------------------------------------- Fliegende Punkte
 * Die wichtigste Zahl im Spiel loest sich vom Ort der Handlung und fliegt in
 * den Zaehler. --pop kommt mit hartem Ueberschuss, --rise/--drift langsam.
 */
.fx-pop {
  position: fixed;
  z-index: 210;
  pointer-events: none;
  transform:
    translate(-50%, -50%)
    translate(var(--drift, 0px), var(--rise, 0px))
    scale(var(--pop, 0));
  font-family: var(--pop-font, ui-monospace, "SF Mono", Menlo, monospace);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #1a1a1a;
  white-space: nowrap;
  will-change: transform, opacity;
}
.fx-pop-good { color: #1a8f4a; }
.fx-pop-ok   { color: #b47600; }
.fx-pop-bad  { color: #999; }
.fx-pop-big  { font-size: 44px; }
.fx-pop-combo {
  font-size: 22px;
  color: #ff2d92;
  -webkit-text-stroke: 2px #fff;
  paint-order: stroke fill;
}
.fx-pop-time {
  font-size: 20px;
  color: #1a8f4a;
}

/* ------------------------------------------------------------ Sprechblasen
 * Zackenrand per Rahmen und Schlagschatten, keine Bilddatei und keine
 * Comic-Webschrift — die waere im Klassik-Look der erste Stilbruch.
 * --in kommt elastisch von 0, --out schiebt sie am Ende nach oben weg.
 */
/* Tiefer als die Mitte: dort steigen die fliegenden Punkte auf, und zwei
   Dinge uebereinander sind schlechter lesbar als eines allein. */
.bubble {
  position: absolute;
  left: 50%;
  top: 80%;
  z-index: 60;
  pointer-events: none;
  transform:
    translate(-50%, -50%)
    translateY(calc(-55px * var(--out, 0)))
    rotate(-3deg)
    scale(var(--in, 0));
  background: #fff;
  color: #111;
  border: 2.5px solid #111;
  box-shadow: 4px 4px 0 #111;
  padding: 0.55rem 1.1rem;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}
.bubble-perfect { background: #ffe94d; font-size: 21px; }
.bubble-good    { background: #d8f5c8; }
.bubble-ok      { background: #fff; }
.bubble-bad     { background: #f2f2f2; color: #444; }
.bubble-streak  { background: #111; color: #ffe94d; border-color: #111; box-shadow: 4px 4px 0 #ffe94d; }
.bubble-timeout { background: #ffd2cc; }

/* --------------------------------------------------- Serie, Combo, Leben */
.mini-status .ms-streak {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  font-weight: 600;
  color: #c85000;
  opacity: 0;
  transition: opacity 160ms ease;
}
.mini-status .ms-streak.on { opacity: 1; }
.mini-status .ms-streak.hot { animation: streak-pulse 1.1s ease-in-out infinite; }
@keyframes streak-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }

.mini-status .ms-combo {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13px;
  font-weight: 800;
  color: #ff2d92;
  opacity: 0;
}
.mini-status .ms-combo.on { opacity: 1; }
.mini-status .ms-combo.tier-4,
.mini-status .ms-combo.tier-5 { color: #e00060; }

.mini-status .ms-lives {
  font-size: 13px;
  letter-spacing: 0.08em;
  color: #d0304a;
}
.mini-status .ms-lives[hidden] { display: none; }
.mini-status .ms-lives.low { animation: lives-warn 900ms ease-in-out infinite; }
@keyframes lives-warn { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

/* ------------------------------------------------------ Bewegung reduzieren
 * Alles Dekorative aus, jede Information bleibt lesbar. Die fliegenden Punkte
 * bleiben — sie sind Information, nur ohne Ueberschuss und kuerzer.
 */
@media (prefers-reduced-motion: reduce) {
  .compare.hit-good,
  .compare.hit-ok,
  .compare.hit-bad { animation: none; }
  .mini-status .ms-streak.hot,
  .mini-status .ms-lives.low { animation: none; }
  .bubble { transform: translate(-50%, -50%) rotate(-3deg) scale(var(--in, 1)); }
}
