/*
 * Pubquiz Bühnenmomente E6 (frontend/js/quizStage/moments/*, stageFx.js, personFigure.js).
 * Spec: docs/superpowers/specs/2026-10-16-avatar-e6-buehnenmomente-design.md
 * Aufbau: ein Abschnitt je Baustein, jeder mit eigenem Kommentarkopf; die Tasks 3 bis 7 ergänzen nur ihren Abschnitt (kein Eingriff in
 * die anderen, damit Zusammenführungen sauber bleiben). Animiert wird nur `transform` und `opacity`.
 */

/* ==========================================================================================================================
 * Basis (Task 1): Figur statt Kopf (solo, bust), Personenkarte mit Figur, Lichtkegel, Geschwindigkeitsstriche, Polaroid
 * ======================================================================================================================== */

/* Figur ohne Schild und Podest: Breite 23 × --pq-k wie überall (components-pubquiz-stage.css, .pq-figure), Größe über --pq-k des Umfelds. */
.pq-figure--solo,
.pq-figure--bust {
  position: relative;
  flex: none;
}
/* Brustbild: schneidet bei den Hüften ab (Saum bei 15,4 k von 22,8 k Figurhöhe, die Beine liegen unten im Körper-SVG); der Rand oben und
   seitlich bleibt offen für Blase und Effekte. */
.pq-figure--bust {
  margin-bottom: calc(-7 * var(--pq-k));
  clip-path: inset(calc(-10 * var(--pq-k)) calc(-8 * var(--pq-k)) calc(7 * var(--pq-k)) calc(-8 * var(--pq-k)));
}

/* Personenkarte (Schnellste Person, Ausgeschieden, Siegerfolie): die Figur ersetzt den runden Kopf-Ausschnitt. */
.person-card .person-photo.has-figure {
  display: flex;
  justify-content: center;
  width: auto;
  max-width: 100%;
  height: auto;
  border-radius: 0;
  overflow: visible;
  background: none;
  outline: none;
}
.person-card .pq-figure {
  --pq-k: 4.4px;
}
.qe-people-fastest .person-card .pq-figure {
  --pq-k: 7.2px;
}
.qe-finale-winners .person-card .pq-figure {
  --pq-k: 7.8px;
}

/* Lichtkegel: Hintergrund-Ebene im (positionierten) Host, nur `opacity` ändert sich (stageFx.js, spotlight). */
.pq-spotlight {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse 48% 62% at 50% 38%, rgba(255, 244, 200, 0.6) 0%, rgba(255, 244, 200, 0.26) 42%, rgba(255, 244, 200, 0) 72%);
}

/* Geschwindigkeitsstriche: links im (positionierten) Host, bis zum Spielen unsichtbar (stageFx.js, speedLines). */
.pq-speedlines {
  position: absolute;
  inset: 0 auto 0 0;
  width: 60%;
  z-index: 0;
  pointer-events: none;
}
.pq-speedline {
  position: absolute;
  left: 8%;
  top: calc(34% + var(--i, 0) * 15%);
  width: 3.2em;
  height: 0.28em;
  border-radius: 0.14em;
  background: var(--pq-speed-ink, currentColor);
  opacity: 0;
  transform-origin: 100% 50%;
}

/* Polaroid: weißer Rand mit breiterem Rand unten für die Unterschrift, Schatten (stageFx.js, polaroidFrame). */
.pq-polaroid {
  display: inline-flex;
  flex-direction: column;
  gap: 0.5em;
  margin: 0;
  padding: 0.7em 0.7em 0.5em;
  color: #16161d;
  background: #fff;
  border: 1px solid rgba(22, 22, 29, 0.14);
  border-radius: 0.2em;
  box-shadow: 0 0.35em 1.1em rgba(0, 0, 0, 0.32);
}
.pq-polaroid__photo {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  min-height: 1em;
}
.pq-polaroid figcaption {
  min-height: 1.3em;
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
  overflow-wrap: anywhere;
}

/* Reduzierte Bewegung und Schalter „Avatare und Animationen“ aus: keine Striche. Das Licht (JS: stageFx.js) setzt bei beiden den Endwert ohne animate(). */
@media (prefers-reduced-motion: reduce) {
  .pq-speedlines {
    display: none;
  }
}
.pq-figures-still .pq-speedlines {
  display: none;
}

/* ==========================================================================================================================
 * B1 Schnellste Person „Blitzstart“ (Task 3): moments/fastest.js
 * ======================================================================================================================== */

/* Die Striche hängen am äußeren figure (Host mit position: relative) und liegen links neben der Figur: sie ziehen beim Weg hinter ihr her. */
.qe-people-fastest .person-card .pq-figure {
  position: relative;
}
.qe-people-fastest .pq-figure > .pq-speedlines {
  inset: 0 100% 0 auto;
  width: 4.2em;
}
.qe-people-fastest .pq-figure > .pq-speedlines .pq-speedline {
  left: auto;
  right: 0.3em;
}

/* ==========================================================================================================================
 * B2 Ausgeschieden „Abgang mit Würde“ (Task 4): moments/leavers.js
 * ======================================================================================================================== */

/* Nach dem Live-Abgang bleibt die Figur ausgeblendet (`data-gone`, gesetzt von leavers.js); Name und Text der Karte stehen weiter, der Platz
   bleibt erhalten (kein Springen der übrigen Karten). Nach dem Neuladen gibt es kein `data-gone`: die Figur steht in Grundhaltung. */
.person-card .pq-figure[data-gone] {
  opacity: 0;
  visibility: hidden;
}

/* ==========================================================================================================================
 * B3 Buzzer und Auswahl „Rampenlicht“ (Task 5): buzzer.js, pick.js
 * ======================================================================================================================== */

/* Auftritt: Platz für Lichtkegel und Figur (moments/rampenlicht.js). Die Figur (ca. 24 × --pq-fk hoch) steht mittig am Boden des Platzes und
 * wächst beim Vortreten auf 135 % nach oben (transform-origin unten Mitte); der Platz lässt dafür oben Raum, das Licht (Hintergrund-Ebene,
 * hier etwas wärmer und kräftiger als in der Basis, damit es auch auf hellem Grund und auf der Teamfarbe zu sehen ist) füllt ihn und läuft
 * zum Rand hin aus. Die Figur hat ihre eigene Größe (--pq-fk, ein Teil von --pq-k des Umfelds), damit Name und Text daneben ihre Schriftgrößen behalten. */
.pq-turn {
  --pq-fk: 4px;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  width: calc(36 * var(--pq-fk));
  padding-top: calc(12 * var(--pq-fk));
  isolation: isolate;
}
.pq-stage .pq-turn {
  --pq-fk: calc(0.5 * var(--pq-k));
}
.pq-turn > .pq-spotlight {
  background: radial-gradient(closest-side at 50% 52%, rgba(255, 226, 130, 0.9) 0%, rgba(255, 226, 130, 0.45) 50%, rgba(255, 226, 130, 0) 100%);
}
.pq-turn > .pq-figure {
  --pq-k: var(--pq-fk);
  z-index: 1;
  transform-origin: 50% 100%;
}
/* Buzzer, Halter (Leinwand, Moderation): Die Figur steht links neben Name und Zeile (eine Spalte, so hoch wie der Text), der Halter wird
 * nicht höher als vor E6; sonst schrumpfen Frage und Antworten (die Fläche teilt sich die Höhe mit ihnen). */
.pq-buzz-holder:has(> .pq-turn) {
  grid-template-columns: auto auto;
  justify-content: center;
  align-items: center;
  column-gap: 0.6rem;
}
.pq-buzz-holder:has(> .pq-turn) > .pq-turn {
  grid-column: 1;
  grid-row: 1 / span 2;
  --pq-fk: 2.6px;
  padding-top: calc(8 * var(--pq-fk));
  width: calc(30 * var(--pq-fk));
}
.pq-buzz-holder:has(> .pq-turn) > :not(.pq-turn) {
  grid-column: 2;
}
.pq-stage .pq-stage-buzz--stage .pq-buzz-holder:has(> .pq-turn) {
  column-gap: calc(2 * var(--pq-k));
}
.pq-stage .pq-stage-buzz--stage .pq-buzz-holder > .pq-turn {
  --pq-fk: calc(0.4 * var(--pq-k));
}

/* Ergebnis (done, level_ended): die Figur klein links neben der Ergebniszeile, ohne eigenen Kasten und ohne die Zeile höher zu machen
 * (die Figur ragt beim Vortreten nach oben über ihren Platz hinaus, das Licht ist aus). */
.pq-buzz-resultrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
}
.pq-buzz-turnhost {
  position: relative;
  flex: none;
}
.pq-buzz-resultrow .pq-turn {
  --pq-fk: 2.6px;
  width: calc(26 * var(--pq-fk));
  padding-top: 0;
}
.pq-stage .pq-buzz-resultrow .pq-turn {
  --pq-fk: calc(0.28 * var(--pq-k));
}
.pq-stage .pq-stage-buzz--stage .pq-buzz-resultrow {
  gap: calc(1.4 * var(--pq-k));
}

/* Rebound: kurzer Auftritt der Person, die eben falsch lag, links neben der Zeile „… lag daneben“; er schwebt (absolut), nichts verschiebt sich. */
.pq-buzz-wrongrow {
  position: relative;
}
.pq-buzz-turnhost--float {
  position: absolute;
  right: 100%;
  top: 50%;
  margin-right: 0.6rem;
  translate: 0 -50%;
  pointer-events: none;
}
.pq-buzz-turnhost--float .pq-turn {
  --pq-fk: 2.6px;
  width: calc(30 * var(--pq-fk));
  padding-top: calc(6 * var(--pq-fk));
}
.pq-stage .pq-buzz-turnhost--float .pq-turn {
  --pq-fk: calc(0.4 * var(--pq-k));
}

/* Auswahl: Platz für die wählende Person in der oberen linken Ecke (das Licht fällt ins Leere daneben, nie auf die Karten); die Überschrift
 * hält Abstand zu beiden Seiten und bleibt mittig, ihre Zeile ist so hoch wie der Platz. */
.pq-pick.has-spot {
  position: relative;
}
.pq-pick-spot {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
}
.pq-pick--presenter .pq-turn {
  --pq-fk: 3px;
}
.pq-pick--presenter.has-spot > .pq-pick-title {
  display: grid;
  align-content: center;
  min-height: calc(30 * 3px);
  padding-inline: calc(36 * 3px);
}
.pq-pick--stage.has-spot > .pq-pick-title {
  display: grid;
  align-content: center;
  min-height: calc(18 * var(--pq-k));
  padding-inline: calc(18 * var(--pq-k));
}
.pq-pick--stage.pq-pick--wheel.has-spot > .pq-pick-title {
  display: block;
  min-height: 0;
  padding-inline: 0;
}

/* ==========================================================================================================================
 * B4 Rangliste „Auf- und Absteiger“ (Task 6): ranking.js
 * ======================================================================================================================== */

/* Rundenrangliste auf Bühne und Moderation mit Figuren (mountRanking figures: true): kleine Figur (Brustbild) statt des Kopfes, ▲/▼ neben der
 * Platzzahl. Größe der Figur über --pq-rk (auf der Bühne 0,25 × --pq-k der Bühne, so wächst und schrumpft sie mit Schrift und Abständen). */
.pq-ranking--figs {
  --pq-rk: 1.7px;
  --pq-up: #0b7a48;
  --pq-down: var(--danger, #b91c1c);
}
[data-theme="dark"] .pq-ranking--figs {
  --pq-up: #4ade80;
}
.pq-floor .pq-ranking--figs {
  --pq-rk: calc(0.25 * var(--pq-k));
}
.pq-ranking--figs .pq-figure--bust {
  --pq-k: var(--pq-rk);
  /* Das Kästchen der Figur endet bei den Hüften (Basis: negativer Rand und Beschnitt): so ragt es nie über die Zeile hinaus (kein Beschnitt der letzten Zeile am Rand der Bühne). */
  height: calc(15.8 * var(--pq-k));
  margin-bottom: 0;
  clip-path: inset(calc(-10 * var(--pq-k)) calc(-8 * var(--pq-k)) 0 calc(-8 * var(--pq-k)));
}
.pq-ranking.pq-ranking--figs .pq-ranking-row {
  grid-template-columns: 2.6em minmax(0, 1fr) auto auto;
  align-items: center;
}
.pq-ranking.pq-ranking--figs .pq-rank {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25em;
  white-space: nowrap;
}
/* Die Figur ragt bei Hüpfen und Jubeln über die Zeile (kein Beschnitt durch die Namenszelle); nur der Name kürzt mit Auslassung. */
.pq-ranking.pq-ranking--figs .pq-name-cell {
  display: flex;
  align-items: center;
  gap: 0.45em;
  overflow: visible;
  min-width: 0;
}
.pq-ranking--figs .pq-name-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pq-ranking--figs .pq-name-cell > .list-comic {
  flex: none;
  margin-right: 0;
}
/* Pfeil: Form (▲/▼) und Textersatz tragen die Bedeutung, die Farbe verstärkt sie nur. */
.pq-move {
  font-size: 0.78em;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
}
.pq-move--up {
  color: var(--pq-up, #0b7a48);
}
.pq-move--down {
  color: var(--pq-down, #b91c1c);
}
/* Textersatz auch ohne accessibility.css (Test-Harness): visuell versteckt. */
.pq-move .sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================================================================
 * B5 Endstand „Gruppenfoto“ (Task 7): celebration.js, finale.js
 * ======================================================================================================================== */

/* Ebene der Foto-Einstellung (celebration.js): liegt wie Podium, Großaufnahme und Endstand in derselben Zelle, sichtbar nur in dieser Einstellung. */
.pq-cel-photo {
  display: flex;
  align-items: center;
  justify-content: center;
}
.pq-celebration[data-shot="photo"] > .pq-cel-photo {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.6s ease, transform 0.9s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s;
}

/* Das Foto (moments/groupPhoto.js): Bild im Polaroid-Rahmen, Sieger in zwei Reihen (hinten die erste, die vordere steht versetzt davor),
 * Übrige klein links und rechts. Größe: --pq-ku ist die Einheit der Siegerfiguren (Figurenkasten 23 Einheiten breit, die Figur selbst nur
 * etwa 12; der Abstand der Mitten beträgt 16, so stehen sie dicht wie auf einem Gruppenbild); die Übrigen sind halb so groß. */
.pq-photo {
  --pq-u: min(1vh, 0.5625vw);
  --pq-ku: calc(var(--pq-u) * var(--pq-photo-scale, 1.1));
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  min-height: 0;
}
.pq-photo[data-size="s"] {
  --pq-photo-scale: 1.25;
}
.pq-photo[data-size="m"] {
  --pq-photo-scale: 1.15;
}
.pq-photo[data-size="l"] {
  --pq-photo-scale: 1;
}
.pq-photo__scene {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: calc(3 * var(--pq-ku));
  /* oben Platz für den Sprung und die Effekte des Jubels */
  padding: calc(4 * var(--pq-ku)) calc(2 * var(--pq-ku)) 0;
}
.pq-photo__rows {
  display: flex;
  flex-direction: column;
  align-items: center;
  --pq-k: var(--pq-ku);
}
.pq-photo__row {
  display: flex;
  justify-content: center;
  align-items: flex-end;
}
/* Der Kasten der Figur ist breiter als sie selbst (Platz für das Schild): negativer Rand rückt die Figuren zusammen. */
.pq-photo__row > .pq-figure,
.pq-photo__others > .pq-figure {
  margin-inline: calc(-3.5 * var(--pq-k));
}
/* Hintere Reihe zuerst; die vordere steht davor und verdeckt die Beine der hinteren ein Stück. Bei gleich vielen Figuren rückt sie um
 * einen halben Abstand zur Seite, so steht jede zwischen zwei Figuren der hinteren Reihe (groupPhoto.js setzt data-stagger). */
.pq-photo__row + .pq-photo__row {
  position: relative;
  z-index: 1;
  margin-top: calc(-16 * var(--pq-k));
}
.pq-photo__row[data-stagger] {
  padding-left: calc(16 * var(--pq-k));
}
.pq-photo__others {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-end;
  justify-content: center;
  --pq-k: calc(var(--pq-ku) * 0.55);
  /* höchstens zwei nebeneinander, die dritte steht davor */
  max-width: calc(2 * 16 * var(--pq-k) + 2 * var(--pq-k));
}
.pq-photo__others > .pq-figure:nth-child(3) {
  margin-top: calc(-12 * var(--pq-k));
}
.pq-photo__others:empty {
  display: none;
}

/* Rahmen: erscheint erst im Klick (data-frozen). Bis dahin liegt er unsichtbar an derselben Stelle, nichts rückt. Die weiße Fläche ist ein
 * eigenes Pseudoelement, damit nur `opacity` übergeht (die Figuren darin bleiben deckend). */
.pq-photo .pq-polaroid {
  position: relative;
  max-width: 100%;
  max-height: 100%;
  font-size: calc(3.4 * var(--pq-u));
  background: none;
  border-color: transparent;
  box-shadow: none;
}
.pq-photo .pq-polaroid::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #fff;
  border: 1px solid rgba(22, 22, 29, 0.14);
  border-radius: 0.2em;
  box-shadow: 0 0.35em 1.1em rgba(0, 0, 0, 0.32);
  opacity: 0;
  transition: opacity 0.3s ease-out;
}
.pq-photo[data-frozen] .pq-polaroid::before {
  opacity: 1;
}
.pq-photo .pq-polaroid > * {
  position: relative;
  z-index: 1;
}
.pq-photo .pq-polaroid__photo {
  align-items: stretch;
}
.pq-photo .pq-polaroid figcaption {
  opacity: 0;
  transition: opacity 0.3s ease-out;
}
.pq-photo[data-frozen] .pq-polaroid figcaption {
  opacity: 1;
}
/* Das Foto steht: auch das Atmen der Figuren (CSS) hält an. */
.pq-photo[data-frozen] .pq-figure,
.pq-photo[data-frozen] .pq-figure * {
  animation-play-state: paused !important;
}

/* Der Schleier des Klicks: weiße Fläche über der ganzen Leinwand (fest im Bild, kein sichtbarer Rand an der Ebene), nur `opacity`
 * (groupPhoto.js animiert sie genau einmal: 0 → 0,35 → 0 in 400 ms). */
.pq-photo-veil {
  position: fixed;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background: #fff;
  opacity: 0;
}

/* Handy (mobiles Pubquiz, `.mpq-cel` = 16:9-Feld): Der Schleier bleibt im Feld, die Unterschrift bleibt lesbar (mindestens 12 px), die Figuren sind
 * etwas kleiner, damit Bild und Unterschrift ins Feld passen. */
.mpq-cel .pq-photo-veil {
  position: absolute;
}
.mpq-cel .pq-photo .pq-polaroid {
  font-size: max(12px, calc(3.4 * var(--pq-u)));
}
.mpq-cel .pq-photo[data-size] {
  --pq-photo-scale: 0.9;
}

/* Konfetti läuft in der Foto-Einstellung aus: Teilchen des Stoßes bei Platz 1 segeln sonst sichtbar ins Foto hinein. Die Fläche blendet in
 * 0,6 s aus (wie die Ebenen), bei reduzierter Bewegung und Schalter aus sofort. */
.pq-cel-confetti {
  transition: opacity 0.6s ease;
}
.pq-celebration[data-shot="photo"] > .pq-cel-confetti {
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .pq-photo .pq-polaroid::before,
  .pq-photo .pq-polaroid figcaption,
  .pq-cel-confetti {
    transition: none;
  }
}
.pq-figures-still .pq-cel-confetti {
  transition: none;
}

/* Siegerfolie des Ausscheidungsquiz (finale.js): Die Figur ersetzt den runden Kopf-Ausschnitt (.has-figure nimmt ihm den Umriss), der
 * Rahmen der Sieger (Umriss in Erfolgsfarbe, wie vor E6 um das Kopfbild) liegt jetzt als abgerundetes Rechteck um die ganze Figur. */
.qe-finale-winners .person-card .person-photo.has-figure {
  box-sizing: border-box;
  padding: 0.25rem 0.5rem 0;
  border-radius: 18px;
  outline: 4px solid var(--timer-ok);
  outline-offset: 4px;
  /* Platz für den Rahmen vor dem Namen darunter */
  margin-bottom: 0.5rem;
}
/* Das Gruppenfoto folgt unter den Siegerkarten, kleiner als auf der Pubquiz-Leinwand. */
.qe-finale > .pq-photo,
.qe-finale > .pq-photo[data-size] {
  --pq-photo-scale: 0.45;
  width: auto;
  height: auto;
  margin-top: 8px;
}
.qe-finale > .pq-photo .pq-polaroid {
  font-size: calc(2.2 * var(--pq-u));
}
